You want more?
Further articles available here
This is how you can approach WebSocket Fuzzing
The tool support is not very advanced in the area of WebSockets, for example, although WebSockets can be captured in Burp and manually manipulated and repeated, there is no way to scan or fuzz WebSocket messages. A quick internet search shows that OWASP ZAP is supposed to have an integrated WebSocket fuzzing functionality, but the tested website could no longer be used as soon as it was passed through ZAP as a proxy, as the WebSocket connections were always closed immediately. Thus, ZAP was also ruled out as a possibility for automated evaluation of WebSockets. A slightly more in-depth internet search reveals some WebSocket fuzzers, but they are very outdated and still based on Python2 and could not be started in current test environments without effort. Accordingly, we decided to create our own WebSocket fuzzing script.
Investing time in developing our own script also makes sense if recent statements by PortSwigger are taken into account in the decision. According to PortSwigger, WebSocket fuzzing is not currently implemented and is something they hope to research in the future. Therefore, in the meantime, as long as there is no support from Burp, a solution of our own has to be found. PortSwigger cites that WebSocket scanning is difficult because it is not easy to determine cause and effect. This issue was also considered in the development of our script and it was decided not to include vulnerability detection logic in the script at this time. Instead, the script only triggers payloads and, if received, records the server’s responses. It is then left to the tester to manually process and interpret the elicited responses and other behaviour of the server. The purpose of the script is to save the tester the manual sending of many WebSocket messages.
The essential requirements for this script were deliberately kept low, so the script only needs to be able to successfully establish a WebSocket connection and then send a payload from a file. This was completed with the following function, shortened for the article:
def fuzzer(cookie, hostname, url, fuzz_values_file, websocket_messages_file, proxy_host, proxy_port, verbose): # Read fuzzing payloads from text file with open(fuzz_values_file, "r") as f: fuzz_values = [payload_parsing(line.rstrip('\n')) for line in f.readlines()] # Read WebSocket message from text file with open(websocket_messages_file, "r") as messages_file: for websocket_message in messages_file: websocket_message = websocket_message.strip() for fuzz_value in fuzz_values: # Create the WebSocket if proxy_host is None: ws = websocket.WebSocket() ws.connect("wss://"+hostname+url, cookie=cookie, origin="https://"+hostname) else: ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE}) ws.connect("wss://"+hostname+url, cookie=cookie, origin="https://"+hostname, http_proxy_host=proxy_host, http_proxy_port=proxy_port, proxy_type="http") # Replace FUZZ_VALUE with attack payload from the file message = websocket_message.replace("FUZZ_VALUE", fuzz_value) print("\n<----> WebSocket message that will be sent/fuzzed: " + message + "\n") # Send the fuzzed message over the WebSocket connection and wait for answer ws.send(message) ws.recv() ws.close()
In the very first version of the script, a manual adjustment of the script had to be made every time a WebSocket message was fuzzed, because the message to be fuzzed was located within the script. This was solved by moving the WebSocket messages to a second file. Although this creates a somewhat unwieldy nested for-loop, it is much easier to use during testing.
Also, in this version of the script, the payload parsing is designed for JSON, as in our case JSON messages were sent via WebSockets. Depending on the WebSocket messages encountered, this would also have to be optimised before fuzzing.
def payload_parsing(payload): payload = payload.replace('"', '\\"') return payload
The entire script has been made available on our GitHub. There are also examples of its effective use listed.
It is important to note when using this script that the script itself does not make any evaluations of the fuzzing results. This means that it is currently strongly recommended to run the script through a proxy such as Burp, so that the triggered responses can be further evaluated manually afterwards..
The following are tips for testers on how to use the script for best results: First, analyse how the website builds and sends the WebSocket messages. Sending a message should first be able to be repeated with the script without fuzzing, otherwise fuzzing makes little sense. During our testing, it was found that often more than one message needs to be sent over the WebSocket to get a response from the server. Accordingly, in the script, the possibility was provided to specify such “pre messages” before the actual fuzzing message is processed. The fuzzing of the WebSocket messages themselves is only as good as the compiled fuzzing payloads, accordingly such lists should be compiled with care.
After the messages have been successfully fuzzed, the following can be done to simplify the manual analysis: In the proxy used, only display the messages received from the server in the WebSocket history and sort them by size. This way it can be quickly recognised if there are messages with a deviating size, which can then be evaluated first. It is also possible to manually filter for expected error messages.
In addition to what the script provides in terms of testing possibilities, it should also be noted that there are other WebSocket specific vulnerabilities that are not covered by this script. How these areas of WebSockets can be tested has already been described in detail in one of our earlier Labs articles.
The following improvements have already been noted for this script and will be developed at a later date:
The provided script can take part of the manual processing of WebSocket messages off a tester’s hands. Testers using this script must however be aware that there is still manual effort involved in evaluating the messages generated by this script. Nevertheless, the script simplifies fuzzing considerably, as it allows far more messages to be sent than would be possible with just manually repeating messages. Although the script has already received some improvements and enhancements during testing, there are still areas where time can be invested to make the script even better to use for testers.
Our experts will get in contact with you!
Andrea Hauser
Andrea Hauser
Andrea Hauser
Andrea Hauser
Our experts will get in contact with you!