1 / 91

Buffer overflow attack and defense

Buffer overflow attack and defense. Prof. Stefano Bistarelli. C Consiglio Nazionale delle Ricerche Iit Istituto di Informatica e Telematica - Pisa. Università “G. d’Annunzio” Dipartimento di Scienze, Pescara. Errori del codice.

tuwa
Télécharger la présentation

Buffer overflow attack and defense

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Buffer overflow attack and defense Prof. Stefano Bistarelli CConsiglio Nazionale delle Ricerche IitIstituto di Informatica e Telematica - Pisa Università “G. d’Annunzio”Dipartimento di Scienze, Pescara

  2. Errori del codice • Un errore del codice può influire sulla sicurezza del software (in alcuni casi con conseguenze catastrofiche). • Ad esempio nel giugno 1996 il satellite europeo Ariane 5 è esploso subito dopo il lancio a causa di un errore nel software; il programma tentò di inserire un numero di 64 bit in uno spazio di 16 bit, provocando un overflow. S. Bistarelli - Metodologie di Secure Programming

  3. S. Bistarelli - Metodologie di Secure Programming

  4. Buffer overflow • Il problema dei buffer overflow è sicuramente quello più comune tra tutti i tipi di insicurezza nel codice C, mentre è praticamente assente in linguaggi di più alto livello che non lasciano al programmatore la gestione della memoria. • I problemi di buffer overflow sono stati la principale causa dei problemi di sicurezza riscontrati negli utlimi 10 anni. • La tecnica del buffer overflow consiste nel forzare la scrittura in memoria con una quantità di informazioni superiore a quella accettabile. Se il software è privo di controlli è possibile inserire del codice eseguibile (bytecode) in queste stringhe di overflow che consentono ad esempio di eseguire comandi su shell (shellcode). Inoltre se il software viene eseguito in modalità root un attacco di questo tipo può garantire il pieno possesso di tutte le funzionalità del sistema. • I buffer overflow possono essere eseguiti sulle seguenti zone di memoria: stack,heap e bss (block started by symbol). S. Bistarelli - Metodologie di Secure Programming

  5. Segmento testo Segmento dati Stack Organizzazione della memoria di un processo • Per capire la tecnica del buffer overflow è necessario studiare l'organizzazione della memoria di un processo (programma). • I processi sono divisi, in memoria, in tre regioni: testo, dati e stack. La regione testo è fissata, contiene il codice del programma ed è a sola lettura. Qualsiasi tentativo di scrittura provoca una violazione di segmento. La regione dati contiene i dati inizializzati e non (variabili statiche e globali) relativi al processo mentre la regione stack contiene i dati dinamici (utilizzati nella chiamata di funzioni). 0x00000000 Indirizzi di memoria bassi 0xFFFFFFFF Indirizzi di memoria alti S. Bistarelli - Metodologie di Secure Programming

  6. Indirizzi di memoria bassi codice Segmento testo costanti Dati variabili globali e statiche BSS variabili allocate dinamicamente Heap variabili locali, chiamate di funzioni Stack Indirizzi di memoria alti Organizzazione della memoria di un processo S. Bistarelli - Metodologie di Secure Programming

  7. … a volte considereremo il disegno opposto … S. Bistarelli - Metodologie di Secure Programming

  8. c b a Lo Stack • Lo stack (pila) è una struttura dati di tipo LIFO (Last In First Out) che consente di memorizzare un numero variabile di informazioni. • Questa struttura dati viene utilizzata all'interno dell'architettura degli elaboratori per gestire le chiamate di funzioni (call in assembly). La zona di memoria destinata alla gestione dello stack viene suddivisa logicamente in aree (stack frame) per ogni chiamata di funzione. x=pop push(x) Stack 1) x=a, 2) x=b, 3) x=c 1) x=c, 2) x=b, 3) x=a S. Bistarelli - Metodologie di Secure Programming

  9. Lo Stack e i registri di sistema • Ogni processo viene eseguito step-by-step tramite l'elaborazione di istruzioni successive. L'indirizzo di memoria dell'istruzione da eseguire, in un preciso istante, è contenuto nel registro di sistema EIP (Extended Instruction Pointer) a 32 bit (1dword). S. Bistarelli - Metodologie di Secure Programming

  10. Lo Stack e i registri di sistema • Oltre a questo registro di sistema esistono altri registri utili per la gestione di chiamate di funzioni (call). Il registro EBP (Extended Base Pointer) che punta alla base di uno stack frame ed il registro ESP (Extended Stack Pointer) che punta alla cima dello stack frame. S. Bistarelli - Metodologie di Secure Programming

  11. Lo Stack e i registri di sistema • Quando viene richiamata una funzione (call) il sistema inserisce nello stack l'indirizzo dell'istruzione successiva, push(EIP+4) dove 4 indica 4 byte (4byte=1dword), successivamente inserisce nello stack il puntatore alla base dello stack frame corrente, push (EBP) ed infine copia l'ESP attuale sull'EBP inizializzando così il nuovo stack frame. S. Bistarelli - Metodologie di Secure Programming

  12. EIP, EBP, ESP • EIP va in stack • EBP va in stack (chiamato SFP) • EBP’ = ESP • Settato nuovo ESP’ (lunghezza della procedura chiamata) S. Bistarelli - Metodologie di Secure Programming

  13. memoriabassa buffer flag SFP* EBP' nuovoEBP Indirizzo di ritorno (ret) a b memoriaalta Un esempio in C Analizziamo quest'esempio di codice in C per capire meglio l'allocazione dello stack frame:void test_function (int a, int b) { char flag; char buffer[10]; } int main() { test_function (1,2); exit(0); } EIP Stato dello stack frame Indirizzo di ritorno (ret) = EIP + 4 byte *SFP= Saved Frame Pointer, valore utilizzato per rispristinare lo stato originale di EBP (prima della chiamata di test_function();) S. Bistarelli - Metodologie di Secure Programming

  14. memoriabassa buffer flag SFP* EBP Indirizzo di ritorno (ret) a b memoriaalta Lo stack frame • Alle variabili locali della funzione test_function si fa riferimento mediante sottrazione del valore del frame pointer EBP e gli argomenti della funzione mediante addizione a tale valore. • Quando una funzione viene richiamata, il puntatore EIP diventa l'indirizzo di inizio del codice della funzione. • La memoria dello stack è utilizzata per le variabili locali e gli argomenti della funzione. Dopo il termine dell'esecuzione della funzione, l'intero stack frame viene estratto dallo stack in modo da riprendere l'esecuzione sull'istruzione di ritorno (ret). S. Bistarelli - Metodologie di Secure Programming

  15. Esempio di overflow Analizziamo quest'esempio di codice in C che provoca un overflow:void overflow_function (char *str) { char buffer[20]; strcpy(buffer, str); // Funzione che copia str nel buffer } int main() { char big_string[128]; int i; for(i=0; i < 128; i++) { big_string[i] = 'A'; } overflow_function(big_string); exit(0); } Questa istruzioneprovoca un overflow! S. Bistarelli - Metodologie di Secure Programming

  16. Segmentation fault Perchè il codice precedente provoca un Segmentation fault? 1) La prima chiamata di overflow_function inizializza correttamente lo stack frame: 2) Al momento del termine dell'esecuzione della funzione overflow_function, l'istruzione di ritorno è stata sovrascritta con il carattere A (segmentation fault!) memoriabassa memoriabassa } AA...A buffer 20 byte } SFP A Indirizzo di ritorno (ret) A 108 byte *str (argomento) A memoriaalta A S. Bistarelli - Metodologie di Secure Programming

  17. Buffer overflow (basati sullo stack) Cosa succede se l'istruzione di ritorno (ret) contiene un indirizzo di memoria valido? • In questo caso il processo continuerebbe indisturbato eseguendo l'istruzione successiva contenuta in ret. • Il buffer overflow basato sullo stack consiste proprio nello sfruttare tale possibilità sostituendo l'istruzione di ritorno ret con un nuovo puntatore ad una porzione di codice inserita manualmente da un intruso. • Come è possibile • modificare tale istruzione di ritorno ed • inserire arbitrariamente del codice in un processo? S. Bistarelli - Metodologie di Secure Programming

  18. Cos'è un Buffer Overrun • Si verifica quando i dati superano la dimensione prevista e sovrascrivono altri valori • È frequente soprattutto nel codice C/C++ non gestito • Può essere di quattro tipi: • buffer overrun basato sullo stack • buffer overrun dell'heap • Sovrascrittura della v-table e del puntatore a funzione • Sovrascrittura del gestore eccezioni • Può essere sfruttato dai worm S. Bistarelli - Metodologie di Secure Programming

  19. Possibili conseguenze dei sovraccarichi buffer S. Bistarelli - Metodologie di Secure Programming

  20. Dati Puntatore Dati Dati Puntatore Puntatore Ibuffer overrundell'heap • Sovrascrivonoidatimemorizzatinell'heap • Sono più difficili da sfruttare di un buffer overrun xxxxxxxxxxxxxx strcpy S. Bistarelli - Metodologie di Secure Programming

  21. Ibuffer overrundell'heap: example 1 class CustomerRecord { private: char szName[20]; char szAddress[10]; char szPassword[20]; char szCreditHistory[200]; char szBankDetails[25]; S. Bistarelli - Metodologie di Secure Programming

  22. void ChangeAddress (char *a) { strcpy (szAddress, a); } bool ChangePassword (char *newpwd, char *oldpwd) { bool res=false; if (strcmp (oldpwd, szPassword)==0) { strcpy (szPassword, newpwd); res=true; } return res; } S. Bistarelli - Metodologie di Secure Programming

  23. char * GetSensitiveData (char *pwd) { if (strcmp (pwd, szPassword)==0) { // return all the personal info! return "Here's all the personal info...\n"; } else return ""; } S. Bistarelli - Metodologie di Secure Programming

  24. Eseguire procedura • Come faccio ad ottenere • GetSensitiveData password • Se non conosco la password=secret?? • Trucco: • ChangeAddress … • Buffer overflow su ?? Heap!!  • char szAddress[10]; • char szPassword[20]; S. Bistarelli - Metodologie di Secure Programming

  25. Esempio di sovraccarico buffer basato sullo stack int main(int argc, char* argv[]) { //A blatant shortcut printf("Address of foo = %p\n", foo); printf("Address of bar = %p\n", bar); foo(argv[1]); return 0; } Attacco: lanciare bar … senza che codice lanci bar S. Bistarelli - Metodologie di Secure Programming

  26. void foo(const char* input) • { • char buf[10]; • //What? No extra arguments supplied to printf? • //It is a cheap trick to view the stack • printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n"); • //Pass the user input straight to secure code public enemy #1. • strcpy(buf, input); • printf("%s\n", buf); • printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n"); • } • void bar(void) • { • printf("The attack!\n"); • } S. Bistarelli - Metodologie di Secure Programming

  27. Devo passare dei parametri a foo, in modo tale che AL RITORNO mi vada prima ad eseguire bar!!! • Quindi devo far scrivere a foo sul suo indirizzo di ritorno l’indirizzo di bar S. Bistarelli - Metodologie di Secure Programming

  28. Eseguiamo codice } 00000000 00000A28 7FFDC000 0012FEE4 0040108A 0032116F buf SFP ret S. Bistarelli - Metodologie di Secure Programming

  29. 34333231 00000035 7FFDF000 0012FEE4 0040108A 0032116F Dove ho scritto su buffer 12345 ??? Conosciamo cygnus HexEditor Little-big endian Dopo chiamata procedura e input 12345 } buf SFP ret S. Bistarelli - Metodologie di Secure Programming

  30. Conosciamo cygnus HexEditor • 12345 • In esadecimale • 31 32 33 34 35 S. Bistarelli - Metodologie di Secure Programming

  31. Big-endian e little-endian sono due metodi differenti usati dai calcolatori per immagazzinare in memoria dati di dimensione superiore al byte (es. word, dword, qword). S. Bistarelli - Metodologie di Secure Programming

  32. big-endian è la memorizzazione che inizia dal byte più significativo per finire col meno significativo; è utilizzata dai processori Motorola, IBM e Sun e nei protocolli usati in Internet • viene anche chiamato network byte order. • little-endian è la memorizzazione che inizia dal byte meno significativo per finire col più significativo; è utilizzata dai processori Intel e Digital S. Bistarelli - Metodologie di Secure Programming

  33. Etimologia  • Big-endian e little-endian sono tratti dal nome dei due gruppi di persone incontrati dal personaggio fantastico Gulliver durante i suoi viaggi, in continuo litigio su quale lato fosse il migliore da rompere nelle uova. S. Bistarelli - Metodologie di Secure Programming

  34. esempi Nel caso di una DWORD, il numero esadecimale 0x01234567 verrà immagazzinato rispettivamente: Little endian Big endian +----+----+----+----+ +----+----+----+----+ |0x67|0x45|0x23|0x01| |0x01|0x23|0x45|0x67| +----+----+----+----+ +----+----+----+----+ byte: 0 1 2 3 0 1 2 3 (Negli esempi il valore in grassetto è il byte più significativo) S. Bistarelli - Metodologie di Secure Programming

  35. 34333231 00000035 7FFDF000 0012FEE4 0040108A 0032116F Dove ho scritto su buffer 12345 ??? Conosciamo cygnus HexEditor Little-big endian Dopo chiamata procedura e input 12345 } buf SFP ret Allora che input devo dare ?? per ottenere cosa ??? S. Bistarelli - Metodologie di Secure Programming

  36. Provare input 1234 • 12341234 • 1234123412 (10 byte) per buff • 123412341234 (posso facilmente salvarne di piu’ perche’ allocate multipli di dword) • Poi sovrascrivo indirizzo EBP e indirizzo di ritorno!! • Uso di editor esadecimale • FINE!!  S. Bistarelli - Metodologie di Secure Programming

  37. Weird example!!! LAB!

  38. the goal is to enter a serial and to get the good boy message • Using a buffer overflow of the stack!! • Tools: • Debugger • odbg110.zip • Disassembler • freeida43.exe • Hexeditor • cygnusfe.zip S. Bistarelli - Metodologie di Secure Programming

  39. Run the program: -- The analyst's weird crackme -- --------------------------------- enter your serial please: S. Bistarelli - Metodologie di Secure Programming

  40. !Run ida disassembler! • No way to go to the CODE:00401177 push offset aWooCongrats ; format S. Bistarelli - Metodologie di Secure Programming

  41. The source  int main(){ int i,len,temp; unsigned char name[75]; unsigned long check=0; printf("-- The analyst's weird crackme --\n"); printf("---------------------------------\n"); printf("enter your serial please:\n"); gets(name); asm{ nop}; len=strlen(name); S. Bistarelli - Metodologie di Secure Programming

  42. //cout << len; if (len < 25) goto theend; if (len > 120 ) goto theend; for (i=1; i <= len ; i++) { temp += name[i] ; } if (temp = 31337) goto theend; if (temp < 5000) goto theend; if (temp > 15000) goto theend; goto theend; printf("wOO! congrats ;)\n"); theend: getch(); return 0; } S. Bistarelli - Metodologie di Secure Programming

  43. Analisi dell’assembler: • Push (per mettere su stack parametri della gets, ) CODE:0040112E pop ecx CODE:0040112F lea eax, [ebp+s] ; buffer CODE:00401132 push eax ; s CODE:00401133 call _gets ; get entered serial CODE:00401138 pop ecx CODE:00401139 nop CODE:0040113A lea edx, [ebp+s] CODE:0040113D push edx ; s S. Bistarelli - Metodologie di Secure Programming

  44. Quanto è grande buffer in memoria? S. Bistarelli - Metodologie di Secure Programming

  45. EBP RET Vediamo struttura stack!! • Pulsante “open stack variables” (CTRL-K) FFFFFFB4 s db ? FFFFFFB5 db ? ; undefined :: :: FFFFFFFD db ? ; undefined FFFFFFFE db ? ; undefined FFFFFFFF db ? ; undefined 00000000 s db 4 dup(?) 00000004 r db 4 dup(?) 00000008 argc dd ? 0000000C argv dd ? ; offset (FFFFFFFF) 00000010 envp dd ? ; offset (FFFFFFFF) 00000014 } Buf di quante word? S. Bistarelli - Metodologie di Secure Programming

  46. Siccome indirizzo delle istruzioni di successo è 00401177 • dovremo provocare un buffer overflow in una procedura e inserire come codice di ritorno quello • Tramite editor esadecimale • 00401177  w@ S. Bistarelli - Metodologie di Secure Programming

  47. n.b • Finora abbiamo solo modificato puntatore .. • Non abbiamo iniettato noi codice (lo faremo nell’esercitazione linux) S. Bistarelli - Metodologie di Secure Programming

  48. Di solito, • Lo scopo di un buffer overflow attack è di modificare il funzionamento di un programma privilegiato in modo da prenderne il controllo e, nel caso il programma abbia sufficienti privilegi, prendere il controllo dell’ host. • Typically the attacker • is attacking a root program, and • immediately executes code similar to “exec(sh)” to get a root shell. S. Bistarelli - Metodologie di Secure Programming

  49. To achieve this goal, the attacker must achieve two sub-goals: • Arrange for suitable code to be available in the program's address space. • Get the program to jump to that code, with suitable parameters loaded into registers & memory. S. Bistarelli - Metodologie di Secure Programming

  50. The “buffer” part • how the attack code is placed in the victim program’s address space • Inject it! • It is already there • For instance, if the attack code needs to execute “exec(“/bin/sh”)”, and there exists code in libc that executes “exec(arg)” where “arg” is a string pointer argument, then the attacker need only change a pointer to point to “/bin/sh” and jump to the appropriate instructions in the libc library S. Bistarelli - Metodologie di Secure Programming

More Related