Skip to content
Field Detail
Platform PortSwigger Web Security Academy
Type WebSockets — Message-Based XSS
Difficulty Apprentice
Objective Use a WebSocket message to trigger an alert() popup in the support agent's browser

Manipulating WebSocket Messages to Exploit Vulnerabilities

I opened the live chat and sent a test message, intercepting the underlying request:

Screenshot
GET /chat HTTP/2
Host: 0a9c000c03be9d6d822002f600470010.web-security-academy.net
Upgrade: websocket
HTTP/1.1 101 Switching Protocol
Connection: Upgrade
Upgrade: websocket
Screenshot

The Upgrade: websocket header combined with the 101 Switching Protocol response is what flips this from a regular HTTP request into a WebSocket connection — once the handshake completes, the same connection stays open for bidirectional messages instead of closing after a single request/response cycle.

Checking the WebSockets history tab in Burp:

Screenshot

Messages show up here tagged by direction. The support agent's reply shows as <- to client:

Screenshot

I intercepted another chat message frame and sent it to Repeater. First probe was <script>alert(0)</script>:

Screenshot

The rendered message on the chat page came back HTML-encoded, and the WebSocket message in Burp confirmed it:

Screenshot
{"user":"You","content":"&lt;script&gt;alert(0)&lt;/script&gt;"}

Angle brackets were being HTML-encoded. I tried sending raw angle brackets directly in Repeater — bypassing the client-side encoding — using what the lab actually asks for:

{"user":"You","content":"<script>alert()</script>"}
Screenshot

No alert. <script> tags appear to be filtered or stripped server-side, separate from the encoding behavior — sanitization that targets script tags specifically doesn't cover every XSS vector. WebSocket messages are just as susceptible to standard input-based vulnerabilities as regular HTTP parameters; the delivery mechanism changes, but the underlying flaw is the same. Switching to an event-handler-based payload sidesteps the script-tag filter entirely:

{"message":"<img src=teto.png onerror=alert()>"}
Screenshot

Alert fired.

Screenshot

Lab solved >>..<<

Dead Ends & Rabbit Holes

<script>alert()</script> with raw angle brackets sent directly through Repeater didn't fire — server-side sanitization appears to target <script> tags specifically rather than HTML injection broadly. An <img onerror=...> payload sidesteps that entirely.

Resources