...

buffer-overrun - Dipartimento di Matematica e Informatica

by user

on
Category: Documents
13

views

Report

Comments

Transcript

buffer-overrun - Dipartimento di Matematica e Informatica
UNIVERSITÀ DI PERUGIA
DIPARTIMENTO DI MATEMATICA E INFORMATICA
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Buffer overflow attack
and defense
Prof. Stefano Bistarelli
Università “G. d’Annunzio”
Dipartimento di Scienze, Pescara
C
Consiglio Nazionale delle
Ricerche
Iit
Istituto di Informatica e Telematica - Pisa
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Errori del codice

Un errore del codice può influire sulla sicurezza del software
(in alcuni casi con conseguenze catastrofiche).

Ad esempio nel giugno 1996 il satellite europeo Ariane 5 è
esploso subito dopo il lancio a causa di un errore nel
software; il programma tentò di inserire un numero di 64 bit in
uno spazio di 16 bit, provocando un overflow.
S. Bistarelli - Metodologie di Secure
Programming
2
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
S. Bistarelli - Metodologie di Secure
Programming
3
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Buffer overflow

Il problema dei buffer overflow è sicuramente quello più comune tra tutti i tipi di
insicurezza nel codice C, mentre è praticamente assente in linguaggi di più alto
livello che non lasciano al programmatore la gestione della memoria.

I problemi di buffer overflow sono stati la principale causa dei problemi di
sicurezza riscontrati negli utlimi 10 anni.

La tecnica del buffer overflow consiste nel forzare la scrittura in memoria con
una quantità di informazioni superiore a quella accettabile. Se il software è privo
di controlli è possibile inserire del codice eseguibile (bytecode) in queste
stringhe di overflow che consentono ad esempio di eseguire comandi su shell
(shellcode). Inoltre se il software viene eseguito in modalità root un attacco di
questo tipo può garantire il pieno possesso di tutte le funzionalità del sistema.

I buffer overflow possono essere eseguiti sulle seguenti zone di memoria:
stack, heap e bss (block started by symbol).
S. Bistarelli - Metodologie di Secure
Programming
4
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Organizzazione della memoria di un processo

Per capire la tecnica del buffer overflow è necessario studiare l'organizzazione
della memoria di un processo (programma).

I processi sono divisi, in memoria, in tre regioni: testo, dati e stack. La regione
testo è fissata, contiene il codice del programma ed è a sola lettura. Qualsiasi
tentativo di scrittura provoca una violazione di segmento. La regione dati
contiene i dati inizializzati e non (variabili statiche e globali) relativi al processo
mentre la regione stack contiene i dati dinamici (utilizzati nella chiamata di
funzioni).
0x00000000
Segmento testo
Indirizzi di memoria bassi
Segmento dati
0xFFFFFFFF
Stack
Indirizzi di memoria alti
S. Bistarelli - Metodologie di Secure
Programming
5
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Organizzazione della memoria di un processo
Indirizzi di memoria bassi
codice
Segmento testo
costanti
Dati
variabili globali e statiche
BSS
variabili allocate
dinamicamente
Heap
variabili locali,
chiamate di funzioni
Stack
S. Bistarelli - Metodologie di Secure
Programming
Indirizzi di memoria alti
6
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
… a volte considereremo il disegno opposto …
S. Bistarelli - Metodologie di Secure
Programming
7
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Lo Stack


Lo stack (pila) è una struttura dati di tipo LIFO (Last In First Out) che
consente di memorizzare un numero variabile di informazioni.
Questa struttura dati viene utilizzata all'interno dell'architettura degli
elaboratori per gestire le chiamate di funzioni (call in assembly). La
zona di memoria destinata alla gestione dello stack viene suddivisa
logicamente in aree (stack frame) per ogni chiamata di funzione.
x=pop
push(x)
Stack
1) x=a, 2) x=b, 3) x=c
1) x=c, 2) x=b, 3) x=a
c
b
a
S. Bistarelli - Metodologie di Secure
Programming
8
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Lo Stack e i registri di sistema

Ogni processo viene eseguito step-by-step
tramite l'elaborazione di istruzioni successive.
L'indirizzo di memoria dell'istruzione da
eseguire, in un preciso istante, è contenuto
nel registro di sistema EIP (Extended
Instruction Pointer) a 32 bit (1dword).
S. Bistarelli - Metodologie di Secure
Programming
9
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Lo Stack e i registri di sistema

Oltre a questo registro
di sistema esistono altri
registri utili per la
gestione di chiamate di
funzioni (call). Il
registro EBP
(Extended Base
Pointer) che punta alla
base di uno stack
frame ed il registro
ESP (Extended Stack
Pointer) che punta alla
cima dello stack frame.
S. Bistarelli - Metodologie di Secure
Programming
10
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Lo Stack e i registri di sistema

Quando viene richiamata
una funzione (call) il
sistema inserisce nello
stack l'indirizzo
dell'istruzione successiva,
push(EIP+4) dove 4 indica
4 byte (4byte=1dword),
successivamente inserisce
nello stack il puntatore alla
base dello stack frame
corrente, push (EBP) ed
infine copia l'ESP attuale
sull'EBP inizializzando così
il nuovo stack frame.
S. Bistarelli - Metodologie di Secure
Programming
11
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione





EIP, EBP, ESP
EIP va in stack
EBP va in stack (chiamato SFP)
EBP’ = ESP
Settato nuovo ESP’ (lunghezza della
procedura chiamata)
S. Bistarelli - Metodologie di Secure
Programming
12
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Un esempio in C
Analizziamo quest'esempio di codice in C per capire meglio
l'allocazione dello stack frame:
void test_function (int a, int b)
{
char flag;
char buffer[10];
}
buffer
flag
SFP*
EBP'
nuovo
EBP
Indirizzo di ritorno (ret)
EIP
int main()
{
test_function (1,2);
exit(0);
}
memoria
bassa
Stato dello stack frame
a
b
Indirizzo di ritorno (ret) = EIP + 4 byte
memoria
alta
*SFP=
Saved Frame Pointer, valore utilizzato per rispristinare lo stato originale di EBP
(prima della chiamata di test_function();)
S. Bistarelli - Metodologie di Secure
Programming
13
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Lo stack frame



Alle variabili locali della funzione
test_function si fa riferimento
mediante sottrazione del valore del
frame pointer EBP e gli argomenti
della funzione mediante addizione a
tale valore.
Quando una funzione viene
richiamata, il puntatore EIP diventa
l'indirizzo di inizio del codice della
funzione.
memoria
bassa
buffer
flag
SFP*
EBP
Indirizzo di ritorno (ret)
La memoria dello stack è utilizzata
per le variabili locali e gli argomenti
della funzione. Dopo il termine
dell'esecuzione della funzione,
l'intero stack frame viene estratto
dallo stack in modo da riprendere
l'esecuzione sull'istruzione di ritorno
(ret).
S. Bistarelli - Metodologie di Secure
Programming
a
b
memoria
alta
14
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Esempio di overflow
Analizziamo quest'esempio di codice in C che provoca un overflow:
void overflow_function (char *str) {
char buffer[20];
strcpy(buffer, str); // Funzione che copia str nel buffer
}
Questa istruzione
provoca un overflow!
int main() {
char big_string[128];
int i;
for(i=0; i < 128; i++)
{
big_string[i] = 'A';
}
overflow_function(big_string);
exit(0);
}
S. Bistarelli - Metodologie di Secure
Programming
15
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Segmentation fault
Perchè il codice precedente provoca un Segmentation fault?
1) La prima chiamata di
overflow_function inizializza
correttamente lo stack frame:
2) Al momento del termine dell'esecuzione
della funzione overflow_function, l'istruzione
di ritorno è stata sovrascritta con il carattere A
(segmentation fault!)
memoria
bassa
memoria
bassa
buffer
A
A
...
A
}
SFP
A
Indirizzo di ritorno (ret)
A
*str (argomento)
A
}
memoria
alta
S. Bistarelli - Metodologie di Secure
Programming
A
20 byte
108
byte
16
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Buffer overflow (basati sullo stack)
Cosa succede se l'istruzione di ritorno (ret) contiene un indirizzo
di memoria valido?
●
●
●
In questo caso il processo continuerebbe indisturbato
eseguendo l'istruzione successiva contenuta in ret.
Il buffer overflow basato sullo stack consiste proprio nello
sfruttare tale possibilità sostituendo l'istruzione di ritorno ret
con un nuovo puntatore ad una porzione di codice inserita
manualmente da un intruso.
Come è possibile
1.
modificare tale istruzione di ritorno ed
2.
inserire arbitrariamente del codice in un processo?
S. Bistarelli - Metodologie di Secure
Programming
17
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Cos'è un Buffer Overrun



Si verifica quando i dati superano la dimensione
prevista e sovrascrivono
altri valori
È frequente soprattutto nel codice C/C++ non
gestito
Può essere di quattro tipi:





buffer overrun basato sullo stack
buffer overrun dell'heap
Sovrascrittura della v-table e del puntatore a funzione
Sovrascrittura del gestore eccezioni
Può essere sfruttato dai worm
S. Bistarelli - Metodologie di Secure
Programming
18
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Possibili conseguenze dei sovraccarichi
buffer
Possibile
conseguenza
Obiettivo dell'hacker
Violazione dell'accesso
Realizzare gli attacchi DoS
(denial of service) contro i server
Instabilità
Interferire con il normale
funzionamento del software
Inserimento di codice
Ottenere privilegi per il proprio
codice
Sfruttare dati aziendali di vitale
importanza
Eseguire azioni distruttive
S. Bistarelli - Metodologie di Secure
Programming
19
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
I buffer overrun dell'heap


Sovrascrivono i dati memorizzati nell'heap
Sono più difficili da sfruttare
di un buffer overrun
Dati
Puntatore
Dati
strcpy
Dati
xxxxxxx
Puntatore
xxxxxxx
Puntatore
S. Bistarelli - Metodologie di Secure
Programming
20
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
I buffer overrun dell'heap: example 1
class CustomerRecord
{
private:
char szName[20];
char szAddress[10];
char szPassword[20];
char szCreditHistory[200];
char szBankDetails[25];
S. Bistarelli - Metodologie di Secure
Programming
21
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
void ChangeAddress (char *a)
{
strcpy (szAddress, a);
}
bool ChangePassword (char *newpwd, char *oldpwd)
{
bool res=false;
if (strcmp (oldpwd, szPassword)==0)
{
strcpy (szPassword, newpwd);
res=true;
}
return res;
}
S. Bistarelli - Metodologie di Secure
Programming
22
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
char * GetSensitiveData (char *pwd)
{
if (strcmp (pwd, szPassword)==0)
{
// return all the personal info!
return "Here's all the personal info...\n";
}
else
return "";
}
S. Bistarelli - Metodologie di Secure
Programming
23
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Eseguire procedura

Come faccio ad ottenere


GetSensitiveData password
Se non conosco la password=secret??

Trucco:
ChangeAddress …

Buffer overflow su ?? Heap!! 



char szAddress[10];
char szPassword[20];
S. Bistarelli - Metodologie di Secure
Programming
24
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Esempio di sovraccarico buffer basato sullo stack
int main(int argc, char* argv[])
{
//A blatant shortcut
printf("Address of foo = %p\n", foo);
printf("Address of bar = %p\n", bar);
foo(argv[1]);
return 0;
}
Attacco: lanciare bar …
senza che codice lanci bar
S. Bistarelli - Metodologie di Secure
Programming
25
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione



void foo(const char* input)
{
char buf[10];
//What? No extra arguments supplied to printf?
//It is a cheap trick to view the stack
printf("My stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");




//Pass the user input straight to secure code public enemy #1.
strcpy(buf, input);
printf("%s\n", buf);

printf("Now the stack looks like:\n%p\n%p\n%p\n%p\n%p\n%p\n\n");



}

void bar(void)
{
printf("The attack!\n");
}



S. Bistarelli - Metodologie di Secure
Programming
26
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione


Devo passare dei parametri a foo, in modo
tale che AL RITORNO mi vada prima ad
eseguire bar!!!
Quindi devo far scrivere a foo sul suo
indirizzo di ritorno l’indirizzo di bar
S. Bistarelli - Metodologie di Secure
Programming
27
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Eseguiamo codice
00000000
buf
00000A28
7FFDC000
0012FEE4 SFP
0040108A ret
0032116F
}
S. Bistarelli - Metodologie di Secure
Programming
28
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Dopo chiamata procedura e input 12345
34333231
buf
00000035
7FFDF000
0012FEE4 SFP
0040108A ret
0032116F
}

Dove ho scritto su
buffer 12345 ???


Conosciamo cygnus
HexEditor
Little-big endian
S. Bistarelli - Metodologie di Secure
Programming
29
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione


Conosciamo cygnus HexEditor
12345


In esadecimale
31 32 33 34 35
S. Bistarelli - Metodologie di Secure
Programming
30
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Big-endian e little-endian sono due metodi
differenti usati dai calcolatori per
immagazzinare in memoria dati di
dimensione superiore al byte (es. word,
dword, qword).
S. Bistarelli - Metodologie di Secure
Programming
31
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

big-endian è la memorizzazione che inizia dal byte
più significativo per finire col meno significativo; è
utilizzata dai processori Motorola, IBM e Sun e nei
protocolli usati in Internet


viene anche chiamato network byte order.
little-endian è la memorizzazione che inizia dal byte
meno significativo per finire col più significativo; è
utilizzata dai processori Intel e Digital
S. Bistarelli - Metodologie di Secure
Programming
32
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Etimologia 

Big-endian e little-endian sono tratti dal nome
dei due gruppi di persone incontrati dal
personaggio fantastico Gulliver durante i suoi
viaggi, in continuo litigio su quale lato fosse il
migliore da rompere nelle uova.
S. Bistarelli - Metodologie di Secure
Programming
33
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
esempi
Nel caso di una DWORD, il numero esadecimale 0x01234567
verrà immagazzinato rispettivamente:
Little endian
+----+----+----+----+
|0x67|0x45|0x23|0x01|
+----+----+----+----+
byte:
0
1
2
3
Big endian
+----+----+----+----+
|0x01|0x23|0x45|0x67|
+----+----+----+----+
0
1
2
3
(Negli esempi il valore in grassetto è il byte più
significativo)
S. Bistarelli - Metodologie di Secure
Programming
34
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Dopo chiamata procedura e input 12345
34333231
buf
00000035
7FFDF000
0012FEE4 SFP
0040108A ret
0032116F
}

Dove ho scritto su
buffer 12345 ???


Conosciamo cygnus
HexEditor
Little-big endian
Allora che input devo dare ?? per ottenere cosa ???
S. Bistarelli - Metodologie di Secure
Programming
35
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione





Provare input 1234
12341234
1234123412 (10 byte) per buff
123412341234 (posso facilmente salvarne di
piu’ perche’ allocate multipli di dword)
Poi sovrascrivo indirizzo EBP e indirizzo di
ritorno!!


Uso di editor esadecimale
FINE!! 
S. Bistarelli - Metodologie di Secure
Programming
36
UNIVERSITÀ DI PERUGIA
DIPARTIMENTO DI MATEMATICA E INFORMATICA
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Weird example!!! LAB!
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

the goal is to enter a serial and to get the
good boy message


Using a buffer overflow of the stack!!
Tools:

Debugger


Disassembler


odbg110.zip
freeida43.exe
Hexeditor

cygnusfe.zip
S. Bistarelli - Metodologie di Secure
Programming
38
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Run the program:
-- The analyst's weird crackme ---------------------------------enter your serial please:
S. Bistarelli - Metodologie di Secure
Programming
39
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
!Run ida disassembler!

No way to go to the
CODE:00401177
push
offset aWooCongrats ; format
S. Bistarelli - Metodologie di Secure
Programming
40
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
The source 
int main(){
int i,len,temp;
unsigned char name[75];
unsigned long check=0;
printf("-- The analyst's weird crackme --\n");
printf("---------------------------------\n");
printf("enter your serial please:\n");
gets(name);
asm{ nop};
len=strlen(name);
S. Bistarelli - Metodologie di Secure
Programming
41
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
//cout << len;
if (len < 25) goto theend;
if (len > 120 ) goto theend;
for (i=1; i <= len ; i++)
{
temp += name[i] ;
}
if (temp = 31337) goto theend;
if (temp < 5000) goto theend;
if (temp > 15000) goto theend;
goto theend;
printf("wOO! congrats ;)\n");
theend:
getch();
return 0;
}
S. Bistarelli - Metodologie di Secure
Programming
42
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Analisi dell’assembler:

Push (per mettere su stack parametri
della gets, )
CODE:0040112E
CODE:0040112F
CODE:00401132
CODE:00401133
CODE:00401138
CODE:00401139
CODE:0040113A
CODE:0040113D
pop ecx
lea eax, [ebp+s] ; buffer
push eax
;s
call _gets
; get entered serial
pop ecx
nop
lea edx, [ebp+s]
push edx
;s
S. Bistarelli - Metodologie di Secure
Programming
43
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Quanto è grande buffer in memoria?
S. Bistarelli - Metodologie di Secure
Programming
44
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Vediamo struttura stack!!
Pulsante “open stack variables” (CTRL-K)
FFFFFFB4 s
db ?
FFFFFFB5
db ? ; undefined
::
::
Buf di quante
FFFFFFFD
db ? ; undefined
word?
FFFFFFFE
db ? ; undefined
FFFFFFFF
db ? ; undefined
EBP
00000000 s
db 4 dup(?)
RET
00000004 r
db 4 dup(?)
00000008 argc
dd ?
0000000C argv
dd ?
; offset (FFFFFFFF)
00000010 envp
dd ?
; offset (FFFFFFFF)
00000014

}
S. Bistarelli - Metodologie di Secure
Programming
45
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Siccome indirizzo delle istruzioni di
successo è 00401177
 dovremo provocare un buffer
overflow in una procedura e inserire
come codice di ritorno quello

Tramite editor esadecimale
 00401177  w @

S. Bistarelli - Metodologie di Secure
Programming
46
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
n.b


Finora abbiamo solo modificato puntatore ..
Non abbiamo iniettato noi codice (lo faremo
nell’esercitazione linux)
S. Bistarelli - Metodologie di Secure
Programming
47
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Di solito,


Lo scopo di un buffer overflow attack è di modificare
il funzionamento di un programma privilegiato in
modo da prenderne il controllo e, nel caso il
programma abbia sufficienti privilegi, prendere il
controllo dell’ host.
Typically the attacker


is attacking a root program, and
immediately executes code similar to “exec(sh)” to get a
root shell.
S. Bistarelli - Metodologie di Secure
Programming
48
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

1.
2.
To achieve this goal, the attacker must
achieve two sub-goals:
Arrange for suitable code to be available in
the program's address space.
Get the program to jump to that code, with
suitable parameters loaded into registers &
memory.
S. Bistarelli - Metodologie di Secure
Programming
49
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
The “buffer” part

how the attack code is placed in the victim
program’s address space


Inject it!
It is already there

For instance, if the attack code needs to execute
“exec(“/bin/sh”)”, and there exists code in libc that
executes “exec(arg)” where “arg” is a string pointer
argument, then the attacker need only change a pointer
to point to “/bin/sh” and jump to the appropriate
instructions in the libc library
S. Bistarelli - Metodologie di Secure
Programming
50
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
The “overflow” part

how the attacker overflows a program buffer
to alter adjacent program state

Overflow a buffer with weak bound check, with the
goal of corrupting the state of an adjacent part of
the program’s state (adjacent pointers)
S. Bistarelli - Metodologie di Secure
Programming
51
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Le vie di ingresso!!
S. Bistarelli - Metodologie di Secure
Programming
52
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Buffer overflow (basati sullo stack)

Ovviamente il processo deve avere delle "vie d'ingresso". Ad
esempio dei parametri che l'utente può specificare nella linea di
comando, dei pacchetti da inviare ad una porta in ascolto del
processo (quest'ultimo caso è quello più pericoloso perchè
consente di effettuari attachi da remoto).

In questa sede consideriamo l'esempio classico di attacco
basato sul buffer overflow dello stack su di un parametro del
processo a linea di comando.

Che tipo di codice è possibile inserire in un attacco basato su
buffer overflow? Si deve utilizzare un bytecode, ossia un codice
autonomo, scritto in linguaggio macchina, che non deve
contenere determinati caratteri speciali nelle sue istruzioni
perchè deve sembrare un buffer di dati.
S. Bistarelli - Metodologie di Secure
Programming
53
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Un tipico esempio di bytecode è il cosiddetto
shellcode. Ossia un bytecode che genera una shell.

Se si riesce a manomettere un programma suid
root in maniera che esegua una shellcode è
possibile prendere il possesso di un sistema,
avendo privilegi da root, mentre il sistema è convinto
che il programma suid root stia ancora assolvendo i
suoi compiti previsti.
S. Bistarelli - Metodologie di Secure
Programming
54
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

A questo punto sorgono due problemi: (1) Dal momento che
dobbiamo inserire del codice di tipo bytecode nello stack, che è
una struttura dinamica, come possiamo determinare la posizione
assoluta in memoria della nostra prima istruzione bytecode?
(2) Una volta determinata questa posizione come possiamo
modificare l'istruzione di ritorno ret dello stack frame?

Non è possibile determinare la posizione assoluta del bytecode
nello stack, per questo motivo è necessario utilizzare un
espediente, il NOP sled (NOP = nessuna operazione, sled è la
traduzione di slitta)
S. Bistarelli - Metodologie di Secure
Programming
55
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

NOP è un istruzione assembler vuota, non esegue niente. Viene
utilizzata per gestire sincronizzazioni su cicli di calcolo...

La tecnica del NOP sled consiste nell'inserire prima del nostro
bytecode un grande array di istruzioni NOP (una slitta di NOP).
Così facendo anche se l'istruzione di ritorno (ret) dovesse saltare
su una posizione qualsiasi della slitta di NOP alla fine il bytecode
verrebbe comunque eseguito.

Ciò non toglie che per risolvere il primo problema dobbiamo
comunque avere una stima dell'indirizzo del bytecode.
S. Bistarelli - Metodologie di Secure
Programming
56
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Una volta che abbiamo stimato la possibile posizione del nostro
bytecode possiamo utilizzare un'altra tecnica per risolvere il
secondo problema che consiste nel riempire la fine del nostro
buffer, dopo il bytecode, con l'indirizzo di ritorno stimato.

In questa maniera, purchè uno di questi indirizzi di ritorno
sovrascriva l'indirizzo di ritorno reale, l'espediente darà il risultato
desiderato.

Utilizzando queste tecniche il nostro buffer avrà una forma del
genere:
NOP sled
bytecode
Indirizzo di ritorno ripetuto
S. Bistarelli - Metodologie di Secure
Programming
57
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Di seguito è riportato il codice assembly (memorizzato in una variabile
definita in C) di una shellcode (si veda il file exploit.c in allegato):

char shellcode[] =
"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0"
"\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d"
"\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73"
"\x68";

Gli step per l'esecuzione del ns. buffer overflow:
1) stima dell'indirizzo di ritorno (ret), nel ns. caso ret=stack pointer; 2)
buffer= NOP sled + shellcode + indirizzo ret ripetuto;
3) esecuzione del programma vuln.c che ha vulnerabilità passandogli
come parametro buffer il buffer costruito in exploit.c (tramite l'istruzione
exec(“./vuln”,”vuln”,buffer,0));
S. Bistarelli - Metodologie di Secure
Programming
58
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Heap!!
S. Bistarelli - Metodologie di Secure
Programming
59
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione


Un tipo di vulerabilità simile allo stack-based buffer overflow è lo
heap-based buffer overflow che segue lo stesso principio
ma partendo da variabili allocate nello heap, quindi non
staticamente ma dinamicamente con funzioni della famiglia
malloc().

Lo heap ("mucchio") è una zona di memoria allocata
dinamicamente durante l'esecuzione (runtime) di un processo.

Un array di caratteri, allocato dinamicamente attraverso una
chiamata malloc/calloc fara' parte dello heap. In generale
qualunque assegnazione dinamica di memoria contigua farà
parte dello heap. Viceversa, quando la porzione di memoria non
e' piu' utile, viene chiamata una funzione che libera tale zona di
memoria: free().
S. Bistarelli - Metodologie di Secure
Programming
60
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Un semplice overflow basato su heap

Consideriamo l'esempio contenuto nel file heap.c (in allegato). In
questo caso si allocano due variabili userinput e outputfile nello
heap con dimensioni fisse e pari a 20 byte.

Cosa succede se si inserisce un valore > di 20 byte in una delle
due variabili? Si ha un overflow. E se le due variabili vengono
allocate in memoria in zone contigue l'overflow su una di esse
può sovrascrivere il contenuto dell'altra.






char *userinput = malloc(20);
char *outputfile = malloc(20);
20
Ad esempio un overflow sulla
variabile userinput provoca la
20
sovrascrittura della variabile outputfile.
S. Bistarelli - Metodologie di Secure
Programming
Heap
userinput
outputfile
61
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Proviamo ad eseguire il programma heap.c

$ ./heap prova
---DEBUG-[*] userinput @ 0x80499d8: prova
[*] outputfile @ 0x80499f0: /tmp/notes
[*] distance between: 24
----------------Writing to “prova” to the end of /tmp/notes...














Cosa succede se utilizziamo un parametro con più di 24 byte?
$ ./heap 123456789012345678901234test
---DEBUG-[*] userinput @ 0x80499d8: 123456789012345678901234test
[*] outputfile @ 0x80499f0: test
[*] distance between: 24
----------------Writing to “123456789012345678901234test” to the end of test...
S. Bistarelli - Metodologie di Secure
Programming
62
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
BSS
S. Bistarelli - Metodologie di Secure
Programming
63
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Buffer overflow (basati su BSS, Block Started by
Symbol)

I buffer overflow basati su BSS sfruttano lo stesso principio dei
buffer overflow basati su heap. Le variabili globali e statiche di un
programma vengono allocate nella zona di memoria BSS in
maniera contigua. Un overflow di una di queste variabili provoca
la sovrascrittura di altre variabili.

Consideriamo l'esempio (bss_game.c, in allegato). In questo
programma si utilizzano due variabili statiche:
static char buffer[20]; static int (*function_ptr) (int user_pick);

Come per l'esempio sullo heap è possibile provocare un
overflow della variabile buffer (parametro del programma)
sovrascrivendo il contenuto del puntatore a funzione function_ptr!
In questo caso posso far eseguire un bytecode come per il buffer
overflow basato sullo stack!!!
S. Bistarelli - Metodologie di Secure
Programming
64
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Come evitare buffer overflow
S. Bistarelli - Metodologie di Secure
Programming
65
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Come difendersi dai buffer overrun

Utilizzare con particolare cautela le seguenti
funzioni:






strcpy
strncpy
CopyMemory
MultiByteToWideChar
Utilizzare l'opzione di compilazione /GS
in Visual C++ per individuare i sovraccarichi buffer
Utilizzare strsafe.h per un gestione del buffer più
sicura
S. Bistarelli - Metodologie di Secure
Programming
66
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

La soluzione più immediata e sicura consiste nell'inserire controlli sulle
dimensioni dei parametri inseriti dall'utente, in modo da assicurarsi che
non si verifichino overflow.

Molte volte, soprattutto in programmi complessi, l'utilizzo di controlli
sulle dimensioni delle variabili può risultare pesante. Si possono così
utilizzare funzioni che non provocano overflow anche in presenza di
parametri sovradimensionati. Ad esempio l'utilizzo delle funzioni C
strlcpy() e strlcat() al posto di strcpy().

Un alternativa è l'utilizzo di librerie considerate "sicure” progettate
proprio per evitare buffer overflow. Ad esempio LibSafe
(http://www.research.avayalabs.com/project/libsafe/).

Altre possibilità di prevenire buffer overflow sono fornite da strumenti in
grado di rilevare tali bug, come StackGuard (per i buffer overflow basati
sullo stack). http://www.cse.ogi.edu/DISC/projects/immunix/StackGuard/
S. Bistarelli - Metodologie di Secure
Programming
67
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Defenses
Writing correct code
1.

Code auditing
Non executable buffer
2.

Data segment non executable
Code pointer integrity checking
3.

detect that a code pointer has been corrupted before it is
dereferenced.

Stack Introspection by Snarskii



Create a new libc
Stackguard (Activation Record Integrity Checking)
Pointguard (function pointer integrity checking)
S. Bistarelli - Metodologie di Secure
Programming
68
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Defenses
4.
Array bounds checking

The Compaq C compiler for the Alpha CPU (“-check_bounds”) :




Richard Jones and Paul Kelly developed a gcc patch that does full array
bounds checking for C programs.


The performance costs are substantial
Purify: is a memory usage debugging tool for C programs.



only explicit array references are checked, i.e. “a[3]” is checked, while “*(a+3)” is
not
since all C arrays are converted to pointers when passed as arguments, no
bounds checking is performed on accesses made by subroutines
dangerous library functions (i.e. strcpy()) are not normally compiled with bounds
checking, and remain dangerous even with bounds checking enabled
Purify uses “object code insertion” to instrument all memory accesses. After
linking with the Purify linker and libraries, one gets a standard native executable
program that checks all of its array references to ensure that they are legitimate.
imposes a 3 to 5 times slowdown.
Type-Safe Languages
S. Bistarelli - Metodologie di Secure
Programming
69
UNIVERSITÀ DI PERUGIA
DIPARTIMENTO DI MATEMATICA E INFORMATICA
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Safe and unsafe functions
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Strcpy vs strncpy
char * strcpy ( char * destination, const char * source );


Copies the C string pointed by source into the array pointed by
destination, including the terminating null character.
To avoid overflows, the size of the array pointed by destination
shall be long enough to contain the same C string as source
(including the terminating null character), and should not overlap
in memory with source.
S. Bistarelli - Metodologie di Secure
Programming
71
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Strcpy vs strncpy
char * strncpy ( char * destination, const char * source, size_t num );
•Copies the first num characters of source to destination.
•If the end of the source C string (which is signaled by a null-character)
is found before num characters have been copied, destination is padded
with
zeros until a total of num characters have been written to it.
•No null-character is implicitly appended to the end of destination, so
destination
will only be null-terminated if the length of the C string in source is less
than num.
S. Bistarelli - Metodologie di Secure
Programming
72
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
strncpy

if the length of the src string is >= n, you end
up without null termination
char dest[LEN];
char *src; ... /* src is set to point to a source string of unknown
length */
strncpy(dest,src,LEN);
dest[LEN-1]='\0'; /* null terminate for safety */
S. Bistarelli - Metodologie di Secure
Programming
73
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
strncpy

Using strncpy() has performance
implications, because it zero-fills all the
available space in the target buffer after the
’\0’ terminator.

a strncpy() of a 13-byte buffer into a 2048-byte
buffer overwrites the entire 2048-byte buffer
S. Bistarelli - Metodologie di Secure
Programming
74
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
strnlcpy

Look on the web!!

Problemi di compatibilità!!
S. Bistarelli - Metodologie di Secure
Programming
75
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione


Fail solo se input o buf e’ un illegal pointer
Se input troppo lungo verrà troncato 
S. Bistarelli - Metodologie di Secure
Programming
76
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

Non si tronca il buffer, se troppo lungo si
ottiene errore GESTITO!!
S. Bistarelli - Metodologie di Secure
Programming
77
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Sprintf vs snprintf
int sprintf (String, Format, [Value, ...])
char *String;
const char *Format;

The sprintf subroutine converts, formats, and stores the Value
parameter values, under control of the Format parameter, into
consecutive bytes, starting at the address specified by the String
parameter.
The sprintf subroutine places a null character (\0) at the end.
You must ensure that enough storage space is available to
contain the formatted string.
S. Bistarelli - Metodologie di Secure
Programming
78
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Sprintf vs snprintf
int snprintf (String, Number, Format, [Value, . . .])
char *String;
int Number;
const char *Format;

The snprintf subroutine is identical to the sprintf
subroutine with the addition of the Number
parameter, which states the size of the buffer
referred to by the String parameter.
S. Bistarelli - Metodologie di Secure
Programming
79
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
_snprintf


In w32 environment
Non setta il \0 finale!!! 
S. Bistarelli - Metodologie di Secure
Programming
80
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Gets vs fgets

char *gets(char *s);



read a line of data from STDIN. gets continues
to read characters until NEWLINE or EOF is
seen
The NEWLINE character is NOT placed in the
buffer
gets does NOT check the size of the buffer and
overflow on the stack can occour.
S. Bistarelli - Metodologie di Secure
Programming
81
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione

char *fgets(char *s, int n, FILE *stream);



fgets is used to read a line of data from an
external source.
If fgets is reading STDIN, the NEWLINE character
is placed into the buffer.
it checks that the incoming data does not exceed
the buffer size
S. Bistarelli - Metodologie di Secure
Programming
82
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Use strsafe.h!!
S. Bistarelli - Metodologie di Secure
Programming
83
UNIVERSITÀ DI PERUGIA
DIPARTIMENTO DI MATEMATICA E INFORMATICA
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Secure Programming opensource software
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Open vs closed source




Open-source software is more secure than closed software
 E.S. Raymond, The Cathedral & the Bazaar: Musings on Linux
and Open Source by an Accidental Revolutionary, O’Reilly &
Assoc., 1999.
And the contrary
 K. Brown, Opening the Open Source Debate, Alexis de
Tocqueville Inst., 2002;
www.adti.net/cgi-local/SoftCart.100.exe/online-store/scstore/pbrown_%1.html?L+scstore+llfs8476ff0a810a+1042027622
!!The defender can install and configure the SW with high
security concerns!!
!!The attacker know the source code!! (if the defender just install
it wothout any personal configuration!)
S. Bistarelli - Metodologie di Secure
Programming
85
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Toward a perfect software!
1.
Software auditing

2.
Vulnerability mitigation

3.
which prevents vulnerabilities by searching for them
ahead of time, with or without automatic analysis
which are compile-time techniques that stop bugs at
runtime
Behavior management

which are operating system features that either limit
potential damage or block specific behaviors known to be
dangerous
S. Bistarelli - Metodologie di Secure
Programming
86
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
SW auditing tools
S. Bistarelli - Metodologie di Secure
Programming
87
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
1. Software auditing

Auditing source code for correctness!!



Good practice!! 
Difficult and time-consuming 
Sardonix project (2003)



Record which code has been audited and by whom
Provide rank for people partecipating to the project (to be
used in the resume)
Help novice auditors with a lot of resources and FAQ


Static analyzers
Dynamic debuggers
S. Bistarelli - Metodologie di Secure
Programming
88
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
Sardonix resource

Static analyzers

Sintactically check the code

Ok for strongly typed languages (Java, ML, …)


Undecidable for for weakly typed languages (C,
Perl, …)


But some false positive/negative
Use some heuristics
Dynamic debuggers

Run the program under test loads
S. Bistarelli - Metodologie di Secure
Programming
89
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
2. Vulnerability mitigation tools
S. Bistarelli - Metodologie di Secure
Programming
90
Master di I° livello in Sistemi e Tecnologie per la sicurezza dell'Informazione e della Comunicazione
3. Behaviour management
S. Bistarelli - Metodologie di Secure
Programming
91
Fly UP