Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
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 ( 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
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.