Dott. Ing. Davide Maiorca

Documenti analoghi
Esercitazione 4. Comandi iterativi for, while, do-while

Linguaggio C: introduzione

INDICE. Vista Libretto Livello Digitale 2. Importazione di dati da strumento 3. Inserisci File Vari 5. Compensazione Quote 5.

Laboratorio di Architettura degli Elaboratori

Mini-Corso di Informatica

Introduzione alle macchine a stati (non definitivo)

Strumenti per l Analisi Statica e Dinamica di Eseguibili

La protezione dai memory error exploit

1 Definizione di sistema lineare omogeneo.

Laboratorio di Programmazione Lezione 1. Cristian Del Fabbro

Somma di numeri floating point. Algoritmi di moltiplicazione e divisione per numeri interi

Procedura operativa per la gestione della funzione di formazione classi prime

Corso di Laurea Ingegneria Informatica Laboratorio di Informatica

Fondamenti VBA. Che cos è VBA

Fortran in pillole : prima parte

1 L estrazione di radice

4 GLI ARRAY E LE STRINGHE

Input/output in C e in C++

Il calcolatore. Architettura di un calcolatore (Hardware)

2) FILE BINARI: è una sequenza di byte avente una corrispondenza uno a uno con la sequenza ricevuta dal dispositivo esterno.

Sistemi Web per il turismo - lezione 3 -

EXCEL: FORMATTAZIONE E FORMULE

FUNZIONI DI BASE PANNELLO SMS

Corso di Sicurezza Informatica

VBA è un linguaggio di scripting derivato da Visual Basic, da cui prende il nome. Come ogni linguaggio ha le sue regole.

Introduzione a Visual Basic Lezione 2 Cicli e anomalie

Il generatore di numeri casuali

Manuale di Aggiornamento BOLLETTINO. Rel B. DATALOG Soluzioni Integrate a 32 Bit

Laboratorio di Architettura lezione 5. Massimo Marchiori W3C/MIT/UNIVE

UD4 - MATLAB. M-file. Efficienza degli algoritmi. Formati d uscita

Individuazione di sottoproblemi

File di script. I File di Script Corso 2D - R.Virili 1

x 2 + (x+4) 2 = 20 Alle equazioni di secondo grado si possono applicare i PRINCIPI di EQUIVALENZA utilizzati per le EQUAZIONI di PRIMO GRADO.

Unità Didattica 3 Linguaggio C. Generalità sulle Funzioni. Variabili locali e globali. Passaggio di parametri per valore.

Informatica B. Sezione D. Scuola di Ingegneria Industriale Laurea in Ingegneria Energetica Laurea in Ingegneria Meccanica

Layout Editor e Stampa

Disequazioni - ulteriori esercizi proposti 1

Jclic Download e installazione

La codifica. dell informazione

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1

Numeri frazionari. sistema posizionale. due modi: virgola fissa virgola mobile. posizionale, decimale

7 Disegni sperimentali ad un solo fattore. Giulio Vidotto Raffaele Cioffi

OPERAZIONI CHIUSURA E APERTURA Note operative

PROGRAMMAZIONE STRUTTURATA

Data Import e Probabilità. Renato Mainetti

Relazione di fisica. Come farla e/o correggerla?

PSICOMETRIA. Esercitazione n.1. C.d.L. Comunicazione e Psicologia a.a. 2012/13

Variabili. Unità 2. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

per immagini guida avanzata Modificare il contenuto del foglio di lavoro Geometra Luigi Amato Guida Avanzata per immagini Excel

Lezione 4. Sommario. L artimetica binaria: I numeri relativi e frazionari. I numeri relativi I numeri frazionari

Modulo1. Ricercare nelle mappe

TOP DOWN. Compiti in classe proposti Modulo 1 JUVENILIA SCUOLA. Iacobelli Ajme Marrone

ARCHITETTURA DI UN SISTEMA DI ELABORAZIONE

VALORIZZAZIONE MOVIMENTI DI SCARICO E VALORIZZAZIONE TRASFERIMENTO COSTI DI ANALITICA

Che cos'è un Power Point

Programma per la generazione di filastrocche

Aggiorna. La Funzione Aggiorna Listino Aggiornare Listino Pr7 / Le connessioni / Listino METEL. Aggiorna Lis no. Aggiornamento del listino

Home Page. Title Page. Contents. Laboratorio di LATEX. Page 1 of 16. Go Back. maggio Full Screen. Close. Quit

Architettura degli elaboratori Docente:

Compilazione on-line del Piano di Studio

Sito web Telefono (Carmine)

Ministero della Salute

TEOREMA DEL RESTO E REGOLA DI RUFFINI

MANUALE UTENTE PROCEDURA PLANET WEB INTERPRISE (II edizione)

Sistemi Operativi. Gianluca Della Vedova. Sistemi Operativi. Gianluca Della Vedova. Sistemi Operativi. Gianluca Della Vedova.

Costruiamo la STRISCIA DELLE MISURE. decametro metro decimetro. Tm Gm Mm km hm dam m dm cm mm µm nm pm

Metodo di Gauss-Jordan 1

Modulo 17: Invio del BF tramite

1.1.3 Dispositivi di memorizzazione Sapere come viene misurata la memoria di un computer: bit, byte, KB, MB, GB, TB.

STRINGHE: ARRAY DI CARATTERI! a p e \0

Gestione Commissioni Esami

Informatica Teorica. Macchine a registri

Informatica d ufficio

Esame Laboratorio di Sistemi Operativi Cognome Nome Mat.

DESCRIZIONE CREAZIONE APP Si suddivide in 4 fasi di lavoro: 1. PIANIFICAZIONE; 2. PROGETTAZIONE; 3. SVILUPPO; 4. DISTRIBUZIONE.

Configurazione Posta Elettronica istituzionale con

Codice Gray. (versione Marzo 2007)

Come utilizzare i riferimenti assoluti e relativi in Microsoft Excel

4 0 = 4 2 = 4 4 = 4 6 = 0.

Navigare in Internet Laboratorio di approfondimento la creazione di siti web e/o blog. Marco Torciani. (Seconda lezione) Unitre Pavia a.a.

Introduzione al Linguaggio C ed all IDE DEV-C++

Manuale utente Soggetto Promotore Erogatore Politiche Attive

Oggetto: Utility per la variazione massiva del codice IVA.

Exploiting di applicazioni vulnerabili a buffer overflow sotto Linux

Cos è un algoritmo. Si dice algoritmo la descrizione di un metodo di soluzione di un problema che sia

Rappresentazioni numeriche

Heap e code di priorità

Esercitazioni di Reti Logiche. Lezione 1 Rappresentazione dell'informazione. Zeynep KIZILTAN zkiziltan@deis.unibo.it

MedLeg On WEB Portale Visite Fiscali V Manuale Utente - MedLeg On WEB. Portale Visite Fiscali. Manuale Utente. Versione 11.

Transcript:

Pattern Recognition and Applications Lab Attacchi Base: Buffer Overflow Dott. Ing. Davide Maiorca davide.maiorca@diee.unica.it Corso di Sicurezza Informatica A.A. 2014/2015 Dipartimento di Ingegneria Elettrica ed Elettronica Università di Cagliari, Italia

Sommario Introduzione Analisi di un Programma Vulnerabile Altri Elementi Assembly Analisi funzioni Exploiting Analisi dello stack vulnerabile Attacco allo stack Contromisure

Introduzione

Introduzione Vulnerabilità Finora abbiamo analizzato un eseguibile senza possederne il suo sorgente La prossima domanda è: che relazione ha il reverse engineering con la sicurezza? Un attaccante può analizzare un eseguibile al fine di trovare delle vulnerabilità Una vulnerabilità è un errore di programmazione il cui sfruttamento può portare ad una violazione di integrità e confidenzialità di un sistema Sono state date tante definizioni di vulnerabilità (ISO, NIST, ENISA ) Avete già visto degli esempi Cross Site Scripting SQL Injection In questa lezione analizzeremo la vulnerabilità «regina» legata all esecuzione di un programma, ovvero il buffer overflow

Introduzione Buffer Overflow Vulnerabilità concernente la gestione della memoria e, in particolare, una cattiva gestione dello stack Potete già immaginare di cosa si tratti dal nome Un buffer è una zona di memoria pensata per contenere dei dati La particolarità di questa zona è che la dimensione dei dati è prefissata L esempio più classico di buffer è, ad esempio, un array Un overflow accade quando inseriamo dei dati che superano la capacità del buffer Banalmente: inserite in memoria una stringa di 5 caratteri in un buffer di 4 caratteri CIAOO -> C I A O O char str[3] OVERFLOW!

Challenge! Aprite il programma «invincibile» Dovete indovinare il codice segreto! Ma l impresa non sembra così semplice Per «sconfiggere» il programma «invincibile» ci serve un cambio di prospettiva Chiediamoci: il programma è sicuro? In questa lezione imparerete cosa può succedere quando un programma è vulnerabile ad un buffer overflow In particolare, imparerete a sfruttare un buffer overflow a vostro vantaggio Anche i programmi invincibili (ma insicuri ) possono essere sconfitti!

