HTTP Response Smuggling / Desync

The technique of this post was taken from the video: https://www.youtube.com/watch?v=suxDcYViwao\&t=1343s

HTTP Request Queue Desynchronisation

First of all, this technique abuses a HTTP Request Smuggling vulnerability, so you need to know what that is:

The main difference between this technique and a common HTTP Request smuggling is that instead of attacking the request of the victim by adding a prefix to it, we are going to leak or modify the response the victim receives. This is done by, instead of sending 1 request and a half to abuse the HTTP Request smuggling, send 2 complete requests to desynchronise the proxies responses queue.

This is because we are going to be able to desynchronise the response queue so the response from the legit request of the victim is sent to the attacker, or by injecting attackers controlled content in the response to the victim.

HTTP Pipeline Desync

HTTP/1.1 allows to ask for different resources without needing to wait for previous ones. Therefore, if there is a proxy in the middle, it's the proxies task to maintain a synchronised match of requests sent to the backend and responses coming from it.

However, there is a problem desynchronising the responses queue. If an attacker send a HTTP Response smuggling attack and the responses to the initial request and the smuggled one are responded immediately, the smuggled response won't be inserted inside the queue of the victim response but will just be discarded as an error.

HTTP Request Queue Desynchronisation - HTTP Pipeline Desync: However, there is a problem desynchronising the responses queue. If an attacker send a HTTP Response smuggling attack and the...

Therefore, it's needed that the smuggled request takes more time to be processed inside the back-end server. Therefore, by the time the smuggled request is processed, the communication with the attacker will be over.

If in this specific situation a victim has sent a request and the smuggled request is responded before the legitimate request, the smuggled response will be sent to the victim. Therefore, the attacker will be controlling the request "performed" by the victim.

Moreover, is the attacker then perform a request and the legitimate response to the victim request is answered before the attackers request. The response to the victim is going to be sent to the attacker, stealing the response to the victim (which can contains for example the header Set-Cookie).

HTTP Request Queue Desynchronisation - HTTP Pipeline Desync: Moreover, is the attacker then perform a request and the legitimate response to the victim request is answered before the...

HTTP Request Queue Desynchronisation - HTTP Pipeline Desync: Moreover, is the attacker then perform a request and the legitimate response to the victim request is answered before the...

Multiple Nested Injections

Another interesting difference with common HTTP Request Smuggling is that, in a common smuggling attack, the goal is to modify the beginning of the victims request so it perform an unexpected action. In a HTTP Response smuggling attack, as you are sending full requests, you can inject in one payload tens of responses that will be desynchronising tens of users that will be receiving the injected responses.

Apart from being able to distribute more easily tens of exploits across legitimate users, this could also be used to cause a DoS in the server.

Exploit Organisation

As explained previously, in order to abuse this technique, it's needed that the first smuggled message into the server requires a lot of time to be processed.

This time consuming request is enough if we just want to try to steal the victims response. But if you want to perform a more complex exploit this will be a common structure for the exploit.

First of all the initial request abusing HTTP Request smuggling, then the time consuming request and then 1 or more payload requests that whose responses will be sent to the victims.

Modern testing notes

A common pitfall when testing this nowadays is to confuse real response queue poisoning with harmless client-side pipelining / connection reuse artifacts. If your PoC only works with requestsPerConnection > 1, Repeater groups over a single socket, or explicit connection reuse, re-test with connection reuse disabled before claiming a server-side desync. Otherwise you may have only desynchronised your client from the server, not the front-end from the back-end.

Legitimate reuse-required cases still exist: connection-locked request smuggling, connection-state attacks, and client-side desync. A good confirmation trick is to retry the same primitive over an HTTP/2 downgrade path and look for a nested HTTP/1 response inside a single response. If you can do that, you are likely looking at a real parser discrepancy instead of a pure pipelining illusion.

For the generic methodology and browser-powered variants, check the main HTTP request smuggling page and Browser HTTP Request Smuggling.

Abusing HTTP Response Queue Desynchronisation

Capturing other users' requests

As with HTTP Request Smuggling known payloads, you can steal the victims request with one important difference: In this case you just need the send content to be reflected in the response, no persistent storage is needed.

First, the attacker send a payload containing a final POST request with the reflected parameter at the end and a large Content-Length

Abusing HTTP Response Queue Desynchronisation - Capturing other users' requests: First, the attacker send a payload containing a final POST request with the reflected parameter at the...

Then, once the initial request (blue) was processed and while the sleepy one is being processed (yellow) the next request that arrives from a victim is going to be appended in the queue just after the reflected parameter:

Abusing HTTP Response Queue Desynchronisation - Capturing other users' requests: Then, once the initial request (blue) was processed and while the sleepy one is being processed (yellow)...

Then, the victim will receive the response to the sleepy request and if in the meantime the attacker sent another request, the response from the reflected content request will be sent to him.

Response Desynchronisation

Up to this point, we have learned how to abuse HTTP Request Smuggling attacks to control the request whose response a client is going to receive and how you can then steal the response that was meant for the victim.

But it's still possible to desynchronise even more the responses.

There are interesting requests like HEAD request that are specified to not have any content inside the responses body and that should (must) contain the Content-Length of the request like if it was a GET request.

Therefore, if an attacker injects a HEAD request, like in this images:

Capturing other users' requests - Response Desynchronisation: Therefore, if an attacker injects a HEAD request, like in this images

Then, once the blue one is responded to the attacker, the next victims request is going to be introduced in the queue:

