Merge pull request #1416 from HackTricks-wiki/update_WebSocket_Turbo_Intruder__Unearthing_the_WebSocket_20250917_182701

WebSocket Turbo Intruder Unearthing the WebSocket Goldmine
This commit is contained in:
SirBroccoli 2025-09-29 16:06:16 +02:00 committed by GitHub
commit 52dfcf1a94
2 changed files with 142 additions and 3 deletions

View File

@ -382,7 +382,8 @@ Once you have **obtained a valid RT** you could try to **abuse it to generate se
## **RC in WebSockets**
In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) you can find a PoC in Java to send websocket messages in **parallel** to abuse **Race Conditions also in Web Sockets**.
- In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC) you can find a PoC in Java to send websocket messages in **parallel** to abuse **Race Conditions also in Web Sockets**.
- With Burps WebSocket Turbo Intruder you can use the **THREADED** engine to spawn multiple WS connections and fire payloads in parallel. Start from the official example and tune `config()` (thread count) for concurrency; this is often more reliable than batching on a single connection when racing serverside state across WS handlers. See [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py).
## References
@ -392,6 +393,9 @@ In [**WS_RaceCondition_PoC**](https://github.com/redrays-io/WS_RaceCondition_PoC
- [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
- [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
- [https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/](https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/)
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
- [WebSocketTurboIntruder GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
{{#include ../banners/hacktricks-training.md}}

View File

@ -99,6 +99,135 @@ In [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Bur
The burp extension [**Backslash Powered Scanner**](https://github.com/PortSwigger/backslash-powered-scanner) now allows to fuzz also WebSocket messages. You can read more infromation abou this [**here**](https://arete06.com/posts/fuzzing-ws/#adding-websocket-support-to-backslash-powered-scanner).
### WebSocket Turbo Intruder (Burp extension)
PortSwigger's WebSocket Turbo Intruder brings Turbo Intruderstyle Python scripting and highrate fuzzing to WebSockets. Install it from the BApp Store or from source. It includes two components:
- Turbo Intruder: highvolume messaging to a single WS endpoint using custom engines.
- HTTP Middleware: exposes a local HTTP endpoint that forwards bodies as WS messages over a persistent connection, so any HTTPbased scanner can probe WS backends.
Basic script pattern to fuzz a WS endpoint and filter relevant responses:
```python
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(upgrade_request)
for i in range(10):
connection.queue(message, str(i))
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@MatchRegex(r'{\"user\":\"Hal Pline\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Use decorators like `@MatchRegex(...)` to reduce noise when a single message triggers multiple responses.
### Bridge WS behind HTTP (HTTP Middleware)
Wrap a persistent WS connection and forward HTTP bodies as WS messages for automated testing with HTTP scanners:
```python
def create_connection(upgrade_request):
connection = websocket_connection.create(upgrade_request)
return connection
@MatchRegex(r'{\"user\":\"You\"')
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
Then send HTTP locally; the body is forwarded as the WS message:
```http
POST /proxy?url=https%3A%2F%2Ftarget/ws HTTP/1.1
Host: 127.0.0.1:9000
Content-Length: 16
{"message":"hi"}
```
This lets you drive WS backends while filtering for “interesting” events (e.g., SQLi errors, auth bypass, command injection behavior).
### Socket.IO handling (handshake, heartbeats, events)
Socket.IO adds its own framing on top of WS. Detect it via the mandatory query parameter `EIO` (e.g., `EIO=4`). Keep the session alive with Ping (`2`) and Pong (`3`) and start the conversation with `"40"`, then emit events like `42["message","hello"]`.
Intruder example:
```python
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def queue_websockets(upgrade_request, message):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.queue('42["message","hello"]')
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
HTTP adapter variant:
```python
import burp.api.montoya.http.message.params.HttpParameter as HttpParameter
def create_connection(upgrade_request):
connection = websocket_connection.create(
upgrade_request.withUpdatedParameters(HttpParameter.urlParameter("EIO", "4")))
connection.queue('40')
connection.decIn()
return connection
@Pong("3")
def handle_outgoing_message(websocket_message):
results_table.add(websocket_message)
@PingPong("2", "3")
def handle_incoming_message(websocket_message):
results_table.add(websocket_message)
```
### Detecting serverside prototype pollution via Socket.IO
Following PortSwiggers safe detection technique, try polluting Express internals by sending a payload like:
```json
{"__proto__":{"initialPacket":"Polluted"}}
```
If greetings or behavior change (e.g., echo includes "Polluted"), you likely polluted server-side prototypes. Impact depends on reachable sinks; correlate with the gadgets in the Node.js prototype pollution section. See:
- Check [NodeJS __proto__ & prototype Pollution](deserialization/nodejs-proto-prototype-pollution/README.md) for sinks/gadgets and chaining ideas.
### WebSocket race conditions with Turbo Intruder
The default engine batches messages on one connection (great throughput, poor for races). Use the THREADED engine to spawn multiple WS connections and fire payloads in parallel to trigger logic races (doublespend, token reuse, state desync). Start from the example script and tune concurrency in `config()`.
- Learn methodology and alternatives in [Race Condition](race-condition.md) (see “RC in WebSockets”).
### WebSocket DoS: malformed frame “Ping of Death”
Craft WS frames whose header declares a huge payload length but send no body. Some WS servers trust the length and preallocate buffers; setting it near `Integer.MAX_VALUE` can cause OutOfMemory and a remote unauth DoS. See the example script.
### CLI and debugging
- Headless fuzzing: `java -jar WebSocketFuzzer-<version>.jar <scriptFile> <requestFile> <endpoint> <baseInput>`
- Enable the WS Logger to capture and correlate messages using internal IDs.
- Use `inc*`/`dec*` helpers on `Connection` to tweak message ID handling in complex adapters.
- Decorators like `@PingPong`/`@Pong` and helpers like `isInteresting()` reduce noise and keep sessions alive.
### Operational safety
Highrate WS fuzzing can open many connections and send thousands of messages per second. Malformed frames and high rates may cause real DoS. Use only where permitted.
## Cross-site WebSocket hijacking (CSWSH)
**Cross-site WebSocket hijacking**, also known as **cross-origin WebSocket hijacking**, is identified as a specific case of **[Cross-Site Request Forgery (CSRF)](csrf-cross-site-request-forgery.md)** affecting WebSocket handshakes. This vulnerability arises when WebSocket handshakes authenticate solely via **HTTP cookies** without **CSRF tokens** or similar security measures.
@ -204,7 +333,13 @@ h2c-smuggling.md
- [https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages](https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages)
- [https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/)
- [WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine](https://portswigger.net/research/websocket-turbo-intruder-unearthing-the-websocket-goldmine)
- [WebSocket Turbo Intruder BApp Store](https://portswigger.net/bappstore/ba292c5982ea426c95c9d7325d9a1066)
- [WebSocketTurboIntruder GitHub](https://github.com/d0ge/WebSocketTurboIntruder)
- [Turbo Intruder background](https://portswigger.net/research/turbo-intruder-embracing-the-billion-request-attack)
- [Server-side prototype pollution safe detection methods](https://portswigger.net/research/server-side-prototype-pollution#safe-detection-methods-for-manual-testers)
- [WS RaceCondition PoC (Java)](https://github.com/redrays-io/WS_RaceCondition_PoC)
- [RaceConditionExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/RaceConditionExample.py)
- [PingOfDeathExample.py](https://github.com/d0ge/WebSocketTurboIntruder/blob/main/src/main/resources/examples/PingOfDeathExample.py)
{{#include ../banners/hacktricks-training.md}}