From 6f80ddf78ed26475c8d5cd17cce34d21f8559fff Mon Sep 17 00:00:00 2001 From: GangGreenTemperTatum <104169244+GangGreenTemperTatum@users.noreply.github.com> Date: Wed, 12 Aug 2026 11:46:38 -0400 Subject: [PATCH] Add response-queue-poisoning skill to web-security Port the response-queue-poisoning skill into the web-security capability. Covers CRLF-powered desync attacks: escalating HTTP header injection to response queue poisoning and request tunnelling. Chains with existing crlf-response-splitting, web-cache-deception-path, parser-differential-bypass, self-xss-escalation, and 403-bypass skills. --- .../skills/response-queue-poisoning/SKILL.md | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 capabilities/web-security/skills/response-queue-poisoning/SKILL.md diff --git a/capabilities/web-security/skills/response-queue-poisoning/SKILL.md b/capabilities/web-security/skills/response-queue-poisoning/SKILL.md new file mode 100644 index 0000000..908c996 --- /dev/null +++ b/capabilities/web-security/skills/response-queue-poisoning/SKILL.md @@ -0,0 +1,144 @@ +--- +name: response-queue-poisoning +description: Escalate HTTP header injection (CRLF in URL path or parameters) to critical impact via response queue poisoning and request tunnelling — smuggle requests through persistent connections to capture victim responses or bypass proxy ACLs. Use when CRLF injection exists in request headers/path and front-end maintains persistent backend connections. +--- + +# CRLF-Powered Desync Attacks + +Inject `%0d%0a` in URL paths or parameters to smuggle complete HTTP requests through persistent connections. Two exploitation modes: + +- **Response queue poisoning** — proxy reuses connections across users: smuggled request offsets the response queue, attacker receives victim's response +- **Request tunnelling** — proxy does NOT reuse connections: smuggled request bypasses proxy-layer ACLs to reach blocked endpoints directly + +## When to Use + +- CRLF injection confirmed (or suspected) in URL path, query parameter, or request header +- Front-end proxy + back-end with persistent upstream connections +- Standard CL.TE/TE.CL/TE.0 smuggling failed — this needs no Content-Length/Transfer-Encoding disagreement +- `crlf-response-splitting` already considered (that skill targets CSP bypass XSS via response headers; this targets request pipeline desync) + +## Phase 1: Detect CRLF Injection — Differential Probing + +The core method: inject a header via CRLF in the URL path, then compare responses when using the **real header name** vs a **typo'd control**. If the back-end processes real headers differently than garbage, the status code differential proves CRLF injection reached the parser. + +### The Pattern + +Every probe follows this structure: +``` +GET /%20HTTP%2f1.1%0d%0a%3A%20%0d%0aX%3A%20x HTTP/1.1 +Host: target.com +``` + +The `/%20HTTP%2f1.1` terminates the injected request line. Everything after `%0d%0a` is parsed as headers by the back-end. The front-end sees it as a single URL path. + +Send the request twice — once with the real header name, once with a single-character typo. Different response = injection confirmed. + +### Worked Example: Range Header + +**Control (typo'd):** +```http +GET /%20HTTP%2F1.1%0D%0ARxnge%3A%20bytes=1-%0D%0AX:%20x HTTP/1.1 +Host: target.com +``` +→ Returns `200 OK` (back-end ignores `Rxnge`) + +**Test (real):** +```http +GET /%20HTTP%2F1.1%0D%0ARange%3A%20bytes=1-%0D%0AX:%20x HTTP/1.1 +Host: target.com +``` +→ Returns `206 Partial Content` (back-end processed `Range`) + +**Status code differential (200 vs 206) = CRLF injection confirmed.** + +### Probe Reference + +| Header | Typo | Value | Expected Differential | +|--------|------|-------|-----------------------| +| `Range` | `Rxnge` | `bytes=1-` | 200 vs **206** | +| `If-Match` | `Ix-Match` | `notright` | 200 vs **412** | +| `Expect` | `Exqect` | `100-continue` | 200 vs **100 Continue** | +| `Transfer-Encoding` | `Tzansfer-Encoding` | `chunked` | 200 vs **501** | +| `Host` (duplicate) | `Hxst` | `target.com` | 200 vs **400** | +| HTTP version | `1.1` | `13.37` | 200 vs **505** | + +### Iterative Observation + +Don't stop at status codes. On each probe, observe: + +- **Response headers** — does an injected custom header (e.g. `x-smuggle-test: smuggle`) appear in the response? Direct proof of header injection. +- **Body content** — error pages may leak back-end server identity, framework, or parsing behavior. +- **Connection behavior** — does `Connection: keep-alive` in the injected headers keep the connection open? Required for queue poisoning. +- **Timing** — does the back-end pause (waiting for a body it expects from injected `Content-Length`)? Indicates full request parsing. + +Each observation narrows the exploitation path. A 400 from duplicate Host tells you the back-end parsed headers. A keep-alive response tells you the connection stays open. A TRACE 405 tells you the back-end parsed a smuggled method. Build your model of what the back-end accepts before crafting the exploit payload. + +## Phase 2: Determine Exploitation Mode + +After confirming injection, test whether the proxy reuses connections across users: + +1. Smuggle a request to `/nonexistent-[random]` +2. From a different session/IP, send a normal request to the same host +3. Second session receives the smuggled response → **queue poisoning** (connection reuse confirmed) +4. No cross-session leakage → **request tunnelling** only (still useful for ACL bypass) + +## Phase 3a: Response Queue Poisoning + +Inject two complete requests via CRLF. Front-end sees one; back-end sees two. Response #2 is queued for the next user on this connection. + +``` +GET /%20HTTP/1.1%0d%0aHost:%20target.com%0d%0aConnection:%20keep-alive%0d%0a%0d%0aGET%20/account%20HTTP/1.1%0d%0aHost:%20target.com%0d%0aFoo:%20bar HTTP/1.1 +Host: target.com +``` + +1. Back-end processes two requests: injected `GET /` and smuggled `GET /account` +2. Sends two responses on the persistent connection +3. Front-end returns response #1 to attacker, queues response #2 +4. Next legitimate user on this connection receives the `/account` response +5. Attacker's immediate follow-up request receives the victim's actual response + +### Escalation: Content-Length Absorption + +Smuggle a POST with large `Content-Length` that consumes the victim's request headers as body data: + +``` +...%0d%0a%0d%0aPOST%20/reflect%20HTTP/1.1%0d%0aHost:%20target.com%0d%0aContent-Type:%20application/x-www-form-urlencoded%0d%0aContent-Length:%20300%0d%0a%0d%0adata= HTTP/1.1 +``` + +Back-end reads 300 bytes of "body" — those bytes are the next victim's request headers. If `/reflect` echoes the body, attacker sees victim's `Cookie` and `Authorization` headers. + +### Browser Defense Bypass + +Browsers detecting extra response data beyond `Content-Length` will truncate and close the connection. Pad 100+ `%0d%0a` between the injected responses to delay over-read detection. + +## Phase 3b: Request Tunnelling + +When connections aren't shared across users, smuggle requests past proxy ACLs: + +``` +GET /%20HTTP/1.1%0d%0aHost:%20target.com%0d%0a%0d%0aGET%20/admin%20HTTP/1.1%0d%0aHost:%20target.com%0d%0aX%3A%20x HTTP/1.1 +Host: target.com +``` + +Proxy sees `GET /` (allowed). Back-end sees `GET /` + `GET /admin`. The `/admin` response returns to the attacker on the same connection. No victim interaction needed. + +**Confirmed vulnerable:** Nginx with `keepalive` upstream connections and `location`-based ACLs. + +## Scanning + +Nuclei templates from `turtlesec-software/crlf-desyncs` cover all probes above. CDN→origin CRLF injection: fuzz with `cdn-origin/cdn-cloud-headers-all.txt` wordlist (Akamai, Cloudflare, AWS, GCP headers that may pass CRLF through unsanitized). + +## Chain With + +- `crlf-response-splitting` — response header CRLF → XSS via nested splitting +- `web-cache-deception-path` — cache the poisoned/tunnelled response for persistent impact +- `parser-differential-bypass` — proxy normalizes `%0d%0a` differently than origin +- `self-xss-escalation` — smuggled request forces victim into attacker's self-XSS payload +- `403-bypass` — tunnel past proxy ACLs when direct path bypass fails + +## Reference + +- https://portswigger.net/research/making-http-header-injection-critical-via-response-queue-poisoning (Agarri) +- https://turtlesec.io/blog/posts/crlf-powered-desync-attacks/ (m4st3rspl1nt3r & t0xodile, BlackHat US 2026 / DEFCON 34) +- https://github.com/turtlesec-software/crlf-desyncs (Nuclei templates, labs, CDN header wordlists) +- https://portswigger.net/research/browser-powered-desync-attacks (Kettle — CL.0, pause-based desync)