Охота за багами – это смесь как технических навыков, так и упорства с любопытством. Иногда самые простые баги остаются незамеченными из-за простых предположений. Эта история не о каком-то революционном эксплойте; она о терпении и о том, почему всегда стоит доводить дело до конца.
Цель: Простой вход с использованием OTP
Цель, которую я тестировал — назовем её redacted.com, — была хорошо проработана и прошла множество проверок. Вот как работало приложение:
Пользователи входили в систему, используя адрес электронной почты.
На их почту отправлялся одноразовый 6-значный код (OTP).
Этот код вводился для доступа к аккаунту — никаких паролей.
Механизм был достаточно простым, что делало его идеальным для тестирования уязвимостей OTP, связанных с перебором.
Начало тестирования
Как и каждый исследователь уязвимостей, я открыл Burp Suite, перехватил запрос на получение OTP и отправил его в Intruder для перебора.
При 6-значном коде возможно до 1,000,000 комбинаций (от 000000 до 999999).
Сначала все выглядело нормально. Сервер возвращал статус 200 OK для неверных OTP, что говорило о корректной обработке запросов.
Преграда: Код состояния 401
После 20 попыток ответ сервера изменился. Я начал получать ответ «401 Unauthorized» для всех последующих попыток ввода OTP.
В такой ситуации большинство исследователей уязвимостей останавливаются. Легко предположить, что система внедрила механизм лимита запросов или блокировки. Даже эксперты часто делают такие предположения.
Но я не стал опускать руки. У меня вошло в привычку запускать Intruder до тех пор, пока он либо не завершит весь диапазон, либо не найдет действительный OTP. Любопытство побуждало меня дальше проверять, как же сервер обработает правильный OTP, даже если постоянно приходит ответ 401 или 429.
Проверка: Доказательство бага
На первом этапе специалисты целевого приложения сомневались в серьезности проблемы, предполагая, что она защищена механизмом ограничения запросов. Однако они попросил меня захватить предоставленный ими аккаунт (takeover) для демонстрации
Успех: спустя 2 часа
Я продолжил работу Intruder'а. Это было настоящее испытание для моего терпения — запрос за запросом, и всё, что я видел, это ответы «401 Unauthorized».
После почти 200,000 запросов и двух часов, произошло нечто невероятное. Среди массы ответов 401 я заметил код состояния 200 OK.
Когда я проверил ответ, я обнаружил, что он содержал «access token» — ключ доступа к аккаунту. Как оказалось, на сервере не было механизма ограничения частоты запросов; он просто возвращал 401 для неверных OTP. Однако верное OTP всё же обходило эту «псевдозащиту».
В итоге, я получил вознаграждение в $2,200 за обнаружение этой уязвимости.
Урок: Почему большинство охотников за багами не находят эту уязвимость
Эта уязвимость не была технически сложной. Она была весьма простой — её мог бы найти кто угодно. Но что помогло мне в отличие от других, так это настойчивость.
Вот почему большинство охотников за багами пропускают такие уязвимости:
Они видят ответы 401 Unauthorized или 429 и предполагают, что система реализовала эффективное ограничение частоты запросов. Дайте запросу дойти до верного OTP и посмотрите, как система на это отреагирует.
Они останавливают Intruder до завершения списка.
Им не хватает терпения, чтобы дождаться завершения грубого перебора.
Почему настойчивость имеет значение
Этот опыт преподал мне важный урок: не делайте преждевременных выводов, пока всё не проверено. Такие уязвимости скрываются за догадками, и только тот, кто готов преодолеть такие трудности, находит настоящие сокровища.
Охота за багами — это не всегда про продвинутые навыки, это ещё про упорство и настойчивость. Поэтому в следующий раз, когда вы получите 401/429 или столкнётесь с кажущимся тупиком, вспомните эту историю. Дайте тесту завершиться, доведите дело до конца и оставайтесь любопытным.
Удачной охоты! Пусть ваше терпение принесёт вам щедрые награды!
Комментарии (5)
c0r3dump
23.12.2024 22:15А почему вначале сервер возвращал 200, а потом стал 40х? Срока действия у ОТР не было тоже? А то долго перебирать - протухнет.
Fox_exe
23.12.2024 22:15Сначала возвращался JSON (с кодом 200) и текстом ошибки для показа её в интерфейсе пользователю. А потом сработала защита от ботов. Ботам интерфейс показывать незачем, вот и возвращался текстовой HTTP/401.
Ну или "защиту" писал другой человек, руководствуясь чуть другой логикой (а вернее - привычкой).
HEXFFFFFFFF
Хм. Помоему сумма неадекватно мала. Эта сумма хороша для школьника которому повезло. Но для проффесионала котрый по настоящему умеет искать уязвимости это несерьезная сумма.
cupraer
А запустить стороннюю утилиту и ждать, тупо пялясь в экран — это профессионализм, или третий класс церковно-приходской школы, как по-вашему?