Buffer Overflow - Dipartimento di Informatica ed Applicazioni
Buffer Overflow - Dipartimento di Informatica ed Applicazioni
Buffer Overflow - Dipartimento di Informatica ed Applicazioni
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
<strong>Buffer</strong> <strong>Overflow</strong><br />
Attacchi ai servizi <strong>di</strong> rete<br />
Avella Gianluigi<br />
Cerqua Pasquale<br />
Crucil Sergio<br />
D’Alessandro Oreste<br />
Sicurezza su reti A.A. 2004/2005<br />
Prof. Masucci Barbara<br />
Argomenti trattati<br />
Internet<br />
I servizi <strong>di</strong> rete<br />
<strong>Buffer</strong> <strong>Overflow</strong>: teoria, esempi<br />
Tecniche <strong>di</strong> protezione<br />
Aggirare StackGuard<br />
In principio era….Arpanet ……e poi venne Internet<br />
Internet è una suite <strong>di</strong> servizi<br />
Tutti basati sul protocollo TCP/IP<br />
I più importanti attualmente<br />
http: web (es. Apache, Tomcat, IIS)<br />
ftp: trasferimento file (es. wu-ftp)<br />
smtp, pop, imap: posta elettronica (es. sendmail,<br />
postfix)
300.000.000<br />
250.000.000<br />
200.000.000<br />
150.000.000<br />
100.000.000<br />
50.000.000<br />
Lo sviluppo <strong>di</strong> Internet<br />
0<br />
Dicembre<br />
1994<br />
Dicembre<br />
1996<br />
Dicembre<br />
1998<br />
Dicembre<br />
2000<br />
Sicurezza <strong>Informatica</strong><br />
Problemi dovuti alla “insicurezza” dei servizi informatici<br />
Dicembre<br />
2002<br />
Acquisizione illecita <strong>di</strong> dati.<br />
Accesso indebito a un sistema per l’elaborazione <strong>di</strong><br />
dati.<br />
Danneggiamento <strong>di</strong> dati, inclusa la fabbricazione e<br />
la messa in circolazione <strong>di</strong> virus informatici.<br />
Conseguimento fraudolento <strong>di</strong> una prestazione<br />
informatica.<br />
Attacchi a sistemi informatici <strong>di</strong> tipo “denial of<br />
service“.<br />
Danneggiamento grave delle reti <strong>di</strong> comunicazione:<br />
perturbamento <strong>di</strong> pubblici servizi<br />
Tecnologie <strong>di</strong> sicurezza<br />
Tecnologie <strong>di</strong> sicurezza utilizzate<br />
Biometria<br />
Chiave pubblica<br />
Smart cards - e-token<br />
Crittografia dei files<br />
Prevenzione intrusioni<br />
Accounting utenti<br />
Crittografia dati trasmessi<br />
IDS<br />
ACL<br />
Firewall<br />
Antivirus<br />
0% 20% 40% 60% 80% 100%<br />
Sabotaggio<br />
Violazione del sistema<br />
Sito w eb "defacciato"<br />
Abuso <strong>di</strong> applicazioni w eb<br />
Frode informatica<br />
Accesso non autorizzato<br />
Furto <strong>di</strong> componenti<br />
Frode finanziaria<br />
Abuso della rete w ireless<br />
Abuso della rete interna<br />
Furto <strong>di</strong> informazioni<br />
Denial of Service<br />
Virus<br />
Danni economici<br />
Per<strong>di</strong>te per tipo <strong>di</strong> attacco (2004)<br />
$0 $10 $20 $30 $40 $50 $60<br />
Milioni<br />
Milioni <strong>di</strong> dollari.
Errori nelle configurazioni<br />
Le principali cause della vulnerabilità del software<br />
Configurazioni errate<br />
Allocazione <strong>di</strong> tipi <strong>di</strong>fferenti <strong>di</strong> variabili<br />
Errata deallocazione della memoria<br />
Cicli infiniti<br />
Assenza <strong>di</strong> controllo sulle operazioni e sui<br />
puntatori<br />
<strong>Buffer</strong> overflow<br />
Conoscenze necessarie<br />
Linguaggio Assembler.<br />
Registri CPU.<br />
Funzionamento a basso livello <strong>di</strong> un<br />
sistema operativo.<br />
Funzionamento (in genere) dei<br />
linguaggi <strong>di</strong> programmazione.<br />
Conoscenza <strong>di</strong> un debugger.<br />
Nello specifico:<br />
Un sistema GNU/Linux<br />
Gnu Debugger<br />
Linguaggio C<br />
Architettura x86 Intel<br />
Introduzione al <strong>Buffer</strong> overflow<br />
Teoria <strong>ed</strong> esempio <strong>di</strong> un attacco<br />
Il buffer overflow è un errore <strong>di</strong> programmazione dovuto<br />
all’errata gestione dei dati all’interno <strong>di</strong> un programma.<br />
In C un buffer viene normalmente associato ad un array.<br />
L’overflow <strong>di</strong> un buffer consiste nel riempire oltre il limite<br />
tale buffer.<br />
Un attacker è in grado <strong>di</strong> sfruttare questo errore per<br />
causare il crash <strong>di</strong> un servizio remoto o penetrare<br />
all'interno <strong>di</strong> un sistema.<br />
Tipi <strong>di</strong> attacchi dovuti a questo errore:<br />
Mo<strong>di</strong>fica del flusso <strong>di</strong> un programma.<br />
Iniezione <strong>ed</strong> esecuzione <strong>di</strong> co<strong>di</strong>ce arbitrario.<br />
Mo<strong>di</strong>fica <strong>di</strong> un puntatore a funzione.<br />
Mo<strong>di</strong>fica dei dati passati ad una funzione.
Scenari<br />
Server<br />
Attacco locale Web<br />
Un processo in memoria<br />
Ogni processo caricato in<br />
memoria, viene <strong>di</strong>viso in tre<br />
parti.<br />
Segmento testo<br />
Segmento dati<br />
Stack<br />
Lo stack è una struttura dati<br />
cruciale per il<br />
funzionamento <strong>di</strong> un<br />
processo.<br />
Funzionamento <strong>di</strong> tipo LIFO<br />
PUSH e POP ( Operazioni )<br />
FTP SSH<br />
In<strong>di</strong>rizzi <strong>di</strong> memoria bassi<br />
Segmento<br />
testo<br />
Segmento dati<br />
Stack<br />
In<strong>di</strong>rizzi <strong>di</strong> memoria alti<br />
Attacco a client <strong>di</strong><br />
servizi remoti.<br />
Internet Explorer è<br />
probabilmente il<br />
client<br />
più buggato che si<br />
ricor<strong>di</strong>.<br />
main(){<br />
//co<strong>di</strong>ce<br />
foo(buffer);<br />
//co<strong>di</strong>ce<br />
}<br />
foo(char *buffer){<br />
char a [ 5 ];<br />
strcpy(a,buffer);<br />
}<br />
Scenario “domestico”<br />
Funzionamento dello stack<br />
call 0x80483a9 <br />
push %ebp Record <strong>di</strong><br />
mov %esp,%ebp<br />
attivazione<br />
sub $0x18,%esp<br />
sub $0x8,%esp<br />
Registri del processore<br />
EIP = In<strong>di</strong>rizzo dell’istruzione successiva<br />
EBP = Base pointer<br />
ESP = Top dello Stack<br />
ESP<br />
a [ 0 ]<br />
a [ 1 ]<br />
a [ 2 ]<br />
a [ 3 ]<br />
a [ 4 ]<br />
SFP<br />
RET<br />
BP
main(){<br />
//co<strong>di</strong>ce<br />
foo(buffer);<br />
//co<strong>di</strong>ce<br />
}<br />
Funzionamento dello stack<br />
foo(char *buffer){<br />
char a [ 5 ];<br />
strcpy(a,buffer);<br />
}<br />
add $0x10,%esp<br />
leave<br />
ret<br />
Registri del processore<br />
EIP = In<strong>di</strong>rizzo dell’istruzione successiva<br />
EBP = Base pointer<br />
ESP = Top dello Stack<br />
EBP<br />
EIP<br />
Ghost in the shell<br />
A questo punto il programma è andato in crash!<br />
Ma un attacker potrebbe “confezionare” un array da<br />
passare alla funzione foo() in modo tale che venga<br />
<strong>di</strong>rottata l’esecuzione del programma stesso.<br />
Ma nella maggior parte dei casi questo bug viene<br />
sfruttato per costringere il programma ad eseguire<br />
co<strong>di</strong>ce arbitrario!<br />
ESP<br />
a [ 0 ]<br />
a [ 1 ]<br />
a [ 2 ]<br />
a [ 3 ]<br />
a [ 4 ]<br />
SFP<br />
RET<br />
Nop Nop \x8b \xeb \x1f (\bin/sh) 0x0809ff34<br />
No operation Co<strong>di</strong>ce arbitrario<br />
“Shellcode”<br />
BP<br />
Puntatore Inizio<br />
del buffer<br />
Smashing the stack<br />
Se il buffer passato alla funzione<br />
foo() è più <strong>di</strong> 5 caratteri….<br />
Es: “bbbbbbbbbbbbbbb”<br />
foo(char *buffer){<br />
a[ 5 ];<br />
strcpy(a,buffer);<br />
}<br />
I caratteri che ecc<strong>ed</strong>ono il buffer hanno<br />
sovrascritto l’in<strong>di</strong>rizzo <strong>di</strong> ritorno.<br />
EIP adesso punta ad una locazione <strong>di</strong><br />
memoria non valida.<br />
Un esempio<br />
a [ 0 ]<br />
a [ 1 ]<br />
a [ 2 ]<br />
a [ 3 ]<br />
a [ 4 ]<br />
SFP<br />
RET<br />
Segmentation<br />
Fault<br />
Co<strong>di</strong>ce esempio Co<strong>di</strong>ce exploit<br />
#include <br />
#include <br />
main(int argc, char **argv){<br />
char buffer[10];<br />
if(argc!=2){<br />
printf("Usage:./esempio qualcosa\n");<br />
exit(0);<br />
}<br />
strcpy(buffer,argv[1]);<br />
}<br />
foo(){<br />
printf("Corso <strong>di</strong> sicurezza su reti\n");<br />
exit(0);<br />
}<br />
main() {<br />
int i;<br />
char buffer[33];<br />
for(i=0;i
Analisi del problema - 1<br />
Mo<strong>di</strong>fica del flusso <strong>di</strong> un<br />
programma.<br />
“Iniezione” <strong>di</strong> co<strong>di</strong>ce arbitrario.<br />
Un attacker può prendere pieno<br />
possesso della macchina “vittima”.<br />
Analisi del problema - 2<br />
Firewall <strong>ed</strong> antivirus sono<br />
impotenti!<br />
Danni economici elevati.<br />
Metà degli advisory del Cert, sono<br />
su problemi legati al <strong>Buffer</strong><br />
<strong>Overflow</strong>.<br />
Difesa dal <strong>Buffer</strong> <strong>Overflow</strong> Come <strong>di</strong>fendersi<br />
Programmi modulari e facili da debuggare.<br />
Testing.<br />
Stack non eseguibile.<br />
Controllo della <strong>di</strong>mensione degli array.<br />
Utilizzo <strong>di</strong> linguaggi “tipizzati”.<br />
Controllo dell’integrità sui puntatori.<br />
Utilizzo <strong>di</strong> tool specifici.<br />
Pregare….
Tool <strong>di</strong> <strong>di</strong>fesa<br />
StackGuard, StackShield, FlawFinder<br />
automatizzano alcuni dei suddetti meto<strong>di</strong><br />
<strong>di</strong> prevenzione.<br />
Sono programmi open source.<br />
Disponibili unicamente per il mondo Unix.<br />
StackGuard e StackShield non<br />
richi<strong>ed</strong>ono aggiunte al co<strong>di</strong>ce esistente,<br />
ma non tutti i programmi possono essere<br />
ricompilati.<br />
Meto<strong>di</strong> <strong>di</strong>fensivi <strong>di</strong> StackGuard<br />
L’attacker potrebbe leggere la word canary<br />
Quin<strong>di</strong> tre meto<strong>di</strong> <strong>di</strong> <strong>di</strong>fesa<br />
Terminator Canary<br />
La word è scelta come combinazione <strong>di</strong> caratteri nulli, ritorno<br />
a capo e fine linea.<br />
Random Canary<br />
La word è scelta in modo random a run-time.<br />
Esiste una variante chiamata XOR random canary.<br />
Null Canary<br />
La word e una serie <strong>di</strong> caratteri nulli<br />
Es. 0x00000000<br />
StackGuard<br />
StackGuard è una “patch” per gcc.<br />
La prima versione prev<strong>ed</strong>eva la<br />
protezione da scrittura della word<br />
RET. (Memguard)<br />
Interviene nel<br />
prologo e nell’epilogo<br />
<strong>di</strong> ogni funzione.<br />
Utilizza una “canary” word<br />
nel record <strong>di</strong> attivazione.<br />
Un tentativo <strong>di</strong> sovrascrivere il RET<br />
provocherebbe “il canto” del canarino.<br />
StackShield<br />
SFP<br />
Canary RET<br />
StackShield è un software simile a StackGuard.<br />
Protegge il valore RET da attacchi ti tipo<br />
<strong>Buffer</strong> <strong>Overflow</strong>.<br />
Aggiunge co<strong>di</strong>ce assembly al prologo <strong>ed</strong><br />
all’epilogo <strong>di</strong> ogni funzione.<br />
Utilizza tre meto<strong>di</strong> <strong>di</strong> funzionamento<br />
Global Ret Stack<br />
Ret range check.<br />
Modalità speciale ( attacchi contro puntatori a funzione ).<br />
Non richi<strong>ed</strong>e al programmatore <strong>di</strong> aggiungere co<strong>di</strong>ce.
Global Ret Stack<br />
La prima tecnica <strong>di</strong> protezione prev<strong>ed</strong>e<br />
l’utilizzo <strong>di</strong> un array <strong>di</strong> 256 elementi<br />
(Retarray) da trattare come uno stack<br />
dove verranno salvati gli in<strong>di</strong>rizzi <strong>di</strong> ritorno.<br />
Si utilizzano due puntatori speciali<br />
Retptr ( puntatore alla prima locazione libera<br />
<strong>di</strong> Retarray).<br />
Rettop ( puntatore all’ultimo elemento<br />
dell’array.)<br />
main(){<br />
//co<strong>di</strong>ce<br />
foo();<br />
//co<strong>di</strong>ce<br />
}<br />
foo(){<br />
foo2();<br />
//co<strong>di</strong>ce<br />
}<br />
foo2(){<br />
//co<strong>di</strong>ce<br />
}<br />
Esempio <strong>di</strong> funzionamento<br />
Rettop<br />
Retptr<br />
………..<br />
0x02<br />
0x01<br />
Retarray<br />
Funzionamento del Global Ret Stack<br />
Nel prologo <strong>di</strong> ogni funzione, Retptr viene confrontato con Rettop.<br />
Se Retptr è
Ret Range check<br />
Gli attacchi basati sul buffer<br />
overflow, tentano <strong>di</strong> <strong>di</strong>rottare<br />
il flusso del programma verso<br />
il buffer contenete lo shellcode<br />
e quin<strong>di</strong> verso lo stack.<br />
Il Ret range check rende lo<br />
stack non eseguibile.<br />
R<br />
A<br />
N<br />
G<br />
E<br />
V<br />
A<br />
L<br />
I<br />
D<br />
O<br />
Flaw Finder<br />
Segmento testo<br />
Segmento dati<br />
Stack<br />
E’ un tool <strong>di</strong> sviluppo a supporto dei programmatori.<br />
È capace <strong>di</strong> analizzare co<strong>di</strong>ce sorgente C/C++.<br />
È un semplice parser. Produce in output solo una lista con<br />
un grado <strong>di</strong> potenziale pericolosità delle funzioni.<br />
Il database del programma (ruleset) contiene informazioni<br />
su operazioni comuni che possono manifestare problemi<br />
concernenti la sicurezza.<br />
La Ruleset è aggiornabile. Ogni elemento è costituito dalla<br />
tupla (Hook, Level, Warning, Suggestion, Category, URL,<br />
Other).<br />
Per ogni match si propone al programmatore una<br />
soluzione.<br />
Modalità Speciale<br />
Un puntatore a funzione viene allocato in<br />
una zona <strong>di</strong> memoria in modo casuale.<br />
( stack, heap, segmento dati).<br />
Se viene allocato nello stack, l’attacker<br />
cerca <strong>di</strong> corrompere il puntatore tramite<br />
l’overflow <strong>di</strong> un buffer.<br />
StackShield inizializza un variabile<br />
casuale e controlla che non si trovi al <strong>di</strong><br />
fuori del segmento dati, poiché anche il<br />
puntatore verrà allocato nei pressi della<br />
variabile.<br />
Flaw Finder
Analisi dei meto<strong>di</strong> <strong>di</strong> <strong>di</strong>fesa<br />
Stackguard e StackShield aggiungono<br />
co<strong>di</strong>ce e soprattutto “controlli” ai<br />
programmi aumentando sensibilmente<br />
l’overhead.<br />
Ma attenzione….non sono infallibili!<br />
Falle <strong>di</strong> StackGuard<br />
Vantaggio offerto da StackGuard:<br />
Protezione dell’in<strong>di</strong>rizzo <strong>di</strong> ritorno (RET)<br />
…<br />
Non basta. Infatti:<br />
L’overflow viene scoperto al termine della funzione<br />
Non protegge nessun altro in<strong>di</strong>rizzo<br />
(sav<strong>ed</strong> frame pointer…)<br />
canary può essere aggirato<br />
Attacchi a StackGuard<br />
Falle <strong>di</strong> StackGuard<br />
Inefficienze<br />
Un overflow su un<br />
buffer situato prima <strong>di</strong><br />
una o più variabili locali<br />
permette <strong>di</strong><br />
sovrascrivere anche<br />
queste ultime.<br />
Se vi è la possibilità <strong>di</strong> manipolare un puntatore si<br />
possono alterare importanti sezioni <strong>di</strong> memoria (fnlist,<br />
GOT, frame pointer).
Attacchi a StackGuard - 1<br />
Attacco Emsi: sostituzioni nella fnlist<br />
fnlist contiene gli in<strong>di</strong>rizzi delle funzioni registrate<br />
attraverso atexit()<br />
(gdb) b main<br />
Breakpoint 1 at 0x8048790<br />
(gdb) r<br />
Starting program: /root/StackGuard/c/StackGuard/vul<br />
Breakpoint 1, 0x8048790 in main ()<br />
(gdb) x/10x &fnlist<br />
0x400e<strong>ed</strong>78 : 0x00000000 0x00000002 0x00000003 0x4000b8c0<br />
0x400e<strong>ed</strong>88 : 0x00000000 0x00000003 0x08048c20 0x00000000<br />
0x400e<strong>ed</strong>98 : 0x00000000 0x00000000<br />
Attacchi a StackGuard - 2<br />
Sostituzioni nella Global Offset Table (GOT)<br />
Simile al precendente attacco: l’obiettivo è<br />
alterare l’or<strong>di</strong>ne dell’invocazione delle funzioni.<br />
GOT contiene la corrispondenza in<strong>di</strong>rizzo –<br />
funzione.<br />
Avendo la possibilità <strong>di</strong> manipolare un puntatore<br />
è possibile cambiare l’in<strong>di</strong>rizzo associato a una<br />
funzione utilizzata.<br />
Attacchi a StackGuard - 1<br />
È possibile con un debugger scoprirne l’in<strong>di</strong>rizzo<br />
e, avendo un puntatore a <strong>di</strong>sposizione nel<br />
programma, alterare la registrazione delle<br />
funzioni da eseguire all’invocazione <strong>di</strong> exit().<br />
Nemmeno StackShield è immune a questo<br />
attacco<br />
Attacchi a StackGuard - 2<br />
or<strong>ed</strong>al@Homer:~/src/sg/tests$ cc -o sg1 sg1.c<br />
or<strong>ed</strong>al@Homer:~/src/sg/tests$ readelf –S sg1|grep got<br />
[ 8] .rel.got REL 08048358 etc...<br />
[20] .got PROGBITS 08049888 etc...<br />
Come risultato una printf() potrebbe<br />
invocare invece una system().<br />
L’attacco riesce anche se SG è utilizzato in<br />
combinazione con StackPatch (rende lo stack<br />
non eseguibile).
Attacchi a StackGuard - 3<br />
Alterazione del frame pointer<br />
La combinazione d’uso <strong>di</strong> SG con un terminator canary (valore fisso<br />
0x000aff0d) permette <strong>di</strong> arrivare alla sovrascrittura del frame pointer<br />
(e <strong>di</strong> non sovrascrivere il canary) attraverso le comuni funzioni <strong>di</strong><br />
manipolazione delle stringhe.<br />
In questo modo è possibile ottenere il controllo completo delle<br />
variabili locali e degli argomenti delle funzioni.<br />
Il frame pointer non è utilizzato nei programmi compilati con<br />
l’opzione –fomit-frame-pointer<br />
That’s all folk!<br />
<strong>Buffer</strong> <strong>Overflow</strong>: attacco ai servizi <strong>di</strong> rete<br />
Avella Gianluigi<br />
Cerqua Pasquale<br />
Crucil Sergio<br />
D’Alessandro Oreste<br />
Progetto realizzato da: