GitBook: [#3345] No subject

This commit is contained in:
CPol 2022-08-02 15:24:35 +00:00 committed by gitbook-bot
parent 729535edba
commit f47d1628b5
No known key found for this signature in database
GPG key ID: 07D2180C7B12D0FF

View file

@ -1,5 +1,7 @@
# Iframes in XSS, CSP and SOP
## Iframes in XSS, CSP and SOP
<details>
<summary><strong>Support HackTricks and get benefits!</strong></summary>
@ -16,8 +18,7 @@ Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
</details>
# Iframes in XSS
## Iframes in XSS
There are 3 ways to indicate the content of an iframed page:
@ -61,7 +62,7 @@ alert(parent.secret)
If you access the previous html via a http server (like `python3 -m http.server`) you will notice that all the scripts will be executed (as there is no CSP preventing it)., **the parent wont be able to access the `secret` var inside any iframe** and **only the iframes if2 & if3 (which are considered to be same-site) can access the secret** in the original window.\
Note how if4 is considered to have `null` origin.
## Iframes with CSP <a href="#iframes_with_csp_40" id="iframes_with_csp_40"></a>
### Iframes with CSP <a href="#iframes_with_csp_40" id="iframes_with_csp_40"></a>
{% hint style="info" %}
Please, note how in the following bypasses the response to the iframed page doesn't contain any CSP header that prevents JS execution.
@ -115,7 +116,7 @@ if __name__ == "__main__":
app.run()
```
## Other Payloads found on the wild <a href="#other_payloads_found_on_the_wild_64" id="other_payloads_found_on_the_wild_64"></a>
### Other Payloads found on the wild <a href="#other_payloads_found_on_the_wild_64" id="other_payloads_found_on_the_wild_64"></a>
```html
<!-- This one requires the data: scheme to be allowed -->
@ -126,7 +127,7 @@ if __name__ == "__main__":
<iframe src='data:text/html,<script defer="true" src="data:text/javascript,document.body.innerText=/hello/"></script>'></iframe>
```
## Iframe sandbox
### Iframe sandbox
The `sandbox` attribute enables an extra set of restrictions for the content in the iframe. **By default, no restriction is applied.**
@ -147,9 +148,9 @@ The value of the `sandbox` attribute can either be empty (then all restrictions
<iframe src="demo_iframe_sandbox.htm" sandbox></iframe>
```
# Iframes in SOP
## Iframes in SOP
In this [**challenge**](https://github.com/terjanq/same-origin-xss) created by [**NDevTK**](https://github.com/NDevTK) and [**Terjanq**](https://github.com/terjanq) **** you need you need to exploit a XSS in the coded
In this [**challenge**](https://github.com/terjanq/same-origin-xss) created by [**NDevTK**](https://github.com/NDevTK) and [**Terjanq**](https://github.com/terjanq) you need you need to exploit a XSS in the coded
```javascript
const identifier = '4a600cd2d4f9aa1cfb5aa786';
@ -164,19 +165,19 @@ onmessage = e => {
The main problem is that the [**main page**](https://so-xss.terjanq.me) uses DomPurify to send the `data.body`, so in order to send your own html data to that code you need to **bypass** `e.origin !== window.origin`.
## SOP bypass 1
### SOP bypass 1
When `//example.org` is embeded into a **sandboxed iframe**, then the page's **origin** will be **`null`**, i.e. `window.origin === 'null'`. So just by embedding the iframe via `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">` we could force the `null` origin.
When `//example.org` is embedded into a **sandboxed iframe**, then the page's **origin** will be **`null`**, i.e. `window.origin === 'null'`. So just by embedding the iframe via `<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">` we could **force the `null` origin**.
If the page was **embeddable** you could bypass that protection that way (cookies might also need to be set to `SameSite=None`).
## SOP bypass 2
### SOP bypass 2
The lesser known fact is that when the **sandbox value `allow-popups` is set** then the **opened popup** will **inherit** all the **sandboxed attributes** unless `allow-popups-to-escape-sandbox` is set.
## Challenge Solution
### Challenge Solution
Therefore, for this challenge, one could **create** an **iframe**, **open a popup** to the page with the vulnerable XSS code handler (`/iframe.php`), as `window.origin === e.origin` because both are `null` it's possible to **send a payload that will exploit the XSS**.
Therefore, for this challenge, one could **create** an **iframe**, **open a popup** to the page with the vulnerable XSS code handler (`/iframe.php`), as `window.origin === e.origin` because both are `null` it's possible to **send a payload that will exploit the XSS**.
That **payload** will get the **identifier** and send a **XSS** it **back to the top page** (the page that open the popup), **which** will **change location** to the **vulnerable** `/iframe.php`. Because the identifier is known, it doesn't matter that the condition `window.origin === e.origin` is not satisfied (remember, the origin is the **popup** from the iframe which has **origin** **`null`**) because `data.identifier === identifier`. Then, the **XSS will trigger again**, this time in the correct origin.
@ -215,6 +216,37 @@ That **payload** will get the **identifier** and send a **XSS** it **back to the
</body>
```
## Winning RCs with Iframes
According to this [**Terjanq writeup**](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710) blob documents created from null origins are isolated for security benefits, which means that if you maintain occupy the main page, the iframe page is going to be executed.
Basically in that challenge an **isolated iframe is executed** and right **after** it's **loaded** the **parent** page is going to **send a post** message with the **flag**.\
However, that postmessage communication is **vulnerable to XSS** (the **iframe** can execute JS code).
Therefore, the goal of the attacker is to **let the parent create the iframe**, but **before** let the **parent** page **send** the sensitive data (**flag**) **keep it busy** and send the **payload to the iframe**. While the **parent is busy** the **iframe executes the payload** which will be some JS that will listen for the **parent postmessage message and leak the flag**.\
Finally, the iframe has executed the payload and the parent page stops being busy, so it sends the flag and the payload leaks it.
But how could you make the parent be **busy right after it generated the iframe and just while it's waiting for the iframe to be ready to send the sensitive data?** Basically, you need to find **async** **action** you could make the parent **execute**. For example, in that challenge the parent was **listening** to **postmessages** like this:
```javascript
window.addEventListener('message', (e) => {
if (e.data == 'blob loaded') {
$("#previewModal").modal();
}
});
```
so it was possible to send a **big integer in a postmessage** that will be **converted to string** in that comparison, which will take some time:
```bash
const buffer = new Uint8Array(1e7);
win?.postMessage(buffer, '*', [buffer.buffer]);
```
And in order to be precise and **send** that **postmessage** just **after** the **iframe** is created but **before** it's **ready** to receive the data from the parent, you will need to **play with the miliseconds of a `setTimeout`**.
<details>
<summary><strong>Support HackTricks and get benefits!</strong></summary>