Corso di Sicurezza Informatica



Documenti analoghi
Corso di Sicurezza Informatica. Sicurezza del software. Ing. Gianluca Caminiti

Sistema operativo: Gestione della memoria

Allocazione dinamica della memoria - riepilogo

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Introduzione alla programmazione in C

INFORMATICA 1 L. Mezzalira

Con il termine Sistema operativo si fa riferimento all insieme dei moduli software di un sistema di elaborazione dati dedicati alla sua gestione.

Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica. Programmazione I - corso B a.a prof.

4 3 4 = 4 x x x 10 0 aaa

Funzioni in C. Violetta Lonati

Sistemi Operativi. 5 Gestione della memoria

Per scrivere una procedura che non deve restituire nessun valore e deve solo contenere le informazioni per le modalità delle porte e controlli

La microarchitettura. Didattica della strumentazione digitale e sistemi a microprocessore anno accademico pagina 1

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

SISTEMI OPERATIVI. Prof. Enrico Terrone A. S: 2008/09

Inizializzazione, Assegnamento e Distruzione di Classi

Sistemi Operativi (modulo di Informatica II) I processi

Il tipo di dato astratto Pila

LABORATORIO DI SISTEMI

Gestione della memoria. Paginazione Segmentazione Segmentazione con paginazione

Esercizi su. Funzioni

Introduzione. Corso di Informatica Applicata. Università degli studi di Cassino

dall argomento argomento della malloc()

Vlan Relazione di Sistemi e Reti Cenni teorici

SOMMARIO Coda (queue): QUEUE. QUEUE : specifica QUEUE

GESTIONE INFORMATICA DEI DATI AZIENDALI

Arduino: Programmazione

Funzioni. Il modello console. Interfaccia in modalità console

Variabili e tipi di dato

Architettura hardware

Il Sistema Operativo. C. Marrocco. Università degli Studi di Cassino

Architettura della CPU e linguaggio assembly Corso di Abilità Informatiche Laurea in Fisica. prof. ing. Corrado Santoro

Il memory manager. Gestione della memoria centrale

Guida al sistema. Dott. Enea Belloni

Gestione della Memoria

Il software. la parte contro cui si può solo imprecare. Funzioni principali del sistema operativo. (continua) Gestione della memoria principale

Programmazione I / Informatica generale Prova scritta 11 Giugno 2008

Informazione analogica e digitale

Il Sistema Operativo (1)

FONDAMENTI di INFORMATICA L. Mezzalira

Calcolatori Elettronici. La memoria gerarchica La memoria virtuale

Dispensa di Informatica I.1

2. Spiegare brevemente qual è la funzione del compilatore e la sua importanza per il programmatore.

PROCEDURA INVENTARIO DI MAGAZZINO di FINE ESERCIZIO (dalla versione 3.2.0)

STRUTTURE DEI SISTEMI DI CALCOLO

Studio o faccio i compiti?

Sistemi Operativi IMPLEMENTAZIONE DEL FILE SYSTEM. Implementazione del File System. Struttura del File System. Implementazione

Architettura (10/9/2003) Pag. 1/6. Cognome e Nome (in stampatello):

Pronto Esecuzione Attesa Terminazione

Corso di formazione CerTICTablet

Corso di Sistemi di Elaborazione delle informazioni

10 - Programmare con gli Array

Testi di Esercizi e Quesiti 1

La protezione dai memory error exploit

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Realizzazione di Politiche di Gestione delle Risorse: i Semafori Privati

Un sistema operativo è un insieme di programmi che consentono ad un utente di

ToolChain: Come Generare Applicazioni in Linguaggio Macchina

Appunti sulla Macchina di Turing. Macchina di Turing

AXO Architettura dei Calcolatori e Sistema Operativo. processo di assemblaggio

Il client deve stampare tutti gli eventuali errori che si possono verificare durante l esecuzione.

Laboratorio di Informatica

da 2 a 5 giocatori, dai 10 anni in su, durata 30 minuti

costruttori e distruttori

Il Software. Il software del PC. Il BIOS

Siamo così arrivati all aritmetica modulare, ma anche a individuare alcuni aspetti di come funziona l aritmetica del calcolatore come vedremo.

Hardware di un Computer

CPU. Maurizio Palesi

