flawopen.com/Simulators/HTTP Request Smuggling
An interactive, step-by-step visual sandbox modeling proxy-to-backend socket streams, chunked transfer encoding boundaries, and socket queue poisoning.
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!
0\r\n\r\n marks the end.Attacker sends an HTTP/1.1 POST containing both Content-Length: 6 and Transfer-Encoding: chunked with an obfuscated or trailing chunk body.
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.
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.
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.
// 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;
}
}
Transfer-Encoding and Content-Length with an HTTP 400 status.Connection: close) when unusual headers are detected.