[Ebook ita - security] introduzione alle tecniche di exploit - mori - ifoa - 2003

Post on 17-Aug-2015

18 views 1 download

Transcript of [Ebook ita - security] introduzione alle tecniche di exploit - mori - ifoa - 2003

Introduzione alle tecniche diExploit

IFOA24 Luglio 2003

Luigi MoriNetwork Security ManagerIntrinsiclm@intrinsic.it

Agenda

• Memory layout di un processoWin2000

• Stack Frame• Exploit• Shellcode• Note finali

Processo Win2000

• Lo spazio di indirizzamento è flat• Suddiviso in due regioni principali

– System space (Kernel)– User space (Programma e DLL)

• All’interno dello user space la memoriapuò essere suddivisa in ulteriori sezioni– Codice– Stack– Dati inizializzati– Dati non inizializzati

Memory layout

User Space(Programma, DLL, Dati, Stack,

Ambiente)

System Space(Kernel, Executive, Driver)

0x80000000

L’interfaccia fra i due spazi è la NTDLL.DLL

User Space

• Diviso in una serie di regioni• Ogni regione ha dei permessi di

accesso– codice: XR– dati non inizializzati: RWX– dati inizializzati: RX– stack: RWX

Esempio User Space

stack code datiinit dati code dati

init dati

prova.exe NTDLL.DLL

Stack Frame di una funzione C

int

f(char *s)

{

char c[16];

int i;

i = 1;

return i;

}

push ebp

mov ebp, esp

sub esp,20h

mov [ebp-20],1

...

Stack Frame di una funzione C

Registri salvati

Variabili locali

Frame ptrRet Address

Argomenti

• Registri Salvati. Sono i registrisalvati dalla calling convusata

• Frame pointer. E’ il valoresalvato del registro usatoper indirizzare le variabililocali (EBP)

• Ret Address. Indirizzo diritorno

• Argomeni. Argomentipassati

Stack Frame di f

s

Ret Address

Frame ptr

c

i• Nessun registro salvato• Le variabili locali sono

contigue

Agenda Exploit

• Buffer overflow– classico– frame pointer– heap

• Format String Vulnerabilities• Integer overflow

Buffer overflow classico

• Il padre di tutti i buffer overflow• Ideato da Aleph1 nell’articolo

“Smashing the stack for fun andprofit” nella e-zine Phrack #49

Funzione f

intf(char *s){

char c[16];int i;i = 1;strcpy(c,s);return i;

}

• La funzione strcpy copia idati da s in c senzacontrollare la dimensione

• Se la stringa puntata da sè più lunga di 16 byte cisono dei problemi

Problemi per f

• Se s è abbastanzalunga può andare asovrascrivere framepointer, return addresse altro ancora

• Questo può esseresfruttato da unattaccantea

Ret Address

Frame ptr

c

i

Problemi per f

• Se s è abbastanzalunga può andare asovrascrivere framepointer, return addresse altro ancora

• Questo può esseresfruttato da unattaccantea

Ret Address

Frame ptr

c

i

s

Attacco ad f

• Posso costruire s inmodo che la parteche va a sovrascriverel’indirizzo di ritornopunti all’interno deidati iniettati

• Quando f finsice il suolavoro invece disaltare indietro nellafunzione chiamantesalta nel buffer

a

Ret Address

Frame ptr

c

i

Attacco ad f

• Posso costruire s inmodo che la parteche va a sovrascriverel’indirizzo di ritornopunti all’interno deidati iniettati

• Quando f finsice il suolavoro invece disaltare indietro nellafunzione chiamantesalta nel buffer

a

Ret Address

Frame ptr

c

i

s

Nuovo ret

Anatomia di un exploit

Cuscino di NOP

Addr codice

payloada

Ret Address

Frame ptr

c

i

Anatomia di un exploit

• Il cuscino di NOP iniziale serve pernon dover essere eccessivamenteprecisi nello specificare l’indirizzo dijump

• Il creatore dell’exploit deve prestareattenzione ai check fatti sull’input(alfanumerico, solo 7bit, …)

• Il payload è la parte dell’exploit checompie l’azione vera e propria

Frame pointer overflow

• Buffer overflow in cui è possibilesovrascrivere solo il primo byte delframe pointer

• Vengono detti off-by-one• Spesso sono dovuti a differenti

implementazioni di una funzione supiù piattaforme (strncpy su Linux,Win32, …)

Frame pointer overflow

• Solamente un byte delframe pointer vienesovrascritto

• Dovuti ad errori nelcontrollo della lunghezza(<= invece di un < stretto)

Registri salvati

Variabili locali

Frame ptrRet Address

Argomenti

Frame pointer overflow

• Solamente un byte delframe pointer vienesovrascritto

• Dovuti ad errori nelcontrollo della lunghezza(<= invece di un < stretto)

Registri salvati

Variabili locali

Frame ptrRet Address

Argomenti

Come è possibile ?

g(){

…f();…

}

