* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
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 won’t 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.\
Therefore, it’s possible to **bypass a CSP if you can upload a JS file to the server and load it via iframe even with `script-src 'none'`**. This can **potentially be also done abusing a same-site JSONP endpoint**.
You can test this with the following scenario were a cookie is stolen even with `script-src 'none'`. Just run the application and access it with your browser:
<!-- sometimes it can be achieved using defer& async attributes of script within iframe (most of the time in new browser due to SOP it fails but who knows when you are lucky?)-->
The `sandbox` attribute enables an extra set of restrictions for the content in the iframe. **By default, no restriction is applied.**
When the `sandbox` attribute is present, and it will:
* treat the content as being from a unique origin
* block form submission
* block script execution
* disable APIs
* prevent links from targeting other browsing contexts
* prevent content from using plugins (through `<embed>`, `<object>`, `<applet>`, or other)
* prevent the content to navigate its top-level browsing context
* block automatically triggered features (such as automatically playing a video or automatically focusing a form control)
The value of the `sandbox` attribute can either be empty (then all restrictions are applied), or a space-separated list of pre-defined values that will REMOVE the particular restrictions.
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
if (e.origin !== window.origin && data.identifier !== identifier) return;
if (data.type === 'render') {
renderContainer.innerHTML = data.body;
}
}
```
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`.
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**.
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.
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.
In the [**solution**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc/solution) for this [**challenge**](https://github.com/project-sekai-ctf/sekaictf-2022/tree/main/web/obligatory-calc)**,** [**@Strellic\_**](https://twitter.com/Strellic\_) proposes a similar method to the previous section. Let's check it.
In this challenge the attacker needs to **bypass** this:
```javascript
if (e.source == window.calc.contentWindow && e.data.token == window.token) {
```
If he does, he can send a **postmessage** with HTML content that is going to be written in the page with **`innerHTML`** without sanitation (**XSS**).
The way to bypass the **first check** is by making `window.calc.contentWindow` to `undefined` and `e.source` to `null`:
* **`window.calc.contentWindow`** is actually **`document.getElementById("calc")`**. You can clobber **`document.getElementById`** with **`<img name=getElementById />`** (note that Sanitizer API -[here](https://wicg.github.io/sanitizer-api/#dom-clobbering)- is not configured to protect against DOM clobbering attacks in its default state).
* Therefore, you can clobber **`document.getElementById("calc")`** with **`<img name=getElementById /><div id=calc></div>`**. Then, **`window.calc`** will be **`undefined`**.
* Now, we need **`e.source`** to be **`undefined`** or **`null`** (because `==` is used instead of `===`, **`null == undefined`** is **`True`**). Getting this is "easy". If you create an **iframe** and **send** a **postMessage** from it and immediately **remove** the iframe, **`e.origin`** is going to be **`null`**. Check the following code
In order to bypass the **second check** about token is by sending **`token`** with value `null` and making **`window.token`** value **`undefined`**:
* Sending `token` in the postMessage with value `null` is trivial.
* **`window.token`** in calling the function **`getCookie`** which uses **`document.cookie`**. Note that any access to **`document.cookie`** in **`null`** origin pages tigger an **error**. This will make **`window.token`** have **`undefined`** value.
The final solution by [**@terjanq**](https://twitter.com/terjanq) is the [**following**](https://gist.github.com/terjanq/0bc49a8ef52b0e896fca1ceb6ca6b00e#file-calc-html):
```html
<html>
<body>
<script>
// Abuse "expr" param to cause a HTML injection and
// clobber document.getElementById and make window.calc.contentWindow undefined
According to [**this writeup**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/), if you can iframe a webpage without X-Frame-Header that contains another iframe, you can **change the location of that child iframe**.\
This is specially useful in **postMessages** because if the parent page is sending sensitive data using a **wildcard** like `windowRef.postmessage("","*")` it's possible to **change the location of the iframe to an attacker controlled location** and steal that data.
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 busy 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`**.
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**