STACK, istruzioni PUSH e POP; PROCEDURE, istruzioni CALL e RET

Sommario. Definizione di informatica. Definizione di un calcolatore come esecutore. Gli algoritmi.

Codifica: dal diagramma a blocchi al linguaggio C++

Architettura dei calcolatori e sistemi operativi. Assemblatore e Collegatore (Linker) Capitolo 2 P&H Appendice 2 P&H

Architettura di un calcolatore: introduzione

Architettura del calcolatore

Sistema Operativo. Fondamenti di Informatica 1. Il Sistema Operativo

Corso di Informatica

Il simulatore SPIM SPIM

VARIABILI LOCALI E GLOBALI (ESTERNE)

Introduzione al linguaggio C Gli array

lo PERSONALIZZARE LA FINESTRA DI WORD 2000

La Gestione delle risorse Renato Agati

Informatica B a.a 2005/06 (Meccanici 4 squadra) PhD. Ing. Michele Folgheraiter

Sistemi Operativi IMPLEMENTAZIONE DEL FILE SYSTEM. D. Talia - UNICAL. Sistemi Operativi 9.1

MODELLO CLIENT/SERVER. Gianluca Daino Dipartimento di Ingegneria dell Informazione Università degli Studi di Siena

Le operazioni di allocazione e deallocazione sono a carico del sistema.

COS È UN LINGUAGGIO? LINGUAGGI DI ALTO LIVELLO LA NOZIONE DI LINGUAGGIO LINGUAGGIO & PROGRAMMA

Capitolo Trasmissione di dati

ESERCIZIO 1 (b) Dove è memorizzato il numero del primo blocco del file? Insieme agli altri attributi del file, nella cartella che contiene il file.

Linguaggio C. Fondamenti. Struttura di un programma.

Il processore. Il processore. Il processore. Il processore. Architettura dell elaboratore

Breve riepilogo della puntata precedente:

Corso di Calcolatori Elettronici I A.A Il processore Lezione 18

Corso PLC - Manuale Pratico 1

La manutenzione come elemento di garanzia della sicurezza di macchine e impianti

Gestione dei File in C

Software relazione. Software di base Software applicativo. Hardware. Bios. Sistema operativo. Programmi applicativi

Lezione 2 Principi Fondamentali di SO Interrupt e Caching. Sommario

Processi in Linux. Igino Corona 20 Ottobre 2009

C. P. U. MEMORIA CENTRALE

ci sono più problemi che programmi esiste un problema che non si può risolvere con un programma

Transcript:

Corso di Sicurezza Informatica Sicurezza del Software Ing. Giuseppe D Aquì

Sicurezza nell informatica Un computer sicuro è un computer spento (Kevin Mitnick)

Attacchi informatici Gli attacchi informatici, secondo Wikipedia vengono fatti tramite la rete internet, da parte di utenti chiamati dalla società cracker, che tramite l uso di software particolari, a volte creati da loro stessi, si intrufolano abusivamente all interno del sistema, riuscendo ad ottenere piena disponibilità della macchina, per gestire risorse e dati senza avere i giusti requisiti richiesti

Attacchi di massa Storicamente (fino a metà anni 80) i software venivano scritti appositamente per l utilizzo su specifiche macchine Le macchine stesse a loro volta erano molto diverse tra loro, come architettura e sistema operativo Un attacco, per riuscire, necessitava di una persona con grande esperienza e abilità

Attacchi di massa (2) Con la diffusione dell informatica di massa : Standardizzazione dell architettura Standardizzazione de facto dei sistemi operativi Accesso di rete tramite protocolli standard Si è passati ad un ambiente in cui ci sono centinaia di migliaia di macchine tutte uguali Se un attacco funziona su una, funziona potenzialmente su tutte pacchettizzazione degli attacchi e Script Kiddie

Vulnerabilità Una vulnerabilità è una debolezza del sistema che può essere sfruttata da un attacker Causata da un errore di implemetazione o di progettazione Un exploit è un insieme di istruzioni che sfruttano la vulnerabilità

Exploit Gli exploit vengono in genere pubblicati sui bollettini di sicurezza perché sono una prova tangibile dell esistenza di un bug Un exploit pubblicato ha ovviamente la conseguenza di aumentare gli attacchi da parte di Script Kiddie Ma, considerando che chi ha intenzioni malevole in qualche modo lo trova anche se non pubblicato, diffondere un exploit serve a difendere gli utenti visto che il produttore del software è costretto a rilasciare una correzione (patch)

Memory Leak Un memory leak è una scorretta gestione della memoria da parte di un software Per esempio, a seguito di un memory leak un programa può occupare più memoria di quanta gliene necessiterebbe Non sempre da un memory leak deriva una vulnerabilità

Errori di programmazione Errori che causano accesso non controllato ai dati. Errori che causano alterazione del flusso di esecuzione del programma. Mancanza di verifiche sui permessi di accesso alle funzioni oppure ai dati (controlli inadeguati o incompleti). Errori sulle condizioni limite (primo o ultimo caso). Altri errori logici.

Buffer Overflow Un buffer è un area di memoria temporanea che contiene dei dati Qualsiasi variabile può essere vista come un buffer

Struttura di un software Un software viene scritto con linguaggi di programmazione leggibili da umani e poi tradotto in un linguaggio leggibile dalla macchina I passi sono: Compilazione link

Richiami di architettura dei calcolatori Una CPU è composta da: Control Unit: unità che gestisce il flusso di esecuzione dei programmi Arithmethic Logic Unit Registri: aree di memoria interne, usate come supporto alle operazioni

Codice macchina Qualunque software per essere eseguito deve essere trasformato in codice macchina Sequenza di byte, composta da codice e dati Il codice è composto da numeri (opcode e parametri) che rappresentano istruzioni permettono di svolgere operazioni sui registri della CPU, sulla memoria, sulle periferiche ecc.

Uso della memoria Importante: osservando una locazione di memoria è impossibile sapere se il numero che contiene rappresenta una istruzione o un dato Il suo significato dipende dal flusso di esecuzione!

Mappa della memoria Un software caricato in memoria e pronto per l esecuzione si può suddividere in blocchi chiamati segmenti Blocchi che raggruppano locazioni di memoria che svolgono una funzione simile

Mappa della memoria Data BSS Heap Direzione di crescita Heap Stack Code Direzione di crescita Stack

Mappa della memoria Data: contiene le variabili globali e statiche inizializzate Es. static int pippo=321; BSS: contiene le variabili globali e statiche non inizializzate, o inizializzate a zero Es. static int pippo; static int pluto=0;

Mappa della memoria Heap: contiene le variabili allocate con malloc()/new durante l esecuzione del programma Stack: contiene le variabili locali semplici (int, char, short ) e informazioni ausiliarie per effettuare le chiamate di funzione

Struttura Stack Lo stack (pila) è una struttura dati LIFO Last In First Out L ultimo elemento ad entrare è il primo ad uscire Uno stack possiede due funzioni: Push: inserisce un dato in cima allo stack (top) Pop: rimuove un dato dalla cima dello stack

Heap e Stack L Heap e lo Stack rappresentano la memoria a disposizione di un programma e sono di dimensione variabile L Heap cresce spostando in avanti il puntatore alla cima (top) Lo Stack cresce spostando all indietro il puntatore alla cima (top) Se i due puntatori si incontrano Out of Memory

Mappa della memoria* Data BSS Heap Direzione di crescita Heap Stack Code Direzione di crescita Stack * la disposizione dei blocchi cambia a seconda dell architettura e del Sistema Operativo

Attacco Denial of Service (DoS) Conoscendo il funzionamento della memoria, un primo attacco che può venire in mente è riempire tutta la memoria a disposizione in modo che un programma smetta di funzionare Un attacco di questo tipo porta a negare il servizio agli altri utenti, perché il software è andato in crash

Attacco DoS (esempio) Un servizio erogato via internet (come web, email, etc) ha bisogno di una certa quantità di memoria per gestire ogni richiesta Al crescere delle richieste occuperà sempre più memoria Fino al punto in cui la memoria non basterà più

Attacco DoS Per evitare il fallimento dell esecuzione molti servizi accettano solo un certo numero di richieste, mettendo le altre in coda In questo modo il programma non va in crash Dal punto di vista degli utenti, però, non cambia niente: durante un attacco DoS si vedono negare il servizio

Esecuzione del codice macchina L esecuzione del codice macchina avviene in modo sequenziale Normalmente c è un registro (Program Counter (PC) o Instruction Pointer (IP)) memorizza l indirizzo dell istruzione corrente Viene incrementato per passare all istruzione successiva Esistono istruzioni di Jump che servono ad eseguire le condizioni (if else) e le chiamate a funzione

Chiamate di funzione Una chiamata di funzione è una cosa più complicata di come sembra Non è un semplice salto condizionale, perché ha queste caratteristiche: Può avere delle variabili come argomento Le istruzioni che la compongono non possono agire sulle variabili di altre funzioni e viceversa (visibilità) Alla sua conclusione, l esecuzione del programma deve riprendere da dove era stata interrotta

Chiamate di funzione Per garantire queste caratteristiche il compilatore traduce le chiamate di funzione in operazioni fatte sullo Stack Inserisce (push) sullo Stack: il Return Address: l indirizzo a cui ritornare una volta finita la funzione Il Frame Pointer, che rappresenta l indirizzo di riferimento per tutte le variabili locali Opzionalmente: Gli argomenti della funzione Variabili locali della funzione

Call Stack void funzione(int a){ int b; } b (4 byte) Cima dello Stack Frame Pointer (4 byte) Return Address (4 byte) Espansione dello Stack a (4 byte)

Call Stack void funzione2(int a){ char b[10]; } b (10 byte) Cima dello Stack Frame Pointer (4 byte) Return Address (4 byte) Espansione dello Stack a (4 byte)

Call Stack void funzione3(int a){ char b[8]; char c[16]; } c (16 bytes) Cima dello Stack b (8 bytes) Frame Pointer (4 bytes) Return Address (4 bytes) Espansione dello Stack a (4 bytes)

Stack Buffer Overflow Molte funzioni per l accesso alla memoria in linguaggi a basso/medio livello ( C/C++ ) non effettuano controlli sull accesso alle locazioni di memoria Questo per permettere la massima flessibilità di utilizzo ma da un grande potere derivano grandi responsabilità (cit.)

Stringhe Come si rappresenta una stringa in C? Una stringa è una sequenza di caratteri e si rappresenta come un array di char (interi a 8 bit) Un array è caratterizzato da: Dimensione: Una stringa in C è terminata da un carattere null string \0 Punto di inizio: L indirizzo iniziale della stringa è memorizzato in un puntatore (char*)

Stringhe char* saluto = Ciao ; saluto= 0x2345 0x2345 0x2346 0x2347 0x2348 0x2349 C i a o \0 Un char* è un puntatore ad un area di memoria (buffer) che memorizza la stringa

Copia di stringhe Come si copia una stringa? strcpy(char* dest, char* origine) Strcpy copia il contenuto di origine in dest Prende il primo carattere di origine e lo copia nella prima locazione di dest Prende il secondo carattere di origine e lo copia nella seconda locazione di dest E così via

Strcpy Strcpy ferma la copia solo quando ha esaurito tutti i caratteri di origine Se origine > dest, inizierà a scrivere i caratteri di origine al di fuori del buffer di dest (buffer overflow), potenzialmente distruggendo l esecuzione corretta del programma Se dest è una variabile memorizzata nello Stack allora avremmo un overflow che potenzialmente può distruggere lo Stack

Call Stack void funzione4(char* a){ char b[4]; char c[4]; strcpy(c, a); } c (4 bytes) Cima dello Stack b (4 bytes) Frame Pointer (4 bytes) Return Address (4 bytes) Espansione dello Stack a (4 bytes)

Call Stack void funzione4(char* a){ char b[4]; char c[4]; strcpy(c, a); } char* a = aaa ; a = 0x2345 c a a a \0 Cima dello Stack b FP Return Frame Pointer (4 bytes) Return Address (4 bytes) Espansione dello Stack a 0x2345

Call Stack void funzione4(char* a){ char b[4]; char c[4]; strcpy(c, a); } char* a = Saluti ; a = 0x2345!!!! c S a l u Cima dello Stack b t i \0 FP Return Frame Pointer (4 bytes) Return Address (4 bytes) Espansione dello Stack a 0x2345

Stack Buffer Overflow Vengono sovrascritte altre locazioni di memoria immediatamente successive nello Stack Si può anche arrivare a sovrascrivere il Return Address, modificando così l esecuzione del programma

Casi di accesso non-malizioso Se la variabile che viene sovrascritta non è pensata in modo malizioso, si avrà un Return Address che punta ad un area di memoria che non appartiene al programma In modalità protetta, questo significa generare un Segmentation fault e interromprere l esecuzione del programma

Attacco di Stack Buffer Overflow Per sfruttare in modo malizioso il bug, si possono fare due cose: Inserire nel buffer sotto attacco del codice eseguibile, che faccia qualcosa di malizioso oppure esegua componenti del sistema operativo (shell) Sovrascrivere il return address con l indirizzo del codice malizioso Al termine della funzione verrà eseguito in automatico il codice malizioso!

Proteggersi dallo Stack Buffer Overflow Usare funzioni sicure come strncpy(), che prevedono un controllo sulla dimensione massima del buffer Sfruttare funzionalità dei compilatori per produrre codice più difficile da attaccare Sfruttare funzionalità della CPU per marcare come non-eseguibili le aree di memoria dei dati

Canarino Il Canarino (canary) è un campanello d allarme per il buffer overflow, sfruttato alcuni compilatori È un numero, difficile da conoscere/scoprire, che viene inserito nello Stack subito dopo il Return Address

Canarino void funzione5(int a){ char b[8]; char c[16]; } c (16 bytes) b (8 bytes) Frame Pointer (4 bytes) Canarino Return Address (4 bytes) a (4 bytes) Cima dello Stack Espansione dello Stack

Canarino Il principio è che se qualcuno/qualcosa vuole sovrascrivere il Return Address, allora dovrà sovrascrivere anche il Canarino Prima di chiamare il Return Address, il compilatore inserisce codice che controlla se il Canarino corrisponde all originale Se è stato modificato, allora c è un tentativo di attacco in corso!

No-eXecute Il metodo del Canarino ha un problema: è possibile scoprirlo e ricostruirlo Per questo viene in aiuto l hardware I processori più recenti supportano un flag per le pagine di memoria chiamato NX No-eXecute Appena l esecuzione del programma entra in una pagina marcata come NX l esecuzione si ferma con un errore

Problemi del No-eXecute Il flag NX risolve l attacco Stack Buffer Overflow che abbiamo visto prima Non può impedire però la sovrascrittura del Return Address Ovvero si può sovrascrivere il Return Address per far saltare l esecuzione in qualsiasi punto del programma

Attacco return-to-libc In qualunque programma viene automaticamente aggiunta, in fase di link, la Libreria Standard C (libc) Pertanto si può sovrascrivere il Return Address facendolo puntare a una funzione della libreria C, eseguendola Una funzione come system() (presente nella Libreria C) permette di eseguire qualunque programma del sistema attaccato

Address Space Layout Randomization (ASLR) Per evitare anche questi ultimi attacchi si usa la disposizione casuale degli spazi di indirizzi I blocchi di memoria dedicati alle librerie, ai segmenti di dati e del codice vengono disposti in memoria in modo casuale In questo modo è molto difficile conoscere in anticipo l indirizzo da inserire al posto di Return Address

Heap Overflow Heap Buffer Overflow è simile alla versione Stack È più raro, perché raramente l heap contiene puntatori a funzione che possono essere sovrascritti Non per questo è meno pericoloso! Vedi vulnerabilità JPG Microsoft

Integer Overflow Un Integer Overflow si ha quando si superano i limiti di memorizzazione di un intero Unsigned Char 8 bit [0, 255] Char 8 bit [-128, 127] Unsigned Int -> 32 bit [0, 2 32-1] Int 32 bit [-2 31, 2 31-1]

Integer Overflow (Esempio) Un problema si ha con la conversione implicita da Signed a Unsigned A livello di memoria, non cambia la rappresentazione del dato ma solo la sua interpretazione

Tool per prevenzione e attacco

Analisi della memoria Valgrind/DRMemory

Analisi del codice compilato Disassembler e Debugger Ollydbg, IDA, gdb

Metasploit Piattaforma per la verifica di vulnerabilità

Riferimenti Mappa della memoria per differenti architetture: Notes on Assembly memory Smashing the Stack for fun and profit di Aleph One SecurityFocus