• La funzione f è attaccabile• Molte funzioni hanno all’inizio un

codice del tipo:

• Al termine invece:

• Se dentro f il frame pointer vienecambiato al termine di g vienemodificato lo stack pointer

push ebp

mov ebp, esp

mov esp, ebp

pop ebp

Difese da attacchi allo stack

• Stack non eseguibile– Al segmento di stack vengono rimossi i

diritti di esecuzione, i dati presenti sullostack non possono essere eseguiti

– Alcuni compilatori usano lo stack percreare trampolini verso altro codice

– Il codice per l’exploit potrebbe giàtrovarsi all’interno del programma èsufficiente passargli i dati giusti

Difese da attacchi allo stack

• Canarino– Il compilatore viene modificato in

modo da inserire un valore tra FramePointer e variabili in entrata ad ognifunzione

– All’uscita da ogni funzione si controllase il canarino è ancora vivo (intatto)

– Il canarino può essere un valorecasuale oppure semplicemente 0

Difendersi con il canarino

• Il canarino viene inserito inentrata alla funzione

• Viene controllato in uscita• Se non è intatto significa

che è stato sovrascritto el’esecuzione viene interrotta

• Si evita di eseguire il codicedell’exploit

Registri salvati

Variabili locali

Frame ptrRet Address

Argomenti

Canarino

Heap-based overflow

• Fino ad ora abbiamo visto soloattacchi allo stack

• E’ possibile anche attaccare bufferpresenti nell’area dati (heap)

Heap-based overflow

• Una volta sovrascritto ilbuffer è necessariotrovare un modo persaltarci dentro

• L’idea è disovrascrivere unpuntatore al codice inmodo da farlo puntaredentro al buffer

buffer

altre variabili

codice

Heap-based overflow

• Una volta sovrascritto ilbuffer è necessariotrovare un modo persaltarci dentro

• L’idea è disovrascrivere unpuntatore al codice inmodo da farlo puntaredentro al buffer

buffer

altre variabili

codice

exploit

Esempio di programma affetto

voidg(){}

voidmain(int argc, char **argv){

static struct {char buffer[10];void (*f)();

} s;

s.f = g;argv++;strcpy(&s.buffer,*argv);printf("%08x %08x\n",

&s.f, &s.buffer);s.f();

}

• Dando unargomentoabbastanza lungoè possibilesovrascrivere ilpuntatore afunzione f edirettore il flussodel programma

Situazioni tipiche di exploit

• Classi C++ (mix di puntatori afunzioni e dati)

• Funzioni di libreria che contengonopuntatori statici a funzioni (atexit, …)

• ...

Format String Exploits

• Sfruttano funzioni tipo printf

• Quando la format string può essereinfluenzata dall’utente è possibileche sia presente una Format StringVulnerability

printf(format_string, arg1, arg2, ….)

Format String Functions

• Le funzioni tipo printf accettano unaformat string ed un numero variabiledi argomenti

• In output viene generata unaversione trasformate della formatstring

Esempio

voidf(){ int i;

i = 5; printf(“prova %d %08x\n”, i, &i);}

output

prova 5 00130000

Format functions stack frame

• Il chiamante conosce ilnumero di argomentipassati, il chiamato no

• Il primo argomento è laformat string

• Il chiamato deduce dallaformat string il numero diargomenti

Registri salvati

Variabili locali

Frame ptrRet Address

Arg1Frmat str addr

...

Esempio funzione vulnerabile

voidf(char *s){

char buff[512];char outbuff[512];sprintf(buff,”Err: %s”,s);sprintf(outbuff,buff);

}

• Con il primo sprintfviene creata laformat string per ilsecondo

• Passando allafunzione una stringache funzioni daformat stringpossiamosovrascrivere lo stack

Esempio diformat string exploit

• Passo alla funzione f una stringa tipo“%s%s%s%s”

• Dopo il primo sprintf ho nel bufferbuff la stringa

• Nel secondo sprintf questa stringaviene usata come format string

“Err: %s%s%s%s”

Esempio di format stringexploit

• La funzione sprintf si aspettadi trovare 4 argomenti sullostack (uno per ogni %s)

• Quando cerca di accederea questi argomenti va atoccare il frame dellafunzione chiamante, inquesto caso f

• sprintf andrà a stamparevalori “casuali” dellamemoria del processo. Crashdel programma

Registri salvati

Variabili locali

Frame ptrRet Address

Frmat str addr

Frame di f

Eseguire codice arbitrario

• Sfruttando una format stringvulnerability è possibile anche fareseguire codice arbitrario alprocesso

• Il procedimento è abbastanzadelicato ma lo scopo ultimo èsempre lo stesso: far saltarel’esecuzione all’interno del bufferriempito con il codice dell’exploit

Integer overflow

• Sono gli errori più difficili da sfruttare• Sfruttano una delle caratteristiche

fondamentali dell’aritmetica deicalcolatori

Interi e linguaggio C

