Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CSS Injection crash XS-Leak #177

Merged
merged 1 commit into from
Feb 1, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions content/docs/attacks/css-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,24 @@ Some HTML tags that are normally hidden such as style and script can be rendered
Larger text dimensions can result in the scroll bar being shown,
This scroll bar can have a custom style such as `background: url()` so that it makes a request to an attacker-controlled server when shown. [^3]

If loading external images for exfiltration is disallowed by a CSP img-src directive, you may still be able to use font URLs if they are not blocked by font-src, connect-src or default-src directives. You must first define a `@font-face { font-family: a; src: url(...) }`, and then reference it in a selector like `input[value^="a"] { font-family: a }`. This works because the font will only be loaded if it is required by some element on the page.

If no external requests can be made at all due to a strict CSP, it is still possible to use an XS-Leak based on browser crashing. At the time of writing, Chromium crashes when trying to render the `background: linear-gradient(in display-p3, red, blue)` property [^4]. Using CSS selectors this can be done conditionally.
Because of [Full Site Isolation](https://chromium.googlesource.com/chromium/src/+/main/docs/process_model_and_site_isolation.md#Full-Site-Isolation-site_per_process), if one page of a site crashes, all other active frames of that site crash too. This is detectable by creating a dummy iframe on the attacker's page of the same site with any path, and measuring `onload=` events. By then conditionally crashing CSS in another iframe or popup window, you can detect the result of a single CSS selector by the dummy iframe crashing with it. Doing this repeatedly allows reading larger strings. [^5]

This last attack is often not fully mitigated by Framing Protections because any page on the same site with a `%00` error or a too long URI can serve as the dummy frame, which may be missing the regular response headers. The alternative becomes using popup windows, and only if the COOP protection is active will it be fully mitigated.

## Defense
- Put attacker controlled content in its own document this can be done using a iframe with the srcdoc attribute.
Optionally include the sandbox attribute to isolate the content into its own origin.
- Use a CSS inliner so global styles get converted.

| [SameSite Cookies (Lax)]({{< ref "/docs/defenses/opt-in/same-site-cookies.md" >}}) | [COOP]({{< ref "/docs/defenses/opt-in/coop.md" >}}) | [Framing Protections]({{< ref "/docs/defenses/opt-in/xfo.md" >}}) | [Isolation Policies]({{< ref "/docs/defenses/isolation-policies" >}}) |
| :--------------------------------------------------------------------------------: | :-------------------------------------------------: | :---------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------: |
| ❌ | ❌ | ❌ | |
| [SameSite Cookies (Lax)]({{< ref "/docs/defenses/opt-in/same-site-cookies.md" >}}) | [COOP]({{< ref "/docs/defenses/opt-in/coop.md" >}}) | [Framing Protections]({{< ref "/docs/defenses/opt-in/xfo.md" >}}) | [Isolation Policies]({{< ref "/docs/defenses/isolation-policies" >}}) |
| :--------------------------------------------------------------------------------: | :-------------------------------------------------: | :---------------------------------------------------------------: | :-------------------------------------------------------------------: |
| ❌ | ❌ | ❌ | |
## References
[^1]: CSS Injection Primitives, [link](https://x-c3ll.github.io/posts/CSS-Injection-Primitives/)
[^2]: HTTPLeaks, [link](https://github.com/cure53/HTTPLeaks/)
[^3]: Font ligatures, [link](https://sekurak.pl/wykradanie-danych-w-swietnym-stylu-czyli-jak-wykorzystac-css-y-do-atakow-na-webaplikacje/)
[^3]: Font ligatures, [link](https://research.securitum.com/stealing-data-in-great-style-how-to-use-css-to-attack-web-application/)
[^4]: Chrome tab crashes when using gradients in display-p3, rec2020, prophoto-rgb or a98-rgb, [link](https://issues.chromium.org/issues/382086298)
[^5]: x3CTF - blogdog, [link](https://jorianwoltjer.com/blog/p/ctf/x3ctf-blogdog-new-css-injection-xs-leak#xs-leak-using-process-crashing)