Capturing other users' requests - Response Desynchronisation: Then, once the blue one is responded to the attacker , the next victims request is going to be introduced in the queue

Then, the victim will receive the response from the HEAD request, which is going to contain a Content-Length but no content at all. Therefore, the proxy won't send this response to the victim, but will wait for some content, which actually is going to be response to the yellow request (also injected by the attacker):

Capturing other users' requests - Response Desynchronisation: Then, the victim will receive the response from the HEAD request, which is going to contain a Content-Length but no content...

Content Confusion

Following the previous example, knowing that you can control the body of the request whose response is going to receive the victim and that a HEAD response usually contains in its headers the Content-Type and the Content-Length, you can send a request like the following one to cause XSS in the victim without the page being vulnerable to XSS:

Response Desynchronisation - Content Confusion: Following the previous example, knowing that you can control the body of the request whose response is going to receive the victim and...

TRACE as a reflection gadget

A very practical update is to use a smuggled TRACE request as the response-body generator when the target has no obvious reflection endpoint. TRACE reflects the request received by the backend, often including proxy-added headers (X-Forwarded-For, downgraded HTTP/1.1 start-lines, etc.), so it can be combined with a smuggled HEAD to turn a queue desync into attacker-controlled reflected bytes in the victim response.

Typical pattern:

  1. Smuggle a HEAD so the proxy expects a response body length but the backend only sends headers.
  2. Immediately smuggle TRACE /... with attacker-controlled headers and enough padding.
  3. The TRACE response becomes the missing body of the HEAD response.
  4. Reuse it for content confusion, response splitting, cache poisoning, or simply to learn how the proxy rewrites requests before they reach the backend.
GET / HTTP/1.1
Host: target
Content-Length: 150

HEAD / HTTP/1.1
Host: target

TRACE / HTTP/1.1
Host: target
X-Pad: ...padding...
X: <script>alert(1)</script>

Even if the edge blocks TRACE, smuggling can hide it from the front-end/WAF and deliver it directly to the backend. This is especially interesting in HTTP/2→HTTP/1 downgrade scenarios where the downgraded request line and injected proxy headers are reflected back in the TRACE body.

Cache Poisoning

Abusing the previously commented response desynchronisation Content Confusion attack, if the cache stores the response to the request performed by the victim and this response is an injected one causing a XSS, then the cache is poisoned.

Malicious request containing the XSS payload:

Content Confusion - Cache Poisoning: Malicious request containing the XSS payload

Malicious response to the victim that contains the header that indicates to the cache to store the response:

Content Confusion - Cache Poisoning: Malicious response to the victim that contains the header that indicates to the cache to store the response

Warning

Note that in this case if the "victim" is the attacker he can now perform cache poisoning in arbitrary URLs as he can control the URL that is going to be cached with the malicious response.

Web Cache Deception

This attack is similar to the previous one, but instead of injecting a payload inside the cache, the attacker will be caching victim information inside of the cache:

Cache Poisoning - Web Cache Deception: This attack is similar to the previous one, but instead of injecting a payload inside the cache, the attacker will be caching victim information...

Response Splitting

The goal of this attack is to abuse again the response desynchronisation in order to make the proxy send a 100% attacker generated response.

In order to achieve this, the attacker needs to find an endpoint of the web application that is reflecting some values inside the response and know the content length of the HEAD response.

He will send a exploit like:

Web Cache Deception - Response Splitting: He will send a exploit like

After the first request is resolved and sent back to the attacker, the victims request is added into the queue:

Web Cache Deception - Response Splitting: After the first request is resolved and sent back to the attacker, the victims request is added into the queue

The victim will receive as response the HEAD response + the content of the second request response (containing part of the reflected data):

Web Cache Deception - Response Splitting: The victim will receive as response the HEAD response + the content of the second request response (containing part of the reflected data)

However, note how the reflected data had a size according to the Content-Length of the HEAD response that generated a valid HTTP response in the response queue.

Therefore, the next request of the second victim will be receiving as response something completely crafted by the attacker. As the response is completely crafted by the attacker he can also make the proxy cache the response.

New response-side discrepancies worth testing (2024-2025)

Recent research shows that response desync is not limited to HEAD-only tricks. When auditing modern stacks, also test response translation layers and not just classic CL.TE / TE.CL ambiguities in requests:

  • Response TE.CL / dechunk-vs-length mismatches: one hop dechunks a backend response or strips Transfer-Encoding, while another hop still trusts Content-Length. This can transform backend bytes into a forged follow-up response.
  • Response-order bugs: some multi-endpoint frameworks can map responses to the wrong request even without a textbook CL.TE primitive, enabling response stealing.
  • CGI / gateway conversion issues: when a CGI/FastCGI/uWSGI-style gateway converts backend output into HTTP, headers emitted by the CGI response can leak into the final HTTP response and create fresh response-side desync gadgets.

From an offensive point of view, this means it is worth testing legacy methods (HEAD, TRACE), response rewriting intermediaries, and CGI/proxy adapters even when the classic request-side smuggling checks look clean.

Tooling notes

  • Burp HTTP Request Smuggler remains the most practical day-to-day option to probe these bugs, especially when you need to chain a desync into response stealing or cache poisoning.
  • If you are reviewing implementations from source code, gray-box differential fuzzing is now practical enough to find discrepancies in HTTP requests, HTTP responses, and CGI responses, not only in front-end request parsing.

References