flawopen.com/Simulators/HTTP Request Smuggling
Interactive HTTP Request Smuggling Visualizer (CL.TE & TE.CL)
An interactive, step-by-step visual sandbox modeling proxy-to-backend socket streams, chunked transfer encoding boundaries, and socket queue poisoning.
💡 Plain English Explainer (ELI5)
Imagine a conveyor belt between a front cashier (Reverse Proxy) and a kitchen cook (Backend Server). You hand the cashier a box labeled "Item Count: 1, contains 1 burger and 1 extra order slip". The cashier passes it through. But the cook reads only the outer label, grabs the burger, finishes Order #1, and leaves your extra order slip sitting on the preparation counter. When the next customer steps up to order a salad, the cook pastes their credit card onto your leftover slip and serves your order instead!
Core Concepts & Subsystem Terms
- Content-Length (CL)
- Specifies the exact size of the HTTP message body in octets (bytes). The receiver reads precisely this count before terminating the message.
- Transfer-Encoding: chunked (TE)
- Streams payloads in dynamic chunks formatted as hex size + payload + CRLF. A terminating chunk of size
0\r\n\r\nmarks the end. - Socket Keep-Alive Pipeline
- To optimize performance, frontend proxies reuse persistent TCP connections to stream multiple HTTP requests consecutively to backend servers.
- Request Queue Desync
- When frontend and backend disagree on where Request #1 ends, leftover bytes linger in the TCP socket, prepending to Request #2.
Step-by-Step Exploit & Execution Mechanics
Dual Header Crafting
Attacker sends an HTTP/1.1 POST containing both Content-Length: 6 and Transfer-Encoding: chunked with an obfuscated or trailing chunk body.
Frontend Boundary Parsing
The frontend proxy processes Content-Length: 6, reads only the first 6 bytes (up to the zero chunk), and marks Request #1 as fully ingested.
Backend Parser Trapping
The backend prioritizes Transfer-Encoding: chunked. It reads the 0\r\n\r\n chunk and considers Request #1 finished. The remaining smuggled payload remains stranded in the TCP read buffer.
Victim Connection Merging
The next user's incoming request is forwarded down the same keep-alive TCP socket. The backend parser concatenates the stranded bytes onto the beginning of the victim's request.
Source Code Diff: Ambiguous Header Handling
// Vulnerable Node.js / C HTTP parser logic
int http_parser_execute(http_parser *parser, const char *data, size_t len) {
if (parser->flags & F_CONTENT_LENGTH && parser->flags & F_CHUNKED) {
// FLAW: Silently gives precedence to one header without rejecting request!
// Frontend and backend make conflicting choices, causing TCP desync.
parser->body_read_mode = READ_CHUNKED;
return PARSE_CONTINUE;
}
}
// Hardened RFC 9112 section 6.1 compliant parser
int http_parser_execute(http_parser *parser, const char *data, size_t len) {
if ((parser->flags & F_CONTENT_LENGTH) && (parser->flags & F_CHUNKED)) {
// HARDENED: Mutually exclusive headers MUST be rejected with 400 Bad Request
parser->status_code = 400;
parser->connection_close = 1; // Forcefully close socket to clear buffer
return PARSE_ERROR_INVALID_HEADER;
}
}
Engineering & System Hardening Checklist
- Upgrade to End-to-End HTTP/2: HTTP/2 uses binary framing with explicit frame length indicators rather than text delimiters, eliminating HTTP/1.1 desync vectors entirely.
- Enforce RFC 9112 Section 6.1: Immediately reject any request containing both
Transfer-EncodingandContent-Lengthwith an HTTP 400 status. - Disable Upstream Connection Reuse for Ambiguous Requests: If legacy HTTP/1.1 proxies must be supported, instruct reverse proxies to drop keep-alive (
Connection: close) when unusual headers are detected. - Normalize Headers at Edge: Ensure the edge load balancer strips or normalizes conflicting chunk headers before proxying packets to upstream microservices.