La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

Buffer overflow attack and defense

Presentazioni simili


Presentazione sul tema: "Buffer overflow attack and defense"— Transcript della presentazione:

1 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

2 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 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). 0x Indirizzi di memoria bassi Segmento testo Segmento dati Stack 0xFFFFFFFF Indirizzi di memoria alti S. Bistarelli - Metodologie di Secure Programming

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

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

8 S. Bistarelli - Metodologie di Secure Programming
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 c b a 1) x=c, 2) x=b, 3) x=a 1) x=a, 2) x=b, 3) x=c 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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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); buffer flag SFP* Indirizzo di ritorno (ret) a b memoria alta memoria bassa EBP' nuovo EBP Ricordiamoci che stack cresce da memoria alta verso memoria bassa 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 S. Bistarelli - Metodologie di Secure Programming
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). buffer flag SFP* Indirizzo di ritorno (ret) a b memoria alta memoria bassa EBP S. Bistarelli - Metodologie di Secure Programming

15 S. Bistarelli - Metodologie di Secure Programming
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 istruzione provoca un overflow! S. Bistarelli - Metodologie di Secure Programming

16 S. Bistarelli - Metodologie di Secure Programming
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!) memoria bassa memoria bassa } A A ... A buffer 20 byte } SFP A Indirizzo di ritorno (ret) A 108 byte *str (argomento) A memoria alta 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 S. Bistarelli - Metodologie di Secure Programming
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
Possibile conseguenza Obiettivo dell'hacker Violazione dell'accesso Realizzare gli attacchi DoS (denial of service) contro i server Instabilità Interferire con il normale funzionamento del software Inserimento di codice Ottenere privilegi per il proprio codice Sfruttare dati aziendali di vitale importanza Eseguire azioni distruttive S. Bistarelli - Metodologie di Secure Programming

20 I buffer overrun dell'heap
Sovrascrivono i dati memorizzati nell'heap Sono più difficili da sfruttare di un buffer overrun Dati Puntatore strcpy xxxxxxx xxxxxxx S. Bistarelli - Metodologie di Secure Programming

21 I buffer overrun dell'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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
Eseguiamo codice 00000A28 7FFDC000 0012FEE4 A F } buf SFP ret S. Bistarelli - Metodologie di Secure Programming

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

30 S. Bistarelli - Metodologie di Secure Programming
Conosciamo cygnus HexEditor 12345 In esadecimale S. Bistarelli - Metodologie di Secure Programming

31 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
esempi Nel caso di una DWORD, il numero esadecimale 0x verrà immagazzinato rispettivamente: Little endian Big endian |0x67|0x45|0x23|0x01| |0x01|0x23|0x45|0x67| byte: (Negli esempi il valore in grassetto è il byte più significativo) S. Bistarelli - Metodologie di Secure Programming

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

36 S. Bistarelli - Metodologie di Secure Programming
Provare input 1234 (10 byte) per buff (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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
Run the program: -- The analyst's weird crackme -- enter your serial please: S. Bistarelli - Metodologie di Secure Programming

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

41 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
//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 S. Bistarelli - Metodologie di Secure Programming
Analisi dell’assembler: Push (per mettere su stack parametri della gets, ) CODE: E pop ecx CODE: F lea eax, [ebp+s] ; buffer CODE: push eax ; s CODE: call _gets ; get entered serial CODE: pop ecx CODE: nop CODE: A lea edx, [ebp+s] CODE: D push edx ; s S. Bistarelli - Metodologie di Secure Programming

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

45 Vediamo struttura stack!!
Pulsante “open stack variables” (CTRL-K) FFFFFFB4 s db ? FFFFFFB db ? ; undefined :: FFFFFFFD db ? ; undefined FFFFFFFE db ? ; undefined FFFFFFFF db ? ; undefined s db 4 dup(?) r db 4 dup(?) argc dd ? C argv dd ? ; offset (FFFFFFFF) envp dd ? ; offset (FFFFFFFF) } Buf di quante word? EBP FFFFFFFF-FFFFFFB4 = 75 Multiplo di 4 = 76 Se introduco come password RET S. Bistarelli - Metodologie di Secure Programming

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

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

