Contexte de la mission
Lors d'un récent test d'intrusion réalisé pour l'un de nos clients, nous avons été mandatés pour évaluer la sécurité d'un serveur web Linux exposé sur Internet. Le périmètre était clair : une application web et le serveur qui l'héberge. L'objectif, comme souvent, était de déterminer jusqu'où un attaquant pouvait aller à partir d'un point d'entrée externe.
Ce que nous avons trouvé illustre parfaitement un principe fondamental en cybersécurité : une vulnérabilité isolée n'est pas toujours critique, mais une chaîne de vulnérabilités bien exploitée peut mener à la compromission totale d'un système.
Dans cet article, nous allons détailler pas à pas le chemin complet, de l'accès initial en tant que simple utilisateur web jusqu'à l'obtention des privilèges root, en exploitant deux CVE récentes qui affectent la majorité des distributions Linux.
Phase 1 — Accès initial
Après une phase de reconnaissance et d'énumération de l'application web, nous avons identifié un vecteur d'attaque qui nous a permis d'obtenir un reverse shell sur le serveur en tant que www-data, l'utilisateur standard sous lequel tourne le service web.
À ce stade, nos privilèges étaient extrêmement limités. L'utilisateur www-data n'a généralement accès qu'aux fichiers nécessaires au fonctionnement de l'application et ne dispose d'aucun droit d'administration. C'est un point de départ, pas une fin en soi.
Phase 2 — Fouille du système et découverte de credentials
Une fois notre shell stabilisé, nous avons commencé l'énumération du système. L'une des premières choses que nous cherchons systématiquement, ce sont des fichiers de configuration susceptibles de contenir des identifiants.
Plus tôt dans la phase de test de l'application web, nous avions déjà identifié et exploité une vulnérabilité de type Local File Inclusion (LFI). Pour rappel, une LFI permet à un attaquant de forcer le serveur à lire et afficher le contenu de fichiers locaux auxquels il ne devrait normalement pas avoir accès. C'est exactement ce type de faille qui nous a permis de récupérer le contenu d'un fichier de configuration de l'application.
Dans ce fichier, nous avons trouvé des identifiants de connexion à une base de données MariaDB : un nom d'utilisateur et un mot de passe en clair, stockés dans la configuration applicative comme c'est malheureusement encore trop souvent le cas.
Phase 3 — Extraction d'un hash depuis MariaDB
Avec ces identifiants, nous nous sommes connectés à la base de données MariaDB directement depuis notre shell www-data . Une fois dans la base, nous avons énuméré les tables disponibles. L'une d'entre elles contenait des comptes utilisateurs avec, entre autres, des hashes de mots de passe.
Un hash en particulier a retenu notre attention : il correspondait à un nom d'utilisateur que nous avions aussi repéré dans le fichier /etc/passwd du serveur. Autrement dit, l'application partageait un compte avec un utilisateur système réel. C'est le genre de mauvaise pratique qui transforme une simple fuite de données applicative en vecteur d'escalade de privilèges.
Phase 4 — Cassage du hash avec Hashcat
Le hash récupéré a été soumis à Hashcat, l'un des outils de référence pour le cassage de mots de passe. Après identification du type de hash, nous avons lancé une attaque par dictionnaire :
Quelques heures plus tard, Hashcat nous a retourné le mot de passe en clair. Nous avons immédiatement testé une connexion SSH avec cet utilisateur.
Bingo. Nous étions désormais connectés en tant qu'utilisateur standard du système, avec un vrai shell interactif et des privilèges bien supérieurs à ceux de www-data.
Phase 5 — Énumération post-compromission et identification des CVE
C'est ici que la mission prend un tournant intéressant. Avec notre accès utilisateur, nous avons entamé une énumération approfondie du système à la recherche de vecteurs d'escalade de privilèges vers root.
Parmi les éléments relevés, un service a particulièrement attiré notre attention : UDisks2.
Qu'est-ce que UDisks2 ?
Pour les lecteurs moins techniques, UDisks2 est un service système présent par défaut sur l'immense majorité des distributions Linux (Ubuntu, Debian, Fedora, openSUSE…). Son rôle est de permettre aux utilisateurs de gérer des périphériques de stockage (clés USB, disques externes, images disque…) via une interface D-Bus, sans nécessiter de droits root.
Concrètement, c'est le composant qui fait que lorsque vous branchez une clé USB sur un poste Linux, elle se monte automatiquement. C'est pratique, mais c'est aussi un service qui tourne avec des privilèges élevés et qui interagit directement avec le système de fichiers.
En vérifiant la version d'UDisks2 et la configuration du système, nous avons identifié que la machine était potentiellement vulnérable à deux CVE récentes, découvertes par l'équipe Qualys Threat Research Unit (TRU) en juin 2025 :
- CVE-2025-6018 — Élévation de privilèges via une mauvaise configuration PAM
- CVE-2025-6019 — Élévation de privilèges vers root via libblockdev/UDisks2
Ces deux failles sont conçues pour être chaînées : la première ouvre la porte, la seconde permet de la franchir.
Phase 6 — CVE-2025-6018 : détourner PAM pour obtenir le statut "allow_active"
Le problème
Sur un système Linux, le framework PAM (Pluggable Authentication Modules) gère l'authentification et les sessions utilisateur. En parallèle, Polkit est le mécanisme qui décide quelles actions privilégiées un utilisateur a le droit d'effectuer (monter un disque, redémarrer le système, etc.).
Polkit fait une distinction fondamentale entre un utilisateur physiquement présent devant la machine (session de type "console") et un utilisateur connecté à distance (SSH par exemple). Les actions sensibles comme le montage de périphériques de stockage sont réservées aux utilisateurs dits allow_active, c'est-à-dire ceux qui sont considérés comme physiquement présents.
La CVE-2025-6018 exploite une mauvaise configuration dans la chaîne PAM, plus précisément dans le module pam_env. Ce module lit par défaut le fichier ~/.pam_environment de l'utilisateur lors de l'authentification. Le problème, c'est que ce fichier est contrôlé par l'utilisateur lui-même.
L'exploitation
En injectant des variables d'environnement spécifiques dans le fichier ~/.pam_environment, un attaquant peut manipuler la façon dont pam_systemd enregistre la session. Le résultat : une session SSH se retrouve marquée comme Active=yes par systemd-logind, ce qui la rend équivalente à une session console physique aux yeux de Polkit.
Phase 7 — CVE-2025-6019 : de allow_active à root via UDisks2
Le principe de la vulnérabilité
Maintenant que nous disposons du statut allow_active, nous pouvons interagir avec UDisks2 sans authentification supplémentaire. C'est ici qu'intervient la CVE-2025-6019, qui réside dans libblockdev, la bibliothèque bas niveau utilisée par UDisks2 pour les opérations sur les périphériques bloc.
Le cœur du problème est le suivant : lorsque UDisks2 effectue certaines opérations de maintenance sur un système de fichiers (comme un redimensionnement ou une vérification), il doit temporairement monter le filesystem. Or, libblockdev effectue ce montage temporaire dans /tmp sans appliquer les flags de sécurité nosuid et nodev.
Pour les non-initiés, le flag nosuid est un mécanisme de sécurité crucial. Lorsqu'un filesystem est monté avec nosuid, le système ignore le bit SUID des exécutables qu'il contient. Le bit SUID permet à un programme de s'exécuter avec les droits de son propriétaire (souvent root) plutôt qu'avec ceux de l'utilisateur qui le lance. Sans nosuid, un attaquant peut placer un binaire SUID-root sur le filesystem et l'exécuter pour obtenir un shell root.
L'exploitation étape par étape
Étape 1 : Création de l'image XFS malveillante
Sur notre machine d'attaque, nous avons préparé une image disque au format XFS contenant un binaire bash avec le bit SUID activé et appartenant à root :
Étape 2 : Transfert et montage de l'image sur la cible
Après avoir transféré l'image sur le serveur compromis, nous l'avons montée en tant que loop device via UDisks2 :
Cette commande fonctionne sans mot de passe grâce au statut allow_active obtenu via la CVE-2025-6018. UDisks2 accepte notre requête comme si nous étions un utilisateur local assis devant la machine.
Étape 3 : Déclenchement de la vulnérabilité via D-Bus
Nous avons ensuite lancé un watcher en arrière-plan, un script qui surveille en continu l'apparition du binaire SUID dans les répertoires temporaires, et déclenché l'opération de redimensionnement (ou vérification) du filesystem via D-Bus :
# Watcher en arrière-plan
cd /tmp while true; do for f in /tmp/blockdev*/bash; do [ -e "$f" ] && exec "$f" -p done done &
#Déclenchement via D-Bus
gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/loop0 --method org.freedesktop.UDisks2.Filesystem.Resize 0 '{}'
Ce qui se passe en coulisses : UDisks2 reçoit l'ordre de redimensionner le filesystem XFS. Pour ce faire, libblockdev monte temporairement l'image dans un répertoire /tmp/blockdev* — sans le flag nosuid. Pendant cette brève fenêtre, notre binaire bash avec le bit SUID-root est accessible et exécutable.
Étape 4 : Obtention du shell root
Notre watcher détecte le montage temporaire et exécute immédiatement le binaire SUID :
/tmp/blockdev*/bash -p
Le flag -p indique à bash de ne pas abandonner les privilèges hérités du bit SUID. Résultat :
Nous sommes root et nous disposons désormais des privilèges d'administration complets sur le serveur.
Récapitulatif de la kill chain
Pour résumer le chemin complet parcouru :
Impact et portée
L'impact de cette chaîne d'attaque doit être pris très au sérieux par les décideurs en sécurité, et ce pour plusieurs raisons.
UDisks2 est omniprésent. Ce service est activé par défaut sur la quasi-totalité des distributions Linux en entreprise, y compris les serveurs. D'après les analyses de Qualys, environ 98% des systèmes Linux d'entreprise embarquent UDisks2 en configuration par défaut. Cela signifie que la surface d'attaque est considérable.
Le chaînage rend l'exploitation triviale. Individuellement, chacune de ces CVE nécessite des préconditions. Ensemble, elles forment un chemin direct de "utilisateur standard" vers "root" en quelques secondes, avec des outils déjà présents sur le système. Des PoC publics sont disponibles sur GitHub, ce qui abaisse considérablement la barrière technique pour un attaquant.
L'accès root ouvre la porte à tout. Désactivation des outils de détection (EDR), installation de backdoors persistantes, exfiltration de données, mouvement latéral vers d'autres machines du réseau — un seul serveur compromis peut devenir le point de départ d'une compromission à grande échelle.
Recommandations
À l'issue de cette mission, nous avons formulé les recommandations suivantes à notre client :
Corriger immédiatement les vulnérabilités. Les éditeurs (SUSE, Ubuntu, Debian, Fedora) ont publié des correctifs pour les deux CVE. La mise à jour des paquets udisks2, libblockdev et pam doit être priorisée sur l'ensemble du parc.
Durcir la configuration Polkit. Même après le patch, il est recommandé de modifier la règle Polkit pour org.freedesktop.udisks2.modify-device en remplaçant allow_active: yes par auth_admin. Cela force une authentification administrateur pour toute opération de montage, même pour les sessions locales.
Désactiver user_readenv dans la configuration PAM. Le module pam_env ne devrait pas lire les fichiers d'environnement contrôlés par les utilisateurs (~/.pam_environment), en particulier dans la configuration SSH.
Éviter le partage de credentials entre l'application et le système. Les comptes applicatifs et les comptes système doivent être strictement séparés. Un identifiant de base de données ne doit jamais correspondre à un utilisateur Linux.
Surveiller les montages dans /tmp. La détection de loop devices montés dans des répertoires temporaires, en particulier sans le flag nosuid, constitue un bon indicateur de compromission (IoC) pour les équipes SOC.
Durcir les configurations MariaDB/MySQL. Restreindre les connexions à la base de données, utiliser des comptes avec des privilèges minimaux, et ne jamais stocker de credentials en clair dans les fichiers de configuration de l'application.
Conclusion
Cette mission illustre pourquoi le pentest reste indispensable. Aucune des vulnérabilités exploitées ici n'était particulièrement exotique prise isolément : une LFI, des credentials en clair, un hash faible, une mauvaise configuration PAM, un service système avec un défaut de montage. C'est leur combinaison qui a rendu l'attaque dévastatrice.
La sécurité d'un système ne se mesure pas à sa vulnérabilité la plus critique, mais à la plus longue chaîne d'exploitation qu'un attaquant peut construire. Chaque maillon faible compte, et la défense en profondeur n'est pas un luxe, c'est une nécessité.
Les CVE-2025-6018 et CVE-2025-6019 affectent potentiellement la majorité de votre parc Linux. Si ce n'est pas déjà fait, vérifiez vos versions d'UDisks2 et de libblockdev, et appliquez les correctifs sans délai.