daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

http-response-smuggling-desync.md (18031B)


      1 ---
      2 title: "HTTP Response Smuggling / Desync"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/http-response-smuggling-desync.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/http-response-smuggling-desync.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # HTTP Response Smuggling / Desync
     14 
     15 **The technique of this post was taken from the video:** [**https://www.youtube.com/watch?v=suxDcYViwao\&t=1343s**](https://www.youtube.com/watch?v=suxDcYViwao&t=1343s)<sup>[[3]](#references)[[4]](#references)</sup>
     16 
     17 ## HTTP Request Queue Desynchronisation
     18 
     19 First of all, this technique **abuses a HTTP Request Smuggling vulnerability**, so you need to know what that is:
     20 
     21 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**.
     22 
     23 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**.
     24 
     25 ### HTTP Pipeline Desync
     26 
     27 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**.
     28 
     29 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**.
     30 
     31 ![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...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28633%29.png)
     32 
     33 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.
     34 
     35 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**.
     36 
     37 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**).
     38 
     39 ![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...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%281020%29.png)
     40 
     41 ![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...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28719%29.png)
     42 
     43 ### Multiple Nested Injections
     44 
     45 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**.
     46 
     47 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.
     48 
     49 ### Exploit Organisation
     50 
     51 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**.
     52 
     53 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.
     54 
     55 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.
     56 
     57 ### Modern testing notes
     58 
     59 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.
     60 
     61 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.
     62 
     63 For the generic methodology and browser-powered variants, check [the main HTTP request smuggling page](/hacktricks/pentesting-web/http-request-smuggling/overview) and [Browser HTTP Request Smuggling](/hacktricks/pentesting-web/http-request-smuggling/browser-http-request-smuggling).
     64 
     65 ## Abusing HTTP Response Queue Desynchronisation
     66 
     67 ### Capturing other users' requests <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
     68 
     69 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.
     70 
     71 First, the attacker send a payload containing a **final POST request with the reflected parameter** at the end and a large Content-Length
     72 
     73 ![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...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%281053%29.png)
     74 
     75 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**:
     76 
     77 ![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)...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28794%29.png)
     78 
     79 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**.
     80 
     81 ## Response Desynchronisation
     82 
     83 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**.
     84 
     85 But it's still possible to **desynchronise even** more the responses.
     86 
     87 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**.
     88 
     89 Therefore, if an attacker **injects** a **HEAD** request, like in this images:
     90 
     91 ![Capturing other users' requests - Response Desynchronisation: Therefore, if an attacker injects a HEAD request, like in this images](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%281107%29.png)
     92 
     93 Then, **once the blue one is responded to the attacker**, the next victims request is going to be introduced in the queue:
     94 
     95 ![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](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28999%29.png)
     96 
     97 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):
     98 
     99 ![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...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28735%29.png)
    100 
    101 ### Content Confusion
    102 
    103 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:
    104 
    105 ![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...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28688%29.png)
    106 
    107 ### TRACE as a reflection gadget
    108 
    109 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.<sup>[[1]](#references)</sup>
    110 
    111 Typical pattern:
    112 
    113 1. Smuggle a `HEAD` so the proxy expects a response body length but the backend only sends headers.
    114 2. Immediately smuggle `TRACE /...` with attacker-controlled headers and enough padding.
    115 3. The `TRACE` response becomes the missing body of the `HEAD` response.
    116 4. Reuse it for **content confusion**, **response splitting**, **cache poisoning**, or simply to learn how the proxy rewrites requests before they reach the backend.
    117 
    118 ```http
    119 GET / HTTP/1.1
    120 Host: target
    121 Content-Length: 150
    122 
    123 HEAD / HTTP/1.1
    124 Host: target
    125 
    126 TRACE / HTTP/1.1
    127 Host: target
    128 X-Pad: ...padding...
    129 X: <script>alert(1)</script>
    130 ```
    131 
    132 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.
    133 
    134 ### Cache Poisoning
    135 
    136 Abusing the previously commented response desynchronisation Content Confusion attack, i**f 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**.
    137 
    138 Malicious request containing the XSS payload:
    139 
    140 ![Content Confusion - Cache Poisoning: Malicious request containing the XSS payload](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28614%29.png)
    141 
    142 Malicious response to the victim that contains the header that indicates to the cache to store the response:
    143 
    144 ![Content Confusion - Cache Poisoning: Malicious response to the victim that contains the header that indicates to the cache to store the response](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28566%29.png)
    145 
    146 > [!WARNING]
    147 > 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.
    148 
    149 ### Web Cache Deception
    150 
    151 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:**
    152 
    153 ![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...](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28991%29.png)
    154 
    155 ### Response Splitting
    156 
    157 The **goal** of this attack is to abuse again the **response** **desynchronisation** in order to **make the proxy send a 100% attacker generated response**.
    158 
    159 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**.
    160 
    161 He will send a **exploit** like:
    162 
    163 ![Web Cache Deception - Response Splitting: He will send a exploit like](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28911%29.png)
    164 
    165 After the first request is resolved and sent back to the attacker, the **victims request is added into the queue**:
    166 
    167 ![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](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28737%29.png)
    168 
    169 The victim will receive as response the **HEAD response + the content of the second request response (containing part of the reflected data):**
    170 
    171 ![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)](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28356%29.png)
    172 
    173 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**.
    174 
    175 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**.
    176 
    177 ## New response-side discrepancies worth testing (2024-2025)
    178 
    179 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:<sup>[[2]](#references)</sup>
    180 
    181 - **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.
    182 - **Response-order bugs**: some multi-endpoint frameworks can map responses to the wrong request even without a textbook CL.TE primitive, enabling **response stealing**.
    183 - **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.
    184 
    185 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.
    186 
    187 ## Tooling notes
    188 
    189 - **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.
    190 - 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.<sup>[[2]](#references)</sup>
    191 
    192 ## References
    193 
    194 - [1] [PortSwigger - Making desync attacks easy with TRACE](https://portswigger.net/research/trace-desync-attack)
    195 - [2] [USENIX Security 2025 - The Silent Danger in HTTP: Identifying HTTP Desync Vulnerabilities with Gray-box Testing](https://www.usenix.org/system/files/usenixsecurity25-mu.pdf)
    196 - [3] [DEF CON 29 - Martin Doyhenard - Response Smuggling: Pwning HTTP/1.1 Connections](https://www.youtube.com/watch?v=suxDcYViwao&t=1343s)
    197 - [4] [youtube.com - Watch](https://www.youtube.com/watch?v=suxDcYViwao)