48 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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 S. Bistarelli - Metodologie di Secure Programming
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

51 S. Bistarelli - Metodologie di Secure Programming
The “overflow” part how the attacker overflows a program buffer to alter adjacent program state Overflow a buffer with weak bound check, with the goal of corrupting the state of an adjacent part of the program’s state (adjacent pointers) S. Bistarelli - Metodologie di Secure Programming

52 S. Bistarelli - Metodologie di Secure Programming
Le vie di ingresso!! S. Bistarelli - Metodologie di Secure Programming

53 Buffer overflow (basati sullo stack)
Ovviamente il processo deve avere delle "vie d'ingresso". Ad esempio dei parametri che l'utente può specificare nella linea di comando, dei pacchetti da inviare ad una porta in ascolto del processo (quest'ultimo caso è quello più pericoloso perchè consente di effettuari attachi da remoto). In questa sede consideriamo l'esempio classico di attacco basato sul buffer overflow dello stack su di un parametro del processo a linea di comando. Che tipo di codice è possibile inserire in un attacco basato su buffer overflow? Si deve utilizzare un bytecode, ossia un codice autonomo, scritto in linguaggio macchina, che non deve contenere determinati caratteri speciali nelle sue istruzioni perchè deve sembrare un buffer di dati. S. Bistarelli - Metodologie di Secure Programming

54 S. Bistarelli - Metodologie di Secure Programming
Un tipico esempio di bytecode è il cosiddetto shellcode. Ossia un bytecode che genera una shell. Se si riesce a manomettere un programma suid root in maniera che esegua una shellcode è possibile prendere il possesso di un sistema, avendo privilegi da root, mentre il sistema è convinto che il programma suid root stia ancora assolvendo i suoi compiti previsti. S. Bistarelli - Metodologie di Secure Programming

55 S. Bistarelli - Metodologie di Secure Programming
A questo punto sorgono due problemi: (1) Dal momento che dobbiamo inserire del codice di tipo bytecode nello stack, che è una struttura dinamica, come possiamo determinare la posizione assoluta in memoria della nostra prima istruzione bytecode? (2) Una volta determinata questa posizione come possiamo modificare l'istruzione di ritorno ret dello stack frame? Non è possibile determinare la posizione assoluta del bytecode nello stack, per questo motivo è necessario utilizzare un espediente, il NOP sled (NOP = nessuna operazione, sled è la traduzione di slitta) S. Bistarelli - Metodologie di Secure Programming

56 S. Bistarelli - Metodologie di Secure Programming
NOP è un istruzione assembler vuota, non esegue niente. Viene utilizzata per gestire sincronizzazioni su cicli di calcolo... La tecnica del NOP sled consiste nell'inserire prima del nostro bytecode un grande array di istruzioni NOP (una slitta di NOP). Così facendo anche se l'istruzione di ritorno (ret) dovesse saltare su una posizione qualsiasi della slitta di NOP alla fine il bytecode verrebbe comunque eseguito. Ciò non toglie che per risolvere il primo problema dobbiamo comunque avere una stima dell'indirizzo del bytecode. S. Bistarelli - Metodologie di Secure Programming

57 S. Bistarelli - Metodologie di Secure Programming
Una volta che abbiamo stimato la possibile posizione del nostro bytecode possiamo utilizzare un'altra tecnica per risolvere il secondo problema che consiste nel riempire la fine del nostro buffer, dopo il bytecode, con l'indirizzo di ritorno stimato. In questa maniera, purchè uno di questi indirizzi di ritorno sovrascriva l'indirizzo di ritorno reale, l'espediente darà il risultato desiderato. Utilizzando queste tecniche il nostro buffer avrà una forma del genere: NOP sled bytecode Indirizzo di ritorno ripetuto S. Bistarelli - Metodologie di Secure Programming

58 S. Bistarelli - Metodologie di Secure Programming
Di seguito è riportato il codice assembly (memorizzato in una variabile definita in C) di una shellcode (si veda il file exploit.c in allegato): char shellcode[] = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0" "\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d" "\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73" "\x68"; Gli step per l'esecuzione del ns. buffer overflow: 1) stima dell'indirizzo di ritorno (ret), nel ns. caso ret=stack pointer; 2) buffer= NOP sled + shellcode + indirizzo ret ripetuto; 3) esecuzione del programma vuln.c che ha vulnerabilità passandogli come parametro buffer il buffer costruito in exploit.c (tramite l'istruzione exec(“./vuln”,”vuln”,buffer,0)); S. Bistarelli - Metodologie di Secure Programming

59 S. Bistarelli - Metodologie di Secure Programming
Heap!! S. Bistarelli - Metodologie di Secure Programming

60 S. Bistarelli - Metodologie di Secure Programming
Un tipo di vulerabilità simile allo stack-based buffer overflow è lo heap-based buffer overflow che segue lo stesso principio ma partendo da variabili allocate nello heap, quindi non staticamente ma dinamicamente con funzioni della famiglia malloc(). Lo heap ("mucchio") è una zona di memoria allocata dinamicamente durante l'esecuzione (runtime) di un processo. Un array di caratteri, allocato dinamicamente attraverso una chiamata malloc/calloc fara' parte dello heap. In generale qualunque assegnazione dinamica di memoria contigua farà parte dello heap. Viceversa, quando la porzione di memoria non e' piu' utile, viene chiamata una funzione che libera tale zona di memoria: free(). S. Bistarelli - Metodologie di Secure Programming

61 Un semplice overflow basato su heap
Consideriamo l'esempio contenuto nel file heap.c (in allegato). In questo caso si allocano due variabili userinput e outputfile nello heap con dimensioni fisse e pari a 20 byte. Cosa succede se si inserisce un valore > di 20 byte in una delle due variabili? Si ha un overflow. E se le due variabili vengono allocate in memoria in zone contigue l'overflow su una di esse può sovrascrivere il contenuto dell'altra. char *userinput = malloc(20); char *outputfile = malloc(20); Ad esempio un overflow sulla variabile userinput provoca la sovrascrittura della variabile outputfile. Heap userinput 20 outputfile 20 S. Bistarelli - Metodologie di Secure Programming

62 S. Bistarelli - Metodologie di Secure Programming
Proviamo ad eseguire il programma heap.c $ ./heap prova ---DEBUG-- [*] 0x80499d8: prova [*] 0x80499f0: /tmp/notes [*] distance between: 24 Writing to “prova” to the end of /tmp/notes... Cosa succede se utilizziamo un parametro con più di 24 byte? $ ./heap test [*] 0x80499d8: test [*] 0x80499f0: test Writing to “ test” to the end of test... S. Bistarelli - Metodologie di Secure Programming

63 S. Bistarelli - Metodologie di Secure Programming
BSS S. Bistarelli - Metodologie di Secure Programming

64 Buffer overflow (basati su BSS, Block Started by Symbol)
I buffer overflow basati su BSS sfruttano lo stesso principio dei buffer overflow basati su heap. Le variabili globali e statiche di un programma vengono allocate nella zona di memoria BSS in maniera contigua. Un overflow di una di queste variabili provoca la sovrascrittura di altre variabili. Consideriamo l'esempio (bss_game.c, in allegato). In questo programma si utilizzano due variabili statiche: static char buffer[20]; static int (*function_ptr) (int user_pick); Come per l'esempio sullo heap è possibile provocare un overflow della variabile buffer (parametro del programma) sovrascrivendo il contenuto del puntatore a funzione function_ptr! In questo caso posso far eseguire un bytecode come per il buffer overflow basato sullo stack!!! S. Bistarelli - Metodologie di Secure Programming

65 Come evitare buffer overflow
S. Bistarelli - Metodologie di Secure Programming

66 Come difendersi dai buffer overrun
Utilizzare con particolare cautela le seguenti funzioni: strcpy strncpy CopyMemory MultiByteToWideChar Utilizzare l'opzione di compilazione /GS in Visual C++ per individuare i sovraccarichi buffer Utilizzare strsafe.h per un gestione del buffer più sicura S. Bistarelli - Metodologie di Secure Programming

67 S. Bistarelli - Metodologie di Secure Programming
La soluzione più immediata e sicura consiste nell'inserire controlli sulle dimensioni dei parametri inseriti dall'utente, in modo da assicurarsi che non si verifichino overflow. Molte volte, soprattutto in programmi complessi, l'utilizzo di controlli sulle dimensioni delle variabili può risultare pesante. Si possono così utilizzare funzioni che non provocano overflow anche in presenza di parametri sovradimensionati. Ad esempio l'utilizzo delle funzioni C strlcpy() e strlcat() al posto di strcpy(). Un alternativa è l'utilizzo di librerie considerate "sicure” progettate proprio per evitare buffer overflow. Ad esempio LibSafe (http://www.research.avayalabs.com/project/libsafe/). Altre possibilità di prevenire buffer overflow sono fornite da strumenti in grado di rilevare tali bug, come StackGuard (per i buffer overflow basati sullo stack). S. Bistarelli - Metodologie di Secure Programming

68 S. Bistarelli - Metodologie di Secure Programming
Defenses Writing correct code Code auditing Non executable buffer Data segment non executable Code pointer integrity checking detect that a code pointer has been corrupted before it is dereferenced. Stack Introspection by Snarskii Create a new libc Stackguard (Activation Record Integrity Checking) Pointguard (function pointer integrity checking) S. Bistarelli - Metodologie di Secure Programming

69 S. Bistarelli - Metodologie di Secure Programming
Defenses Array bounds checking The Compaq C compiler for the Alpha CPU (“-check_bounds”) : only explicit array references are checked, i.e. “a[3]” is checked, while “*(a+3)” is not since all C arrays are converted to pointers when passed as arguments, no bounds checking is performed on accesses made by subroutines dangerous library functions (i.e. strcpy()) are not normally compiled with bounds checking, and remain dangerous even with bounds checking enabled Richard Jones and Paul Kelly developed a gcc patch that does full array bounds checking for C programs. The performance costs are substantial Purify: is a memory usage debugging tool for C programs. Purify uses “object code insertion” to instrument all memory accesses. After linking with the Purify linker and libraries, one gets a standard native executable program that checks all of its array references to ensure that they are legitimate. imposes a 3 to 5 times slowdown. Type-Safe Languages S. Bistarelli - Metodologie di Secure Programming

70 Safe and unsafe functions

71 S. Bistarelli - Metodologie di Secure Programming
Strcpy vs strncpy char * strcpy ( char * destination, const char * source ); Copies the C string pointed by source into the array pointed by destination, including the terminating null character. To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source. S. Bistarelli - Metodologie di Secure Programming

72 S. Bistarelli - Metodologie di Secure Programming
Strcpy vs strncpy char * strncpy ( char * destination, const char * source, size_t num ); Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it. No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num. S. Bistarelli - Metodologie di Secure Programming

73 S. Bistarelli - Metodologie di Secure Programming
strncpy if the length of the src string is >= n, you end up without null termination char dest[LEN]; char *src; ... /* src is set to point to a source string of unknown length */ strncpy(dest,src,LEN); dest[LEN-1]='\0'; /* null terminate for safety */ S. Bistarelli - Metodologie di Secure Programming

74 S. Bistarelli - Metodologie di Secure Programming
strncpy Using strncpy() has performance implications, because it zero-fills all the available space in the target buffer after the ’\0’ terminator. a strncpy() of a 13-byte buffer into a 2048-byte buffer overwrites the entire 2048-byte buffer S. Bistarelli - Metodologie di Secure Programming

75 S. Bistarelli - Metodologie di Secure Programming
strnlcpy Look on the web!! Problemi di compatibilità!! S. Bistarelli - Metodologie di Secure Programming

76 S. Bistarelli - Metodologie di Secure Programming
Fail solo se input o buf e’ un illegal pointer Se input troppo lungo verrà troncato  S. Bistarelli - Metodologie di Secure Programming

77 S. Bistarelli - Metodologie di Secure Programming
Non si tronca il buffer, se troppo lungo si ottiene errore GESTITO!! S. Bistarelli - Metodologie di Secure Programming

