![Подарить 8 млн агрегаторам или побаловать себя и свой бизнес, а на сдачу купить новый авто?](/upload/resize_cache/iblock/8dd/pjo1qaod4hjelbudrrbzzf0tmo7nicol/396_262_2619711fa078991f0a23d032687646b21/1920-kh-1080.jpg)
Привет, меня зовут Дмитрий Крылатков, работаю QA-инженером в компании Doubletapp. Я всегда был заинтересован темой тестирования на безопасность, участвую в bug-bounty программах, а также поднимаю осведомленность о существующих уязвимостях среди команд тестирования и разработки. В статье расскажу, как QA может сэкономить ресурсы компании и обеспечить проверку на наличие основных уязвимостей, на что обращать внимание и почему это полезно как для специалиста, так и для бизнеса.
Команда тестирования в первую очередь фокусируется на функциональных требованиях к продукту — проверяет, работает ли приложение в соответствии с ожидаемым результатом, проводит регрессы, разбирается с требованиями и макетами — в общем, обеспечивает качество продукта на всех стадиях. При этом почти всегда QA не отвечает за безопасность продукта — для этого требуются отдельно обученные специалисты, которые умеют искать уязвимости, и как правило этот вид тестирования опускается. Почему это может быть плохо?
Исходя из опыта, я считаю, что стоимость пропущенного бага гораздо ниже, чем уязвимости. Существует много инструментов, которые позволяют локализовывать и хотфиксить баги — регресс, мониторинги или элементарное обращение пользователя в саппорт, если у него что-то перестало работать.
При этом не найденная вовремя уязвимость может долго эксплуатироваться без нашего ведома, угрожая репутации продукта и издержками для бизнеса, — и ни пользователи, ни QA об этом могут не узнать. Получается, что цель QA в обеспечении качества продукта на всех этапах не достигается полностью, ответственность переходит к отделу безопасности, которого в компании может не быть, к тому же безопасники — такие же люди, могут что-то пропустить. Таким образом, для бизнеса стоимость пропущенной уязвимости многократно увеличивается.
Наша задача как QA — не допустить подобных издержек и повысить качество продукта дополнительными проверками на безопасность. В случае, если мы сможем находить проблемы безопасности еще на этапе функционального тестирования, это сократит часы безопасников и предотвратит траты на bug-bounty программу, если всё это есть в компании.
Если же отдела безопасности нет, навыки QA в тестировании на безопасность сделают из вас особенно ценного специалиста.
Мне нравится формулировка, которая описывает оба понятия почти одинаковыми терминами. Баг — невыполнение ожидаемого поведения программы; уязвимость — выполнение неожидаемого поведения. С помощью некоторых дополнительных действий злоумышленник может выполнить сценарий, который не закладывался требованиями к продукту, извлечь информацию, совершить действия от лица пользователя, скомпрометировать сохранность данных, обойти механизмы защиты и многое другое — всё, что выходит за рамки ожидаемого поведения и имеет злонамеренный характер.
Еще одним различием является то, что баги всегда уникальны. Если мы нашли баг в одном приложении, то это абсолютно не гарантирует того, что подобные шаги воспроизведения вызовут аналогичный баг в другом приложении — это, опять же, рождается из уникальных требований к продукту и способов реализации. Уязвимости в этом плане более классифицированы и, зная паттерн поиска конкретной уязвимости, мы можем её искать в абсолютно любом веб-приложении без опоры на требования к продукту. Ярким примером будут всем известные XSS, которые могут быть найдены силами QA в рамках функционального тестирования мест приложения с пользовательским вводом.
Я подготовил список уязвимостей, которые относительно просты в освоении, но при этом повсеместно встречаются в веб-приложениях. Освоив методологию их поиска, тестировщик сможет покрывать основные кейсы, связанные с безопасностью клиентской части приложений. Также не стоит беспокоиться о том, что вы что-то сломаете, поскольку данные уязвимости направлены на пользователей. Лишь бы они были тестовыми!
Список уязвимостей:
В качестве технического примера из этого списка я выбрал IDOR-уязвимость. Расшифровывается IDOR как Insecure Direct Object Reference, то есть небезопасная прямая ссылка на объект. IDOR-уязвимость — одна из наиболее часто встречающихся проблем авторизации, которая может привести к критичным проблемам безопасности. Возникают IDOR’ы, когда приложение обеспечивает доступ к объектам на основе введенных пользователем данных. Я уверен, что в компетенциях QA делать проверки этой уязвимости, поэтому давайте разберемся подробнее, как её искать.
В первых двух буквах названия кроется то, на что мы обращаем внимание при тестировании на IDORы, это ID — любые идентификаторы объектов в HTTP-запросах.
Самый простой пример — это когда у пользователя в браузере отображается ссылка по типу https://example.com/profile/passport/123, где последние три цифры являются ID паспорта пользователя. В случае, если пользователь захочет поменять ID паспорта, к примеру, на 122 и на это действие не будет никакой валидации, он откроет страничку чужого паспорта и получит информацию, которая в рамках его сессии ему доступна быть не должна.
Что мы вообще можем получить с помощью манипуляций с ID? В первую очередь, это неавторизованный доступ к чувствительной информации. По аналогии с предыдущим примером с паспортом, с помощью ID мы можем доставать разные объекты, принадлежащие другим пользователям, — и это далеко не обязательно должна быть личная информация и паспортные данные. Любая информация, которая не должна быть доступна в рамках определенной сессии и роли в приложении, уже будет считаться валидной находкой, если мы смогли её найти через манипуляцию с ID какого-либо чужого объекта.
При тестировании отталкивайтесь от логики авторизации, а не от субъективного восприятия критичности информации, которую вы нашли, — для бизнеса, возможно, подобные находки будут важными.
Во-вторых, получив неавторизованный доступ к объекту, мы можем модифицировать чужие данные. Примером будет служить запрос по типу DELETE /api/users/550123, который потенциально может удалить всех пользователей в приложении.
Кроме этого, могут быть примеры повышения привилегий, если мы сможем атаковать роль выше по иерархии, получая доступ к запросам и объектам, к примеру, юзера-админа. С помощью раскрытия информации мы можем и дальше повышать импакт IDOR-уязвимости, если, например, с помощью неё раскроется объект, в котором хранятся какие-то логины и пароли. На своей практике я находил IDOR, который привел к захвату нескольких аккаунтов.
В-третьих, мы можем рассмотреть прямой доступ к файлам. Файлы также уязвимы к IDOR’ам, поэтому если вы встретите URL по типу https://example.com/passports/123.pdf, очень важно проверить, что «паспорта» с другими ID мы не можем видеть и доставать, — только если это не предусмотрено правами текущей сессии.
Говоря о методологии поиска, мы можем выделить несколько подходов. Прежде всего, это, конечно, изменение самих ID в запросе. Не забываем, что идентификатор может присуждаться любому объекту, поэтому всегда проверяем весь запрос, включая его тело, а не только query-параметры. Запрос может содержать несколько ID в разных комбинациях — пробуем менять любые из них и смотреть, как на это отреагирует бэкенд. Безусловно, прежде чем это делать, нужно разобраться с логикой авторизации приложения — что эти объекты возвращают и в какой роли.
Можно выделить разные манипуляции с параметрами. Один из методов атак — HTTP Parameter Pollution, который заключается в разделении одинакового параметра на несколько сущностей. В примере ниже через амперсанд мы подставили еще один параметр user_id и записали в него ID другого пользователя.
GET /api_v1/messages?user_id=YOUR_USER_ID&user_id=ANOTHER_USER_ID
Аналогичным образом мы можем попробовать поменять query-параметры местами
GET /api_v1/messages?user_id=ANOTHER_USER_ID&user_id=YOUR_USER_ID
IDOR’ы могут встречаться в массивах — например когда принимается массив идентификаторов, объекты которых доступны определенным пользователям.
{“users”: [“user_1”: “123”, “user_2”: “124”]}
В данном случае мы можем «расширить» массив, подставив ID пользователя, которого не должно быть в рамках логики авторизации, или использовать привычные методы изменения ID в уже существующих параметрах
{“users”: [“user_1”: “123”, “user_2”: “124”, “user_5”: ”999”]}
Редко, но метко могут выстреливать и не ID вовсе. В запросе ниже идентификация объекта происходит по юзернейму, который, однако, не выглядит привычным. Для примера, юзернейм здесь закодирован в base64 и после декодинга мы можем увидеть юзернейм super_admin.
GET/user/c3VwZXJfYWRtaW4=/data → GET /user/super_admin/data
Юзернеймы чаще всего являются публичной информацией, поэтому это наталкивает на мысль, что стоит попробовать закодировать их в нужную для запроса кодировку и попытаться вставлять в запрос. Всегда нужно обращать внимание на то, как реализован доступ к тем или иным объектам в приложении, и не всегда это могут быть ID.
Ещё пара моментов, которые не стоит забывать. В случае, если вы тестируете запрос на IDOR-уязвимость и вам возвращается 403 или же неправомерные действия корректно валидируются другими ошибками, попробуйте добавить слэш
GET private/users/89934 → GET private/users/89934/
Возможно, именно этот слэш позволит вам выбраться из регулярки, по которой происходит валидация, и вернёт вам чужой объект. Пробуйте также использовать URL-encoded символы, такие как %20:
GET private/users/89934%20
Мы можем проверять доступ к запросам и объектам через смену авторизации запроса. В случае, если у нас есть несколько ролей, мы можем сделать запрос за админа (или любую роль выше), поменять сессию на роль ниже и сделать запрос. Если нам вернулось то же самое, что было при запросе от админа и стали доступны его объекты, это равнозначно IDOR’у, т.к. является частью недостаточной авторизации объектов.
Несколько завершающих советов по данной уязвимости:
Я прошелся только по основным методологиям и паттернам поиска. Для более детального закрепления информации об этой и других уязвимостях я рекомендую ресурс portswigger. Здесь очень лаконично и удобно описаны уязвимости, в том числе те, которые я предложил изучить на старте. Читаем описание там, пробуем решать лабы для закрепления (ничего страшного, если не будет получаться, — решения всегда есть в интернете). Информации из этого источника должно быть достаточно, чтобы у вас сложилось понимание, что представляют собой те или иные уязвимости и как мы их можем находить в рамках функционального тестирования.
Одним из лучших источников является чтение публичных отчетов о найденных уязвимостях, например, на Hackerone. Очень помогает понять логику и использованные пейлоады.
В качестве софта, конечно, можно использовать привычные Fiddler или Postman, но это будет менее удобно, чем инструмент, специально разработанный для специалистов по безопасности. Я говорю о Burp Suite — отладочной прокси, которая среди QA пользуется меньшей популярностью, хотя и для функционального API-тестирования хорошо подходит. С помощью Burp Suite вы сможете перехватывать трафик, использовать удобный интерфейс для анализа и изменения HTTP-запросов, интерспетить запросы и ответы, брутфорсить, декодировать, запускать встроенные сканеры и многие другие полезности, которые пригодятся при тестировании.
Также Burp поддерживает различные плагины от комьюнити, которые могут облегчить поиски уязвимостей, например, Authmatrix для тестирования на IDOR’ы.
Community Edition бесплатна и покрывает основной нужный функционал, поэтому советую её попробовать даже для обычного функционального тестирования в качестве прокси.
Область применения довольно широка. Вы можете:
И самое важное, отвечая на вопрос «Какое же место QA в тестировании продукта на безопасность?», можно взглянуть на продукт не только со стороны функциональности и юзабилити, но и с критической оценкой — насколько ваш продукт защищен от различных уязвимостей.
Тестирование на безопасность точно может быть частью компетенций QA: с появлением новых навыков вы сможете делать дополнительные проверки на своих продуктах, покрывать ранее неизвестные кейсы и стараться внедрять новые подходы и практики, что положительно скажется на качестве продукта. Как QA в дальнейшем вы сможете влиять на продукт со стороны лучших security-практик еще на этапе создания/тестирования требований. Ну и конечно, будучи специалистом более широкого формата, вы можете делиться знаниями не только с другими тестировщиками, но и с командой разработки.
Поэтому давайте делать наши продукты не только качественными, но и чуть более безопасными!
Также по теме тестирования смотрите лекции на YouTube-канале Doubletapp: