
analisi cve-2024-42327
bersaglio: 10.129.231.176
Informazioni: So che il mio bersaglio è un server zabbix. Ho ricevuto un account utente predefinito per accedere a zabbix: utente matthew password 96qzn0h2e1k3. Questo account ha un utente predefinito, senza gruppi o privilegi aggiuntivi.
Come di consueto, iniziamo con l'enumerazione, faremo una scansione delle porte usando nmap.

L'output di nmap ci mostra che la porta predefinita ssh e apache2 sono anch'esse sulla porta predefinita. Abbiamo anche le porte 10051 e 10050 che eseguono qualche servizio zabbix.
Accediamo a zabbix inserendo l'IP nell'URL del browser e sulla porta http predefinita, porta 80.

Questa è la schermata di accesso di zabbix, accederò con l'utente che ho ricevuto


Nel piè di pagina, ho trovato la versione di zabbix:

Usando il padre degli asini (Google), ho cercato se esisteva già qualche CVE per questa versione di zabbix

Dopo un bel po' di ricerca, ho visto che questa versione è vulnerabile al CVE-2024-42327 che riguarda uno sfruttamento di SQL injection per ottenere dati dal database e scalare privilegi, e al CVE-2024-36467 che permette di cambiare il ruolo utente in superutente abusando di controlli di accesso assenti.
https://nvd.nist.gov/vuln/detail/CVE-2024-36467
https://nvd.nist.gov/vuln/detail/CVE-2024-42327
Nella documentazione di zabbix è spiegato come fare richieste HTTP per chiamare l'API.

https://www.zabbix.com/documentation/current/en/manual/api
Ho inviato la richiesta chiamando il metodo apiinfo.version che ci insegna nella documentazione

che ci ha restituito il seguente:
{"jsonrpc":"2.0","result":"7.0.0","id":1}
Per il test successivo ho cambiato alcuni parametri in questa richiesta per inviarla di nuovo.

In method, ho cambiato da apiinfo.version a user.login e aggiunto i parametri username e password. Anche questo l'ho visto nella documentazione di zabbix.

Ci ha restituito un token:
{"jsonrpc":"2.0","result":"9566174b00c9c3ca552abc1a52d670ba","id":1}
Dopo ancora un po' di ricerca, ho deciso di andare nel repository di zabbix su github
https://github.com/zabbix/zabbix
Ho cercato su CUser e trovato un file CUser.php

Abbiamo trovato la funzione user.update:
public function update(array $users) {
$this->validateUpdate($users, $db_users);
self::updateForce($users, $db_users);
return ['userids' => array_column($users, 'userid')];
}
Non ho trovato alcuna verifica di autorizzazione, quindi ho deciso di cambiare la mia funzione in una funzione di superutente, sono tornato alla richiesta e ho apportato le modifiche al payload.

Mi ha restituito un errore con un messaggio di invalid params.
Dopo un'altra lunga analisi del codice, abbiamo trovato questa funzione:
/**
* Additional check to exclude an opportunity to deactivate himself.
*
* @param array $users
* @param array $users[]['usrgrps'] (optional)
*
From this snippet, we understand that we cannot change our roles because our role is checked
from extracting our data from the API token, and verifying against the database if we are that user.
But following the code we see that usrgrps has no validation at all, and therefore can be abused
to add ourselves into multiple groups at once. As long as the group is not disabled and the group
allows GUI access we can abuse this to change our current role with the following command:
User ID 3 is matthew , User group 7 is the Zabbix administrators group and user group 13 is the
Internal group which both hold unrestrictive privileges. The response indicates that the change
was successful:
* @throws APIException
*/
private function checkHimself(array $users) {
foreach ($users as $user) {
if (bccomp($user['userid'], self::$userData['userid']) == 0) {
if (array_key_exists('roleid', $user) && $user['roleid'] !=
self::$userData['roleid']) {
self::exception(ZBX_API_ERROR_PARAMETERS, _('User cannot change
own role.'));
}
if (array_key_exists('usrgrps', $user)) {
$db_usrgrps = DB::select('usrgrp', [
'output' => ['gui_access', 'users_status'],
'usrgrpids' => zbx_objectValues($user['usrgrps'], 'usrgrpid')
]);
foreach ($db_usrgrps as $db_usrgrp) {
if ($db_usrgrp['gui_access'] == GROUP_GUI_ACCESS_DISABLED
|| $db_usrgrp['users_status'] ==
GROUP_STATUS_DISABLED) {
self::exception(ZBX_API_ERROR_PARAMETERS,
_('User cannot add himself to a disabled group or a
group with disabled GUI access.')
);
}
}
}
break;
}
}
}
Secondo questo snippet, non possiamo cambiare i nostri ruoli perché il nostro ruolo viene verificato estraendo i nostri dati dal token API e verificando nel database se siamo quell'utente. Ma analizzando il codice, vediamo che usrgrps non ha alcuna validazione e per questa mancanza di validazione, può essere abusato per aggiungerci a più gruppi contemporaneamente. Non c'è alcuna verifica per impedire a un utente di aggiungersi a gruppi a cui non dovrebbe avere accesso.
Proviamo a scalare privilegi per la mancanza di questa validazione, ho modificato il payload e inviato di nuovo la richiesta

userid 3 si riferisce all'id dell'utente matthew, usrgrps contiene una lista di ID di gruppo: 13 che è un gruppo interno e 7 che è il gruppo zabbix administrators. La nostra risposta dal server conferma il successo dell'operazione:
{"jsonrpc":"2.0","result":{"userids":["3"]},"id":1}
Ora possiamo estrarre i gruppi di utenti del nostro utente corrente. Modifichiamo la richiesta e inviamo di nuovo.

Verificando la risposta, vediamo che l'utente con ID 3 è nei gruppi di amministratori Interno e Zabbix.
{"jsonrpc":"2.0","result":[{"userid":"1","usrgrps":
[{"usrgrpid":"7","name":"Zabbix administrators"},
{"usrgrpid":"13","name":"Internal"}]},{"userid":"2","usrgrps":
[{"usrgrpid":"8","name":"Guests"}]},{"userid":"3","usrgrps":
[{"usrgrpid":"7","name":"Zabbix administrators"},
{"usrgrpid":"13","name":"Internal"}]}],"id":1}