78 S. Bistarelli - Metodologie di Secure Programming
Sprintf vs snprintf int sprintf (String, Format, [Value, ...]) char *String; const char *Format; The sprintf subroutine converts, formats, and stores the Value parameter values, under control of the Format parameter, into consecutive bytes, starting at the address specified by the String parameter. The sprintf subroutine places a null character (\0) at the end. You must ensure that enough storage space is available to contain the formatted string. S. Bistarelli - Metodologie di Secure Programming

79 S. Bistarelli - Metodologie di Secure Programming
Sprintf vs snprintf int snprintf (String, Number, Format, [Value, . . .]) char *String; int Number; const char *Format; The snprintf subroutine is identical to the sprintf subroutine with the addition of the Number parameter, which states the size of the buffer referred to by the String parameter. S. Bistarelli - Metodologie di Secure Programming

80 S. Bistarelli - Metodologie di Secure Programming
_snprintf In w32 environment Non setta il \0 finale!!!  S. Bistarelli - Metodologie di Secure Programming

81 S. Bistarelli - Metodologie di Secure Programming
Gets vs fgets char *gets(char *s); read a line of data from STDIN. gets continues to read characters until NEWLINE or EOF is seen The NEWLINE character is NOT placed in the buffer gets does NOT check the size of the buffer and overflow on the stack can occour. S. Bistarelli - Metodologie di Secure Programming

82 S. Bistarelli - Metodologie di Secure Programming
char *fgets(char *s, int n, FILE *stream); fgets is used to read a line of data from an external source. If fgets is reading STDIN, the NEWLINE character is placed into the buffer. it checks that the incoming data does not exceed the buffer size S. Bistarelli - Metodologie di Secure Programming

83 S. Bistarelli - Metodologie di Secure Programming
Use strsafe.h!! S. Bistarelli - Metodologie di Secure Programming

84 Secure Programming open-source software

85 S. Bistarelli - Metodologie di Secure Programming
Open vs closed source Open-source software is more secure than closed software E.S. Raymond, The Cathedral & the Bazaar: Musings on Linux and Open Source by an Accidental Revolutionary, O’Reilly & Assoc., 1999. And the contrary K. Brown, Opening the Open Source Debate, Alexis de Tocqueville Inst., 2002; brown_%1.html?L+scstore+llfs8476ff0a810a !!The defender can install and configure the SW with high security concerns!! !!The attacker know the source code!! (if the defender just install it wothout any personal configuration!) S. Bistarelli - Metodologie di Secure Programming

86 Toward a perfect software!
Software auditing which prevents vulnerabilities by searching for them ahead of time, with or without automatic analysis Vulnerability mitigation which are compile-time techniques that stop bugs at runtime Behavior management which are operating system features that either limit potential damage or block specific behaviors known to be dangerous S. Bistarelli - Metodologie di Secure Programming

87 S. Bistarelli - Metodologie di Secure Programming
SW auditing tools S. Bistarelli - Metodologie di Secure Programming

88 S. Bistarelli - Metodologie di Secure Programming
1. Software auditing Auditing source code for correctness!! Good practice!!  Difficult and time-consuming  Sardonix project (2003) Record which code has been audited and by whom Provide rank for people partecipating to the project (to be used in the resume) Help novice auditors with a lot of resources and FAQ Static analyzers Dynamic debuggers S. Bistarelli - Metodologie di Secure Programming

89 S. Bistarelli - Metodologie di Secure Programming
Sardonix resource Static analyzers Sintactically check the code Ok for strongly typed languages (Java, ML, …) But some false positive/negative Undecidable for for weakly typed languages (C, Perl, …) Use some heuristics Dynamic debuggers Run the program under test loads S. Bistarelli - Metodologie di Secure Programming

90 2. Vulnerability mitigation tools
S. Bistarelli - Metodologie di Secure Programming

91 S. Bistarelli - Metodologie di Secure Programming
3. Behaviour management S. Bistarelli - Metodologie di Secure Programming


Scaricare ppt "Buffer overflow attack and defense"

Presentazioni simili


Annunci Google