Le but de ce TP est de se familiariser avec l'exploitation des corruptions mémoire, via l'exploitation d'un stack overflow simple.
En passant, nous allons apprendre à utiliser git, docker, et un debugger : gdb.
Utiliser la commande "git clone" pour cloner le repertoire git de ce TP sur cette machine.
jonathan@blackbox:~$ mkdir tp
jonathan@blackbox:~$ cd tp
jonathan@blackbox:~/tp$ git clone git@github.com:endrazine/cnam-tp2-sec108.git
Cloning into 'cnam-tp2-sec108'...
remote: Enumerating objects: 15, done.
remote: Counting objects: 100% (15/15), done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 15 (delta 1), reused 12 (delta 1), pack-reused 0
Receiving objects: 100% (15/15), 24.13 KiB | 4.83 MiB/s, done.
Resolving deltas: 100% (1/1), done.
jonathan@blackbox:~/tp$ ls
cnam-tp2-sec108
jonathan@blackbox:~/tp$
Vérifier que vous avez bien telechargé un fichier gdbinit ce faisant.
Nous allons utiliser le système de virtualisation docker afin de travailler sur les mêmes binaires compilés, et sur le même environnement.
Suivre les instructions de Docker: https://docs.docker.com/engine/install/
apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io
usermod -aG docker ubuntu
Utiliser la commande "docker login" pour s'identifier aupres du registry container d'OVH. Voir https://docs.docker.com/engine/reference/commandline/login/
jonathan@blackbox:~$ docker login 59b7c723.gra7.container-registry.ovh.net -u cnam -p XXXXXXXXXX
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/jonathan/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
jonathan@blackbox:~$
Les logins et mots de passe seront donnés en cours.
Utiliser la commande "docker pull" pour telecharger l'image docker. Voir https://docs.docker.com/engine/reference/commandline/pull/
jonathan@blackbox:~$ docker pull 59b7c723.gra7.container-registry.ovh.net/cnamtp/cnamtp:latest
latest: Pulling from cnamtp/cnamtp
35807b77a593: Already exists
a1b1132ae316: Pull complete
Digest: sha256:7707d94e423c84ae76011a2fda0d8ecf005726c5de6ba751bf59b41bd796f910
Status: Downloaded newer image for 59b7c723.gra7.container-registry.ovh.net/cnamtp/cnamtp:latest
59b7c723.gra7.container-registry.ovh.net/cnamtp/cnamtp:latest
jonathan@blackbox:~$
Tagger le container docker, le renommer cnamtp:latest:
jonathan@blackbox:~$ docker tag 59b7c723.gra7.container-registry.ovh.net/cnamtp/cnamtp:latest cnamtp:latest
jonathan@blackbox:~$
Utiliser la commande "docker images" pour lister les images telechargées. Quelle est la taille de l'image telechargée ? (Voir https://docs.docker.com/engine/reference/commandline/images/)
jonathan@blackbox:~$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
cnamtp latest b60f468601ea 14 minutes ago 492MB
59b7c723.gra7.container-registry.ovh.net/cnamtp/cnamtp latest b60f468601ea 14 minutes ago 492MB
jonathan@blackbox:~$
Utiliser la commande "docker run" pour lancer l'image. Voir https://docs.docker.com/engine/reference/commandline/run/
docker run -it --entrypoint /bin/bash cnamtp
Vérifier que l'image est bian lancée au moyen de la commande "docker ps". Voir https://docs.docker.com/engine/reference/commandline/ps/
jonathan@blackbox:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d4d598da900 cnamtp "/bin/bash" 46 seconds ago Up 42 seconds naughty_bhaskara
jonathan@blackbox:~$
Attention: Si vous travaillez dans docker, toute modification est perdue si vous ne sauvegardez pas les résultats au moyen de la commande "docker commit". https://docs.docker.com/engine/reference/commandline/commit/
Dans un second terminal, utiliser la commande "docker exec" pour obtenir un shell dans l'environement docker. Voir https://docs.docker.com/engine/reference/commandline/exec/
jonathan@blackbox:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d4d598da900 cnamtp "/bin/bash" 46 seconds ago Up 42 seconds naughty_bhaskara
jonathan@blackbox:~$ docker exec -it 4d4d598da900 /bin/bash
root@4d4d598da900:/#
Installer build-essential et gdb dans l'environement docker.
jonathan@blackbox:~$ docker exec -it 4d4d598da900 /bin/bash
root@4d4d598da900:/# apt update
Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
Get:2 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:3 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:4 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
(...)
root@4d4d598da900:/# apt install build-essential
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
(...)
0 upgraded, 84 newly installed, 0 to remove and 0 not upgraded.
Need to get 57.4 MB of archives.
After this operation, 256 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
(...)
Setting up gnupg (2.2.19-3ubuntu2.1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.2) ...
root@4d4d598da900:/#
root@4d4d598da900:/# apt install gdb
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
(...)
Need to get 30.1 MB of archives.
After this operation, 161 MB of additional disk space will be used.
Do you want to continue? [Y/n]
(...)
1. Africa 2. America 3. Antarctica 4. Australia 5. Arctic 6. Asia 7. Atlantic 8. Europe 9. Indian 10. Pacific 11. SystemV 12. US 13. Etc
Geographic area: 8
Please select the city or region corresponding to your time zone.
1. Amsterdam 6. Belgrade 11. Budapest 16. Gibraltar 21. Jersey 26. Ljubljana 31. Mariehamn 36. Oslo 41. Rome 46. Simferopol 51. Tirane 56. Vatican 61. Zagreb
2. Andorra 7. Berlin 12. Busingen 17. Guernsey 22. Kaliningrad 27. London 32. Minsk 37. Paris 42. Samara 47. Skopje 52. Tiraspol 57. Vienna 62. Zaporozhye
3. Astrakhan 8. Bratislava 13. Chisinau 18. Helsinki 23. Kiev 28. Luxembourg 33. Monaco 38. Podgorica 43. San_Marino 48. Sofia 53. Ulyanovsk 58. Vilnius 63. Zurich
4. Athens 9. Brussels 14. Copenhagen 19. Isle_of_Man 24. Kirov 29. Madrid 34. Moscow 39. Prague 44. Sarajevo 49. Stockholm 54. Uzhgorod 59. Volgograd
5. Belfast 10. Bucharest 15. Dublin 20. Istanbul 25. Lisbon 30. Malta 35. Nicosia 40. Riga 45. Saratov 50. Tallinn 55. Vaduz 60. Warsaw
Time zone: 37
Current default time zone: 'Europe/Paris'
Local time is now: Mon Sep 13 22:46:50 CEST 2021.
Universal Time is now: Mon Sep 13 20:46:50 UTC 2021.
(...)
Setting up shared-mime-info (1.15-1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.2) ...
root@4d4d598da900:/#
Utiliser la commande "exit" pour terminer la session.
Sauvegarder l'environement via la commande "docker commit" dont vous avez le la documentation ci dessus. Pour un exemple, voir : https://phoenixnap.com/kb/how-to-commit-changes-to-docker-image
root@4d4d598da900:/# exit
exit
jonathan@blackbox:~$ docker commit 4d4d598da900 cnamtp:latest
sha256:916e13640d6e67df835229a7537b521af59c6c5770ed475c6b89f492e580ea49
jonathan@blackbox:~$
Relancer une session docker au moyen de la commande "docker exec". Gdb et gcc sont ils toujours bien installés ?
jonathan@blackbox:~$ docker exec -it 4d4d598da900 /bin/bash
root@4d4d598da900:/#
Pour faciliter l'exploitation du programme vulnérable, il vous faut désactiver l'ASLR sur la machine hote.
Voir comment faire ici: https://askubuntu.com/questions/318315/how-can-i-temporarily-disable-aslr-address-space-layout-randomization
jonathan@blackbox:~$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
[sudo] password for jonathan:
0
jonathan@blackbox:~$ cat /proc/sys/kernel/randomize_va_space
0
jonathan@blackbox:~$
Le fichier gdbinit présent dans ce repertoire git permet d'obtenir une lecture plus simple dans gdb. Vous devez le copier (dans l'environement docker !) sous ~/.gdbinit et eventuellement /root/.gdbinit (attention au "." devant le nom de ficher). Vous pouvez sauver l'image docker via la commande "docker commit", comme vu précédemment.
root@41d4b0b83655:~# apt install gcc-multilib
Nous allons réaliser l'ecriture d'un exploit, etape par etape.
On cherche à écrire un programme minimal poc.c qui va déclencher la vulnérabilité.
Comme vu en cours, ceci peut se faire au moyen d'un "one liner" écrit en perl.
Ecrire un "one liner" perl qui déclenche la vulnérabilité. Quel est la taille minimal du payload à passer a l'application pour déclencher la vulnérabilité ?
Lancer le programme vulnérable dans gdb et lui donner un parametre:
jonathan@blackbox:~/CNAM/bo$ gdb ./bo
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./bo...
(No debugging symbols found in ./bo)
gdb$ r AAAAA...
Starting program: /home/jonathan/CNAM/bo/bo AAAAA...
Welcome: AAAAA... !
(...)
gdb$
Note: On utilise la commande "exit" pour sortir de gdb.
Utiliser votre "one liner" pour déclencher la vulnérabilité. Lorsque le programme crash, utiliser la commande "context" dans gdb pour visualiser la valeur des registres.
Modifier votre "one liner" pour que tous les bytes rééscris dans la stack valent 0x41 (equivalent à la lettre "A" en ASCII), sauf la valeur de "saved eip" qui doit être mise à 0x42424242 ("BBBB" en ASCII).
Créer un fichier exploit.c et son Makefile.
On souhaite utiliser l'appel systeme execve() dans exploit.c pour lancer le programme vulnérable avec notre payload (pour l'instant, le "one liner" écrit plus haut).
Le programme exploit ne doit pas prendre d'arguments, mais doit lancer le programme vulnérable avec des parametre hardcodés.
Verifier qu'en lancant le programme exploit, on execute bien le programme vulnérable, avec les arguments souhaités.
Lancer exploit dans gdb. Constater que l'on controle bien eip, la valeur de la prochaine instruction executée.
jonathan@blackbox:~/CNAM/bo/poc$ ls
Makefile bo poc poc.c
jonathan@blackbox:~/CNAM/bo/poc$ gdb ./poc
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./poc...
(No debugging symbols found in ./poc)
gdb$ r
Starting program: /home/jonathan/CNAM/bo/poc/poc
process 31682 is executing new program: /home/jonathan/CNAM/bo/poc/bo
Welcome: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB�������� !
Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
EAX: 0x00000000 EBX: 0x41414141 ECX: 0x00000000 EDX: 0x0804A016 o d I t S z a p c
ESI: 0xF7F8D000 EDI: 0xF7F8D000 EBP: 0x41414141 ESP: 0xFFFFDC30 EIP: 0x42424242
CS: 0023 DS: 002B ES: 002B FS: 0000 GS: 0063 SS: 002BError while running hook_stop:
Cannot access memory at address 0x42424242
0x42424242 in ?? ()
gdb$
Modifier votre exploit de manière à ce que le shellcode (tous les "A") soient remplacés par une instruction générant un SIGTRAP (utiliser l'opcode 0xCC au lieu de 0x41).
Modifier votre exploit, afin que l'adresse de retour ("BBBB", soit 0x42424242) pour qu'il pointe vers le début du pseudo-shellcode.
Executer exploit dans gdb. Verifier que le shellcode est bien executé (le programme doit se terminer via un signal SIGTRAP à l'execution du premier opcode 0xCC, au lieu de se terminer par un SIGSEGV, c'est dire une erreur de segmentation).
Attention: Les microprocesseurs Intel sont des processeurs "Little Endian". L'ordre des bytes n'est pas naturel...
Modifier votre programme en remplaçant le pseudo-shellcode précédent par un "vrai" shellcode: utliser celui vu en cours.
Vous pouvez remplacer les opcodes 0x41 qui restent par des NOPs (opcode 0x90).
Vérifier qu'en lançant votre exploit, vous executez bien votre shellcode.
Utiliser strace pour vérifier que l'execution de votre exploit lance bien le shellcode souhaité.
jonathan@blackbox:~/CNAM/bo/exploit$ ./exploit
Welcome: 1�Ph//shh/bin��PTSP��!�t�;��
�RS��̀������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ����������� !
$
Prérequis: Obtenir l'IP du container docker. Vous pouvez utiliser le shell script suivant:
for container in `docker ps|grep -v IMAGE|awk '{print $1}'`
do
echo "$container "|tr -d "\n"
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $container
done
Rechercher sur exploit-db.com un shellcode x86 qui ouvre un port sur la machine cible et y bind un terminal.
Lancer votre exploit.
Utiliser netcat pour vous connecter à l'IP de la machine cible et vérifiez que vous pouvez y entrer des commandes arbitraires.
Envoyer votre exploit final exploit.c sur mon email du CNAM : jonathan.brossard at lecnam.net
Good for you ! S'attacher à réaliser les wargames disponibles ici pour progresser: https://overthewire.org/wargames/