# Request Smuggling: WebSockets :::info Exploit HTTP Request Smuggling through WebSockets. ::: ## Web Socket ### What is a WebSocket? HTTP works in a request–response model, so the client must repeatedly send requests (polling) to get updates, which is inefficient for real-time features. WebSocket solves this by creating a persistent, two-way connection that allows both client and server to send data anytime. ### Upgrading HTTP connections to Websockets ![image](https://hackmd.io/_uploads/ry9h93oabe.png) WebSocket starts with an HTTP request where the client asks to upgrade the connection using the **Upgrade: websocket** header. If the server supports it, it r**esponds with 101 Switching Protocols,** and the connection is then switched from HTTP to WebSocket, enabling a persistent, two-way communication channel. ![image](https://hackmd.io/_uploads/ryHZj2ipZg.png) After a WebSocket upgrade, the proxy creates a tunnel and forwards traffic without inspecting it. Since the connection now uses the WebSocket protocol instead of HTTP, any attempt to smuggle HTTP requests will fail because the back-end server only accepts WebSocket data. ## Abusing websockets for request smugging ### Smuggling HTTP requests through broken WebSocket Tunnels An attacker can trick the proxy into thinking a WebSocket upgrade succeeded by sending a malformed upgrade request, while the back-end rejects it (e.g., due to an invalid Sec-WebSocket-Version). This creates a tunnel that the proxy doesn’t inspect, but the back-end still processes as HTTP, allowing request smuggling. ![image](https://hackmd.io/_uploads/rJgOyTf2abl.png) ![image](https://hackmd.io/_uploads/HyJErz3pZx.png) ![image](https://hackmd.io/_uploads/SkewRSMhp-e.png) ### Bypassing Proxy Restrictions This application is running behind a Varnish proxy with a vulnerable configuration ![image](https://hackmd.io/_uploads/SJvdDfnT-g.png) This error message was sent by Varnish (the proxy) instead of the backend application, which should be interesting. If we try accessing another non-existent resource like http://MACHINE_IP:8001/nonexistent134, the error message presented will be different. At this point, we should be suspicious that the frontend proxy is restricting access to /flag in the backend web server. ![image](https://hackmd.io/_uploads/By9bOMha-l.png) Luckily, there's also a WebSocket endpoint we can abuse at http://10.49.136.141:8001/socket. Let's send the following payload to try to smuggle a request for the flag inside a broken WebSocket connection: ![image](https://hackmd.io/_uploads/BJuNOMhaZe.png) ![image](https://hackmd.io/_uploads/ByzFcfhTWg.png) ![image](https://hackmd.io/_uploads/S18MifnpZe.png) Just as expected, we get a 426 error from the initial attempt to upgrade the connection to a WebSocket. At this point, the proxy believes the rest of the connection uses the WebSocket protocol and will tunnel everything directly to the backend server, including our smuggled request for /flag ### What if the App Doesn't Speak WebSocket? Some proxies don’t verify whether a WebSocket upgrade actually succeeds. As long as the request looks like an upgrade, the proxy creates a tunnel and stops inspecting traffic. Even if the backend doesn’t support WebSocket and continues using HTTP, this mismatch allows attackers to smuggle HTTP requests through the tunnel. ![image](https://hackmd.io/_uploads/SyuDsf26We.png) ![image](https://hackmd.io/_uploads/B1bCpfnaWg.png) ## Defeat Secure Proxies ### Upgrading our Proxy **Varnish (The "Blind" Proxy)**: It assumed the WebSocket upgrade was successful simply because it saw the Upgrade: WebSocket header. It created a tunnel to the backend blindly, which allowed you to "smuggle" a second request into that tunnel. **Nginx (The "Validating" Proxy)**: It acts as a strict gatekeeper. It forwards the upgrade request to the backend and waits for a 101 Switching Protocols response. If the backend doesn't agree to the upgrade (e.g., returns 426 Upgrade Required), Nginx realizes the handshake failed and refuses to establish the tunnel. ![image](https://hackmd.io/_uploads/r1_SCEh6Wx.png) ### Tricking the Proxy This means we need to somehow force the backend web server to reply to our upgrade request with a fake 101 Switching Protocols response without actually upgrading the connection in the backend. While we won't be able to do this for all applications, if our target app has some vulnerability that allows us to proxy requests back to a server we control as attackers, we might be able to inject the 101 Switching Protocols response to an arbitrary request. ![image](https://hackmd.io/_uploads/B11bkrhT-g.png) ### Leveraging SSRF In this task's application, we will take advantage of an SSRF vulnerability to simulate a fake WebSocket upgrade. After a quick inspection, we can see that the application allows us to test the status of a URL. Each time we input a URL, the server will make a request to `http://MACHINE_IP:8002/check-url?server=<url>` and return the status code from the corresponding response: We can use nc in our AttackBox to check if we can direct a request to ourselves. We should get a response similar to this one: ### Setting up the Attacker's Web Server We can quickly set up a web server that responds with status 101 to every request with the following Python code: ![imag![image](https://hackmd.io/_uploads/ryCxg8nTbg.png) ![image](https://hackmd.io/_uploads/S1lRJI2pZg.png)