Analisi Programma Vulnerabile

DISCLAIMER I VALORI DEI REGISTRI POSSONO ESSERE DIVERSI A SECONDA DELLA VOSTRA ARCHITETTURA E VENGONO RIPORTATI SULLE SLIDES BASANDOSI SU CIO CHE E STATO MOSTRATO A LEZIONE

Analisi Programma (prima occhiata) Il programma vi chiede di inserire un codice di massimo 3 cifre Notate come il codice sia sempre errato (a meno di clamorosi colpi di fortuna ) Il massimo di 3 cifre dovrebbe stuzzicarvi Cosa succede se inserite più di 3 cifre? Proviamo con 5-10 cifre Apparentemente non succede niente Adesso proviamo con 15 cifre Perdete comunque Ma ricevete un errore di segmentation fault! Segmentation fault avviene quando il programma tenta di scrivere dei dati in memoria in segmenti non pertinenti Ad esempio, tento di scrivere in un segmento che non dispone del flag w Questo errore non dovrebbe mai comparire E il primo indizio che il programma possa essere vulnerabile!

Analisi Statica Programma Vediamo di disassemblare l eseguibile objdump d invincible Come prima, cerchiamo di individuare delle funzioni che abbiano dei nomi interessanti main inserire_codice genera_codice win lose Adesso guardiamo la funzione main, in particolare le chiamate call Vediamo quest ordine di chiamate: genera_codice puts inserire_codice win lose

Elementi di Assembly X86 (2) Altre istruzioni JMP <offset>: Salto non condizionato CMP: Confronta i contenuti di due registri (o registi e memoria) ed imposta un flag speciale a 1 se i due elementi hanno lo stesso valore JNE <offset> (di solito accoppiato con cmp): salta all offset se il flag speciale è impostato a zero (quindi se i due elementi confrontati con cmp non sono uguali) JEQ <offset> (di solito accoppiato con cmp): salta all offset se il flag speciale è impostato a zero (quindi se i due elementi confrontati con cmp non sono uguali) LEA address, register: carica un indirizzo di memoria su un registro SAR, n_bit, reg: esegue uno shift di n bit sul valore del registro reg IMUL, reg, value: moltiplica il valore contenuto di un registro per un valore intero

Analisi Main (1) Naturalmente, guardare la sequenza di chiamate non è sufficiente! 08048597 <main>: 8048597: push %ebp 8048598: mov %esp,%ebp 804859a: and $0xfffffff0,%esp 804859d: sub $0x20,%esp 80485a0: call 8048521 <genera_codice> 80485a5: mov %eax,0x18(%esp) 80485a9: movl $0x80486ac,(%esp) 80485b0: call 80483a0 <puts@plt> 80485b5: call 80484fd <inserire_codice> 80485ba: mov %eax,0x1c(%esp) Prepara la chiamata di funzioni Chiama <genera_codice> e salva il risultato nello stack (su esp+0x18) Memorizza la stringa parametro nello stack e chiama puts su quella stringa Chiama <inserire_codice> e memorizza il risultato nello stack (su esp+0x1c)

Analisi Main (2) Naturalmente, guardare la sequenza di chiamate non è sufficiente! 80485be: mov 0x1c(%esp),%eax 80485c2: cmp 0x18(%esp),%eax Confronta il risultato di <inserire_codice> (messo su eax) e <genera_codice> (preso dallo stack) 80485c6: jne 80485cf <main+0x38> 80485c8: call 804856f <win> 80485cd: jmp 80485d4 <main+0x3d> 80485cf: call 8048583 <lose> 80485d4: mov $0x0,%eax Se il risultato del confronto non è pari a 1 (quindi i due elementi sono uguali), vai alla funzione lose ALTRIMENTI CONTINUA L ESECUZIONE con win e SALTA ALL ULTIMA mov (E sostanzialmente l equivalente di un if-else in C, soltanto espresso in maniera leggermente diversa)

Funzioni win e lose Quindi: il main chiama due funzioni che restituiscono due valori Questi valori vengono confrontati E a seconda del confronto vengono chiamate due funzioni diverse! Considerato il funzionamento del programma, possiamo supporre che se il codice è corretto viene chiamata win, altrimenti lose Osserviamo l assembly delle funzioni win e lose Sostanzialmente sono due puts! Quindi le funzioni win e lose si occupano di stampare un messaggio a video! win agisce sulla stringa all indirizzo 0x8048670, mentre lose agisce sulla stringa all indirizzo 0x804868c