• Nel linguaggio ci sono diversi tipi di interi• Ogni tipo di intero è rappresentato da

una variabile con un certo numero di bit• Esempio su piattaforma Win32

– int è un intero a 32 bit– short è un intero a 16 bit

• Ogni intero può avere un valore massimopari a 2^(dimensione in bit)-1

Esempio di funzionevulnerabile

intcatvars(char *buf1, char *buf2, int len1, int len2){

char buff[256];

if ((len1+len2) > 256) return -1;

memcpy(buff,buf1,len1);memcpy(buff+len1,buf2,len2);

…return 0;

}

Il controllo (len1+len2) nontiene conto di un possibileinteger overflow. Al memcpyè quindi possibilesovrascrivere lo stack e siricade nel classico stack-based buffer overflow

Idea base degli exploit

• Tutti le tecniche di exploit che abbiamovisto si dividono in due parti:– iniezione del codice arbitrario in un buffer– dirottamento del programma verso quel

buffer

• E’ il dirottamento la parte più delicata eche differenzia una tecnica dall’altra

Codice iniettato

• Viene detto il payload dell’exploit• E’ il codice che ha il compito di

compromettere il sistema• Scrivere questo codice è complesso

e delicato• In genere il suo obbiettivo è quello

di aprire una porta di accesso alsistema (shellcode)

Come funziona ?

• Uno scrittore di shellcode deveaffrontare diversi problemi

• Il principale è la differenza tra levarie versioni del sistema operativo

• Il secondo è ottenere tutte lefunzioni che servono per svolgere illavoro

Sotto Win32

• Sotto Win32 le funzioni di sistemasono suddivisi in librerie caricatedinamicamente dal programma(DLL)

• Gli indirizzi delle funzioni all’internodelle librerie cambiano da versionea versione

Import & Export Tables

foo.exe kernel32.dll

import table di foo.exe import table di kernel32.dll

export table di kernel32.dll

Import & Export Tables

• In ogni eseguibile sotto Win32 (PE) cisono una import ed una exporttable

• Nella Import Table ci sono le libreriee le funzioni necessarie alfunzionamento del programma

• Nella Export Table ci sono gli indirizzidelle funzioni dell’eseguibileaccessibili agli altri programmi

Import & Export Table

• Al momento dell’esecuzione illoader di Win32 si occupa dicaricare tutte le DLL necessarie

• Completa quindi la Import Table deivari componenti con il contenutodelle altre Export Table

Accesso alle funzioni run-time

• Il codice iniettato deve avere un modoper accedere alle funzioni run-time

• Non può usare un indirizzo fisso perchépotrebbe cambiare da versione aversione

• Può utilizzare le funzioni GetProcAddress eLoadLibrary

• Con queste chiamate può avereaccesso a tutte le altre funzioni

• Per usarle però deve trovare il loroindirizzo

Shellcode Win32(IAT scanning)

• Per prima cosa il payload scandiscela IAT del suo eseguibile per trovarele chiamate LoadLibrary eGetProcAddress

• Sfrutta quindi queste due funzioniper ottenere l’indirizzo di tutte quelleche gli servono

Altre tecniche

• Ci sono altre tecniche usate dagliscrittori di exploit:– PEB– SEH

• Il problema che devono risolvere èsempre lo stesso: trovare unacostante tra le varie versioni delsistema operativo

Riflessioni

• Abbiamo visto una serie di attacchiche possono essere portati versoprogrammi con errori diprogrammazione

• Il problema è che questi errori nonsono macroscopici ma spesso sonoinezie

• Basta poco per rendere unprogramma vulnerabile

Sistemi di Tipi

• Il Tipo di una variabile definiscel’insieme dei valori che può assumeredurante l’esecuzione

• I linguaggi di programmazione sipossono classificare in base al lorosistema di tipi e alle sue caratteristiche

Language Safety

• Gli errori run-time possono essere distintiin due classi– trapped errors. Gli errori che vengono

rilevati– untrapped errors. Errori che non vengono

rilevati

• Un buon sistema di tipi può eliminarecompletamente la seconda classe dierrori rendendo il linguaggio safe

Exploit e sistemi di tipi

• Un exploit che sfrutta un qualcheoverflow genera un untrapped error

• E’ possibile eliminare questo tipo dierrori utilizzando linguaggi diprogrammazione safe

• Il linguaggio C non è safe

Bibliografia

• Memory layout Win2000– Solomon, Russanovich “Inside Microsoft Windows 2000”, Microsoft

Press– Articoli di Matt Pietrek su MSJ

• Stack overflow– Aleph1 “Smashing the stack for fun and profit”, Phrack Magazine

49– Dark Spyrit “Win32 Buffer Overflows”, Phrack Magazine 55– Dark Spyrit “Klog - The Frame Pointer overwrite, Phrack Magazine

55

• Heap overflow– Matt Conover “Heap overflows”

• Sistemi di tipi– Luca Cardelli “Type Systems”