mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 14:40:37 +00:00
142 lines
11 KiB
Markdown
142 lines
11 KiB
Markdown
# Upgrade Header Smuggling
|
|
|
|
<details>
|
|
|
|
<summary><strong>Support HackTricks and get benefits!</strong></summary>
|
|
|
|
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
|
|
|
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
|
|
|
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
|
|
|
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
|
|
|
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
|
|
|
|
</details>
|
|
|
|
## H2C Smuggling <a href="#http2-over-cleartext-h2c" id="http2-over-cleartext-h2c"></a>
|
|
|
|
### HTTP2 Over Cleartext (H2C) <a href="#http2-over-cleartext-h2c" id="http2-over-cleartext-h2c"></a>
|
|
|
|
A normal HTTP connection typically lasts only for the duration of a single request. However, H2C or “**http2 over cleartext”** is where a normal transient http **connection is upgraded to a persistent connection that uses the http2 binary protocol** to communicate continuously instead of for one request using the plaintext http protocol.
|
|
|
|
The second part of the smuggling occurs when a **reverse proxy is used**. Normally, when http requests are made to a reverse proxy, the proxy will handle the request, process a series of routing rules, then forward the request onto the backend and then return the response. When a http request includes a `Connection: Upgrade` header, such as for a websocket connection, the reverse **proxy will maintain the persistent connection** between the client and server, **allowing for the continuous communication needed for these procotols**. For a H2C Connection, the RFC requires 3 headers to be present:
|
|
|
|
```
|
|
Upgrade: h2c
|
|
HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
|
|
Connection: Upgrade, HTTP2-Settings
|
|
```
|
|
|
|
So where is the bug? **When upgrading a connection, the reverse proxy will often stop handling individual requests**, assuming that once the connection has been established, its routing job is done. Using H2C Smuggling, we can bypass rules a reverse proxy uses when processing requests such as path based routing, authentication, or the WAF processing provided we can establish a H2C connection first.
|
|
|
|
![](<../.gitbook/assets/image (454).png>)
|
|
|
|
### Vulnerable Proxies <a href="#exploitation" id="exploitation"></a>
|
|
|
|
Note from the explanation of the vulnerability that the proxy server needs to **forward the Upgrade header**, and sometimes the **Connection header** also needs to be successfully forwarded.
|
|
|
|
By default, the following services **do** forward **Upgrade** and **Connection headers** during proxy-pass, thereby enabling h2c smuggling out-of-the-box.:
|
|
|
|
* HAProxy
|
|
* Traefik
|
|
* Nuster
|
|
|
|
By default, these services **do not** forward both Upgrade and Connection headers during proxy-pass, but **can be configured in an insecure manner** (by passing unfiltered Upgrade and Connection headers):
|
|
|
|
* AWS ALB/CLB
|
|
* NGINX
|
|
* Apache
|
|
* Squid
|
|
* Varnish
|
|
* Kong
|
|
* Envoy
|
|
* Apache Traffic Server
|
|
|
|
### Exploitation <a href="#exploitation" id="exploitation"></a>
|
|
|
|
The original blog post points out that not all servers will forward the required headers for a compliant H2C connection upgrade. This means load balancers like AWS ALB/CLB, NGINX, and Apache Traffic Server amongst others will **prevent a H2C connection by default**. However, at the end of the blog post, he does mention that “not all backends were compliant, and we could **test with the non-compliant `Connection: Upgrade` variant, where the `HTTP2-Settings` value is omitted** from the `Connection` header.”
|
|
|
|
{% hint style="danger" %}
|
|
Note that even if the `proxy_pass` URL (the endpoint the proxy forwards the connection) was pointing to a specific **path** such as `http://backend:9999/socket.io` the connection will be stablished with `http://backend:9999` so you can **contact any other path inside that internal endpoint abusing this technique. So it doesn't matter if a path is specified in the URL of proxy\_pass.**
|
|
{% endhint %}
|
|
|
|
Using the tools [**https://github.com/BishopFox/h2csmuggler**](https://github.com/BishopFox/h2csmuggler) **and** [**https://github.com/assetnote/h2csmuggler**](https://github.com/assetnote/h2csmuggler) you can try to **bypass the protections imposed** by the proxy establishing a H2C connection and access proxy protected resources.
|
|
|
|
Follow this link for[ **more info about this vulnerability in Nginx**](../network-services-pentesting/pentesting-web/nginx.md#proxy\_set\_header-upgrade-and-connection).
|
|
|
|
## Websocket Smuggling
|
|
|
|
Similar to previous technique, this one **instead** of creating a **HTTP2 tunnel** to an endpoint accessible via a proxy, it will create a **Websocket tunnel** for the same purpose, **bypass potential proxies limitations** and talk directly to the endpoint:
|
|
|
|
![](<../.gitbook/assets/image (651) (2) (1).png>)
|
|
|
|
### Scenario 1
|
|
|
|
We have backend that exposes public **WebSocket API** and also has **internal REST API not available** from outside. Malicious client wants to access internal REST API.
|
|
|
|
On the **first** step client sends **Upgrade request** to reverse proxy but with **wrong protocol version** inside header `Sec-WebSocket-Version`. **Proxy** doesn't validate `Sec-WebSocket-Version` header and thinks that **Upgrade request is correct**. Further it translates request to the backend.
|
|
|
|
On the second step backend sends **response with status code `426` because protocol version is incorrect** inside header `Sec-WebSocket-Version`. However, **reverse proxy doesn't check** enough response from backend (including status code) and **thinks that backend is ready for WebSocket communication**. Further it translates request to the client.
|
|
|
|
Finally, reverse **proxy thinks** that **WebSocket connection is established between client and backend**. In reality there is no WebSocket connection - backend refused Upgrade request. At the same time, proxy keeps TCP or TLS connection between client and backend in open state. **Client can easily access private REST API by sending HTTP request over the connection.**
|
|
|
|
![](https://github.com/0ang3el/websocket-smuggle/raw/master/img/2-4.png)
|
|
|
|
It was found that following reverse proxies are affected:
|
|
|
|
* Varnish - team refused to fix described issue.
|
|
* Envoy proxy 1.8.0 (or older) - in newer versions upgrade mechanism has been changed.
|
|
* Others - TBA.
|
|
|
|
### Scenario 2
|
|
|
|
The majority of reverse proxies (e.g. NGINX) **check status code from backend** during handshake part. This makes attack harder but not impossible.
|
|
|
|
Let's observe second scenario. We have backend that exposes public WebSocket API and public REST API for health checking and also has **internal REST API not available from outside**. Malicious client wants to access internal REST API. NGINX is used as reverse proxy. WebSocket API is available on path `/api/socket.io/` and healthcheck API on path `/api/health`.
|
|
|
|
Healthcheck API is invoked by sending POST request, parameter with name `u` controls URL. Backend reaches external resource and returns status code back to the client.
|
|
|
|
On the **first** step client sends POST request to invoke **healthcheck API but with additional HTTP header `Upgrade: websocket`**. NGINX thinks that it's a **normal Upgrade request**, it looks only for `Upgrade` header skipping other parts of the request. Further proxy translates request to the backend.
|
|
|
|
On the **second** step backend invokes healtcheck API. It reaches external resource controlled by malicious users that returns HTTP **response with status code `101`**. Backend translates that response to the reverse proxy. Since NGINX validates only status code **it will think that backend is ready for WebSocket communication**. Further it translates request to the client.
|
|
|
|
![](https://github.com/0ang3el/websocket-smuggle/raw/master/img/3-4.png)
|
|
|
|
{% hint style="warning" %}
|
|
Note how this scenario is much more complex to exploit as you need to be able to contact some endpoint that **returns status code 101**.
|
|
{% endhint %}
|
|
|
|
Finally, **NGINX thinks that WebSocket connection is established between client and backend**. In reality there is no WebSocket connection - healthcheck REST API was invoked on backend. At the same time, reverse proxy keeps TCP or TLS connection between client and backend in open state. **Client can easily access private REST API by sending HTTP request over the connection.**
|
|
|
|
![](https://github.com/0ang3el/websocket-smuggle/raw/master/img/3-5.png)
|
|
|
|
The majority of reverse proxies should be affected by that scenario. However, exploitation requires existence of external SSRF vulnerability (usually considered low-severity issue).
|
|
|
|
### Labs
|
|
|
|
Check the labs to test both scenarios in [https://github.com/0ang3el/websocket-smuggle.git](https://github.com/0ang3el/websocket-smuggle.git)
|
|
|
|
## References
|
|
|
|
* [https://blog.assetnote.io/2021/03/18/h2c-smuggling/](https://blog.assetnote.io/2021/03/18/h2c-smuggling/)
|
|
* [https://bishopfox.com/blog/h2c-smuggling-request](https://bishopfox.com/blog/h2c-smuggling-request)
|
|
* [https://github.com/0ang3el/websocket-smuggle.git](https://github.com/0ang3el/websocket-smuggle.git)
|
|
|
|
<details>
|
|
|
|
<summary><strong>Support HackTricks and get benefits!</strong></summary>
|
|
|
|
Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
|
|
|
Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
|
|
|
Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
|
|
|
**Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/carlospolopm)**.**
|
|
|
|
**Share your hacking tricks submitting PRs to the** [**hacktricks github repo**](https://github.com/carlospolop/hacktricks)**.**
|
|
|
|
</details>
|