HTTP Request smuggling

HTTP request smuggling vulnerabilities occur when the frontend and the backend interpret the boundary of an HTTP request differently causing de-synchronisation between them. This is due to numerous frontend and backend libraries deviating from RFC specifications when dealing with both the Content-Length and the Transfer-Encoding header. HTTP request bodies can be framed according to these two headers and deviations from the specification occur. As a result, part of a request gets appended or smuggled, to the next one which allows the response of the smuggled request to be provided to another user.

  • The body can vary from application to application, framework to framework, and the Content-Length and Transfer-Encoding: chunked headers are applicable to HTTP/1.1 and partially to HTTP/1.0, but not to HTTP/2. That written, other forms of smuggling are possible with the latter.

  • HTTP 1.1 allows for sending both Content-Length (CL) and Transfer-Encoding (TE) headers in the same request, but when both are sent, TE takes precedence.

  • A parent smuggled request carries both headers, to trick the servers.

  • A child smuggled request is the ideal request hidden inside the parent, ideal because it carries only one of the headers.

Steps

Send malformed requests to check for:

  • CL:CL: When provided with two Content-Length headers, if implementation differences occur between a frontend and a backend on which Content-Length header is prioritised, smuggling attacks can occur.

  • CL:TE: Different HTTP libraries tolerate different variations of the Transfer-Encoding header and will normalise them to improve client experience. By understanding what variations of the TE header is normalised by the backend server, it might be possible to smuggle a malformed TE header through the frontend and conduct a CL:TE smuggling attack. The frontend uses Content-Length and forwards the whole body; the backend uses Transfer-Encoding and stops at the zero-length chunk, so whatever follows sits at the front of the next request it reads.

  • TE:TE: Frontend and backend servers correctly prioritise the Transfer-Encoding header, but the header can be obfuscated to trick one of the servers.

  • TE:CL: The frontend server prioritises Transfer-Encoding, while the backend server prioritises Content-Length, making it possible to declare the length of the first chunk up to and including the malicious request. The second chunk is declared as having 0 length, so the frontend server assumes the request is complete. It passes the request to the backend server, which receives and processes it.

Escalation

  • Gain access to protected resources, such as admin consoles

  • Gain access to sensitive data

  • Hijack sessions of web users

  • Launch cross-site scripting (XSS) attacks without requiring any action from the user

  • Credential hijacking

Variants

The classic forms are CL.TE and TE.CL, detected by timing and confirmed by differential responses, with TE-header obfuscation to slip past one server. Exploitation runs to bypassing front-end controls, revealing front-end request rewriting, capturing other users’ requests, and delivering reflected XSS. The HTTP/2 family adds H2.TE and H2.CL, CRLF-based smuggling and splitting, request tunnelling, and response queue poisoning; CL.0 and server-side pause-based smuggling extend it further; and client-side desync needs no privileged network position. Several of these land in a cache, as poisoning or deception. The request smuggling and desync runbook works through detection, confirmation, and attack development.

Resources