|
2 | 2 |
|
3 | 3 | {{#include ../banners/hacktricks-training.md}} |
4 | 4 |
|
5 | | -**This is a summary of the post** [**https://portswigger.net/research/browser-powered-desync-attacks**](https://portswigger.net/research/browser-powered-desync-attacks) |
| 5 | +**This page summarizes, extends and updates** the seminal PortSwigger research on [Browser-Powered Desync Attacks](https://portswigger.net/research/browser-powered-desync-attacks) and subsequent work on HTTP/2 connection-state abuse. It focuses on vulnerabilities where **an origin is determined only once per TCP/TLS connection**, enabling an attacker to “smuggle” requests to a different internal host once the channel is established. |
6 | 6 |
|
7 | | -## Connection State Attacks <a href="#state" id="state"></a> |
| 7 | +## Connection-State Attacks <a href="#state" id="state"></a> |
8 | 8 |
|
9 | 9 | ### First-request Validation |
10 | 10 |
|
11 | | -When routing requests, reverse proxies might depend on the **Host header** to determine the destination back-end server, often relying on a whitelist of hosts that are permitted access. However, a vulnerability exists in some proxies where the whitelist is only enforced on the initial request in a connection. Consequently, attackers could exploit this by first making a request to an allowed host and then requesting an internal site through the same connection: |
| 11 | +When routing requests, reverse proxies might depend on the **Host** (or **:authority** in HTTP/2) header to determine the destination back-end server, often relying on a whitelist of hosts that are permitted access. However, a vulnerability exists in a number of proxies where the whitelist is **only enforced on the very first request in a connection**. Consequently, attackers can access internal virtual hosts by first sending an allowed request and then re-using the same underlying connection: |
12 | 12 |
|
13 | | -``` |
| 13 | +```http |
14 | 14 | GET / HTTP/1.1 |
15 | | -Host: [allowed-external-host] |
| 15 | +Host: allowed-external-host.example |
16 | 16 |
|
17 | | -GET / HTTP/1.1 |
18 | | -Host: [internal-host] |
| 17 | +GET /admin HTTP/1.1 |
| 18 | +Host: internal-only.example |
19 | 19 | ``` |
20 | 20 |
|
21 | 21 | ### First-request Routing |
22 | 22 |
|
23 | | -In some configurations, a front-end server may use the **Host header of the first request** to determine the back-end routing for that request, and then persistently route all subsequent requests from the same client connection to the same back-end connection. This can be demonstrated as: |
| 23 | +Many HTTP/1.1 reverse proxies map an outbound connection to a back-end pool **based exclusively on the first request they forward**. All subsequent requests sent through the same front-end socket are silently re-used, regardless of their Host header. This can be combined with classic [Host header attacks](https://portswigger.net/web-security/host-header) such as password-reset poisoning or [web cache poisoning](https://portswigger.net/web-security/web-cache-poisoning) to obtain SSRF-like access to other virtual hosts: |
24 | 24 |
|
25 | | -``` |
| 25 | +```http |
26 | 26 | GET / HTTP/1.1 |
27 | | -Host: example.com |
| 27 | +Host: public.example |
28 | 28 |
|
29 | 29 | POST /pwreset HTTP/1.1 |
30 | | -Host: psres.net |
| 30 | +Host: private.internal |
31 | 31 | ``` |
32 | 32 |
|
33 | | -This issue can potentially be combined with [Host header attacks](https://portswigger.net/web-security/host-header), such as password reset poisoning or [web cache poisoning](https://portswigger.net/web-security/web-cache-poisoning), to exploit other vulnerabilities or gain unauthorized access to additional virtual hosts. |
34 | | - |
35 | 33 | > [!TIP] |
36 | | -> To identify these vulnerabilities, the 'connection-state probe' feature in HTTP Request Smuggler can be utilized. |
| 34 | +> In Burp Suite Professional ≥2022.10 you can enable **HTTP Request Smuggler → Connection-state probe** to automatically detect these weaknesses. |
37 | 35 |
|
38 | | -{{#include ../banners/hacktricks-training.md}} |
| 36 | +--- |
| 37 | + |
| 38 | +## NEW in 2023-2025 – HTTP/2/3 Connection Coalescing Abuse |
| 39 | + |
| 40 | +Modern browsers routinely **coalesce** HTTP/2 and HTTP/3 requests onto a single TLS connection when the certificate, ALPN protocol and IP address match. If a front-end only authorizes the first request, every subsequent coalesced request inherits that authorisation – **even if the Host/:authority changes**. |
| 41 | + |
| 42 | +### Exploitation scenario |
| 43 | +1. The attacker controls `evil.com` which resolves to the same CDN edge node as the target `internal.company`. |
| 44 | +2. The victim’s browser already has an open HTTP/2 connection to `evil.com`. |
| 45 | +3. The attacker embeds a hidden `<img src="https://internal.company/…">` in their page. |
| 46 | +4. Because the connection parameters match, the browser re-uses the **existing** TLS connection and multiplexes the request for `internal.company`. |
| 47 | +5. If the CDN/router only validated the first request, the internal host is exposed. |
| 48 | + |
| 49 | +PoCs for Chrome/Edge/Firefox are available in James Kettle’s talk *“HTTP/2: The Sequel is Always Worse”* (Black Hat USA 2023). |
| 50 | + |
| 51 | +### Tooling |
| 52 | +* **Burp Suite 2023.12** introduced an experimental **HTTP/2 Smuggler** insertion point that automatically attempts coalescing and TE/CL techniques. |
| 53 | +* **smuggleFuzz** (https://github.com/microsoft/smugglefuzz) – A Python framework released in 2024 to brute-force front-end/back-end desync vectors over HTTP/2 and HTTP/3, including connection-state permutations. |
| 54 | + |
| 55 | +### Mitigations |
| 56 | +* Always **re-validate Host/:authority on every request**, not only on connection creation. |
| 57 | +* Disable or strictly scope **origin coalescing** on CDN/load-balancer layers (e.g. `http2_origin_cn` off in NGINX). |
| 58 | +* Deploy separate certificates or IP addresses for internal and external hostnames so the browser cannot legally coalesce them. |
| 59 | +* Prefer **connection: close** or `proxy_next_upstream` after each request where practical. |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +## Real-World Cases (2022-2025) |
| 64 | + |
| 65 | +| Year | Component | CVE | Notes | |
| 66 | +|------|-----------|-----|-------| |
| 67 | +| 2022 | AWS Application Load Balancer | – | Host header only validated on first request; fixed by patching rules engine (disclosed by SecurityLabs). | |
| 68 | +| 2023 | Apache Traffic Server < 9.2.2 | CVE-2023-39852 | Allowed request smuggling via HTTP/2 connection reuse when `CONFIG proxy.config.http.parent_proxy_routing_enable` was set. | |
| 69 | +| 2024 | Envoy Proxy < 1.29.0 | CVE-2024-2470 | Improper validation of :authority after first stream enabled cross-tenant request smuggling in shared meshes. | |
| 70 | + |
| 71 | +--- |
| 72 | + |
| 73 | +## Detection Cheat-Sheet |
| 74 | + |
| 75 | +1. Send two requests in the **same** TCP/TLS connection with different Host or :authority headers. |
| 76 | +2. Observe whether the second response originates from the first host (safe) or the second host (vulnerable). |
| 77 | +3. In Burp: `Repeat → keep-alive → Send → Follow`. |
| 78 | +4. When testing HTTP/2, open a **dedicated** stream (ID 1) for a benign host, then multiplex a second stream (ID 3) to an internal host and look for a reply. |
| 79 | + |
| 80 | +--- |
39 | 81 |
|
| 82 | +## References |
40 | 83 |
|
| 84 | +* PortSwigger Research – *HTTP/2: The Sequel is Always Worse* (Black Hat USA 2023) |
| 85 | +* Envoy Security Advisory CVE-2024-2470 – Improper authority validation |
41 | 86 |
|
| 87 | +{{#include ../banners/hacktricks-training.md}} |
0 commit comments