Dump stringhe Eseguite objdump s invicible. Potete vedere quello che è, fondamentalmente, l hexdump del file raggruppato per sezioni 0x8048670 (stringa funzione win) Contenuto della sezione.rodata: 8048668 03000000 01000200 48616920 76696e74...Hai vint 8048678 6f212043 6f646963 6520636f 72726574 o! Codice corret 8048688 746f2100 48616920 70657273 6f212049 to!.hai perso! I 8048698 6c20636f 64696365 20c3a820 65727261 l codice.. erra 80486a8 746f2100 496e7365 72697265 20636f64 to!.inserire cod 80486b8 69636520 286d6173 73696d6f 20332063 ice (massimo 3 c 80486c8 69667265 2e2e2e29 3a00 ifre...):. 0x804868c (stringa funzione lose) Indirizzo primo byte della riga Ora sappiamo cosa stampano le funzioni win e lose! Di conseguenza, nell esecuzione del programma arriviamo sempre alla funzione lose!

Funzione genera_codice Restano da analizzare genera_codice ed inserire_codice genera_codice è una funzione molto lunga! Non ne vedremo i dettagli per ragioni di tempo Potreste studiarvela come esercizio Vengono chiamate le funzioni time, srand e rand Molto probabilmente è coinvolta la generazione di un numero casuale ed effettivamente è proprio così! Genera codice genera un valore casuale fra 0 e 999 (compresi) Quindi ogni volta che eseguite il programma il codice è sempre diverso! Un po difficile, così, raggiungere la funzione win A meno di grossi colpi di fortuna, raggiungerete sempre la funzione lose! A meno che

Funzione inserire_codice Cosa possiamo dire della funzione inserire_codice? push %ebp mov %esp,%ebp sub $0x28,%esp lea -0xf(%ebp),%eax mov %eax,(%esp) call 8048380 <gets@plt> lea -0xf(%ebp),%eax mov %eax,(%esp) call 80483f0 <atoi@plt> mov %eax,-0xc(%ebp) mov -0xc(%ebp),%eax Libera memoria per la chiamata di funzioni Carica l indirizzo di memoria puntato da ebp-0xf sul registro eax, muove il contenuto di eax SULLA LOCAZIONE PUNTATA DA ESP (attenzione alle parentesi su %esp) e chiama gets Come per gets, ma questa volta viene chiamata la funzione atoi. Il risultato viene salvato in una variabile locale (la mov) e viene poi «ricaricato» nel registro accumulatore

Exploiting

Funzione inserire_codice - Stack Stack Frame (Per la funzione inserire codice) main Return ADDRESS EBP Precedente EBP lea -0xf(%ebp),%eax mov %eax,(%esp) esp = 0xbffff000 ebp = 0xbffff028 ebp-0xf = 0xbffff019 EBP 0xf EBP 0xf ESP Questa è l esecuzione dello stack dopo la mov prima della chiamata di gets. Lo stack è stato «accorciato» per motivi di spazio. Quando viene chiamata la gets, viene inserito nello stack, come parametro, l indirizzo di base dell array. L array verrà quindi memorizzato a partire da EBP-0xf. Nota bene: non è detto che l indirizzo di partenza dell array sia necessariamente un multiplo di 4

Funzione inserire_codice Stack (2) Stack Frame (Per la funzione inserire codice) main Return ADDRESS EBP Precedente 0 3 2 EBP 0xf 1 EBP lea -0xf(%ebp),%eax mov %eax,(%esp) call 8048380 <gets@plt> esp = 0xbffff000 ebp = 0xbffff028 ebp-0xf = 0xbffff019 ESP EBP 0xf Quando gets viene chiamata, l utente deve inserire dei caratteri da tastiera. Il risultato è un array di char, in cui ogni char è composto da un byte. Immaginiamo che l utente inserisca la stringa «123» (l array è stato dichiarato da tre caratteri ma l utente NON lo sa). Ricordatevi che, a causa del little endian, il primo numero copre l indirizzo INFERIORE dello stack

Funzione inserire_codice Overflow! Stack Frame (Per la funzione inserire codice) main Return ADDRESS EBP Precedente 6 5 4 3 2 EBP 0xf 1 EBP lea -0xf(%ebp),%eax mov %eax,(%esp) call 8048380 <gets@plt> esp = 0xbffff000 ebp = 0xbffff028 ebp-0xf = 0xbffff019 La funzione gets non effettua alcun controllo sulla dimensione dell array. Cioè significa che array più grandi della dimensione dichiarata possono essere scritti in memoria. Ad esempio, questo è cosa succede se inserite «123456». SIETE LIBERI DI RIEMPIRE LO STACK A VOSTRO PIACIMENTO. ESP EBP 0xf

Funzione inserire_codice Attacco Stack Frame (Per la funzione inserire codice) win Return Address Dati Sovrascritti Dati Sovrascritti 6 5 4 3 2 EBP 0xf 1 EBP lea -0xf(%ebp),%eax mov %eax,(%esp) call 8048380 <gets@plt> esp = 0xbffff000 ebp = 0xbffff028 ebp-0xf = 0xbffff019 ESP EBP 0xf Siamo liberi di riempire lo stack come vogliamo. Normalmente questo porterebbe a degli errori di segmentation fault Ma cosa succedesse se fossimo così bravi da riempire lo stack in maniera controllata, in modo da sovrascrivere il return address con un altro indirizzo? Potremmo, ad esempio, saltare direttamente alla funzione win

All attacco! Nella pratica questo attacco è assolutamente possibile gdb invincible break 0*8048509 Ci stiamo fermando prima che la funzione gets venga chiamata Info registers ebp ebp = 0xbffff028 Sono gli stessi valori segnati nelle slide precedenti Dall analisi statica, sappiamo che l array inizia da ebp-0xf. Per arrivare a ridosso dell indirizzo di ritorno, dobbiamo quindi riempire lo stack con 0xf (15) + 4 bytes = 19 bytes L attuale indirizzo di ritorno si trova ad ebp+4 0x080485ba (prossima istruzione del main) Obiettivo finale: sostituire l indirizzo di ritorno con l indirizzo di win In questo esempio è 0x0804856f (dovete sovrascrivere l intero indirizzo!)

All attacco! (2) Quindi, quando gets vi richiede di inserire i dati Dovete prima di tutto inserire 18 bytes La prima parte della stringa può essere, ad esempio, 1111111111111111111 Ora dovete assicurarvi di inserire in memoria i bytes per sovrascrivere l indirizzo di ritorno Dovete inserire i bytes in questo modo: \xbyte Rispettate la little endianess (a due a due). PRIMA GLI ULTIMI DUE VALORI, POI I PENULTIMI DUE, etc. Quindi: \x6f\x85\x04\x08 La stringa finale da inserire dovrebbe essere: 1111111111111111111\x6f\x85\x04\x08 Tuttavia, qualcosa ancora non va Se inserite questa stringa, avrete ancora segmentation fault

EXPLOIT! La ragione è da ricercarsi nel fatto che il programma prende in ingresso dei caratteri Ogni valore esadecimale ha una traduzione in caratteri Sfortunatamente, alcuni non possono essere inseriti da tastiera Per ovviare al problema, ci viene in aiuto la funzione print del linguaggio perl Potete usare questo interprete per tradurre in automatico degli esadecimali in caratteri non inseribili dall utente Un buon modo per fare questo è: Scrivere i caratteri su un file temporaneo Al momento dell esecuzione, dire al programma di trasferire lo standard input da tastiera a file Quindi chiudete gdb ed eseguite perl -e 'print "1"x19; print "\x6f\x85\x04\x08";' > /tmp/input Con perl si possono facilmente ripetere i caratteri con print «carattere»*numero Ogni istruzione perl è separata, come il C, da un punto e virgola (state quindi eseguendo due istruzioni > /tmp/input scrive su file

Epic Win!./invincible < /tmp/input

Come difendersi? (in questo caso) Questo è il caso più semplice di buffer overflow Per difendersi, bisogna evitare di utilizzare funzioni che non effettuano il controllo sulla dimensione degli array gets strcpy sprintf Sono tutte funzioni vulnerabili! Utilizzate, invece, funzioni che effettuano il controllo sulla dimensione degli array fgets strncpy snprintf In ogni caso, compilatori come gcc vi avvisano se state usando delle funzioni «vulnerabili»

In conclusione L analisi di una applicazione vulnerabile consente di effettuare dei potenti attacchi, come il buffer overflow Tali attacchi possono far avere all applicazione dei comportamenti «anomali» Tuttavia, questo ancora non basta Un buffer overflow più avanzato potrebbe essere usato per creare ancora più danni ad esempio, può consentire di prendere il controllo di una macchina Linux (o Windows) Nella prossima lezione vedremo un esempio di tale attacco ed esploreremo tecniche di difesa più complesse