Seminario AVP a.a. 2006/2007:
SQLrand: Preventing SQL
Injection Attacks
Stephen W. Boyd & Angelos D. Keromytis
Columbia University
Elia Gaglio 809477 & Mirco Tonin 804425
1
Code injection attacks

“SQL injection attack” è un’istanza dei code
injection attacks

Code injection attacks: classe di attacchi che
sfruttano il buffer overflow

code injection attacks
analisi di un attacco basato sul buffer overflow:

definizione informale: un buffer overflow si verifica

conseguenza: sovrascrittura della porzione di
ogni qual volta l’insieme dei dati è più grande del
buffer ove dovranno essere memorizzati
sql injection
attacks
memoria successiva al buffer, contenente istruzioni
macchina necessarie ad una normale esecuzione del
programma
2
Buffer Overflow (1/3)


Contesto fondamentale per il verificarsi di un BOF:
chiamata ad una funzione
Esempio. Consideriamo il seguente scenario:

architettura Intel x86 (32 bits):

registri, salvati nello stack, coinvolti nel BOF:





EBP (Base Pointer)(4 bytes): puntatore alla base della
porzione dello stack che stiamo utilizzando
EIP (Instruction Pointer) (4 bytes): puntatore all’istruzione
successiva
crescita dello stack verso indirizzi bassi di memoria
“buff”: buffer di 8 caratteri (8 bytes)
chiamata alla funzione del C, gets: legge dallo
standard input, copia quanto letto in “buff” senza
fare nessun controllo se la stringa inserita sia più
grande del buffer di destinazione
OBIETTIVO: sfruttare gets per sovrascrivere i
registri EBP e EIP salvati sullo stack,
alterando così il normale flusso di esecuzione
del programma
l’attaccante deve
conoscere
l’architettura del
sistema target
3
Buffer Overflow (2/3) (animata)
0x00000000
programma C:
assembler:
2.
char buff[8];
3.
gets(buff);
4. }
00401258
push ebp
.
.
.
5.
6. int main(void){
7.
leggistringa();
00401250 call 00401258
8.
return(0);
00401255
9. }
…………
buffer overflow
riempimento dello stack
1. void leggistringa(void){
buff[0]:
buff[1]:
buff[2]:
buff[3]:
buff[4]:
buff[5]:
buff[6]:
buff[7]:
1
2
3
4
5
6
7
8
1 byte
EBP
aaaa: 61616161
EIP: 00401255
bbbb:
62626262
4 bytes
stringa in input: 12345678aaaabbbb
0x61616161
0x62626262
All’uscita della funzione, avremo che EIP=0x62626262 EBP=0x61616161
indirizzi alti
4
Buffer Overflow (3/3)


Cosa succede?
La cpu tenterà di eseguire l’istruzione che si trova all’indirizzo
contenuto nel registro EIP ovvero 0x62626262, incorrendo in
uno di questi casi:

il numero esadecimale 0x62626262 rappresenta un indirizzo che va
fuori dall’intero spazio di memoria dedicato al processo
segmentation fault

0x62626262 è un indirizzo valido per il processo in esecuzione. Tale
indirizzo potrebbe puntare a del codice maligno inserito da un
attaccante
code injection attack
5
Contromisura: ISR

all’interno dei code injection attacks, ricadono
alcuni tipi di attacchi recenti e poco conosciuti:




sebbene le tecniche usate in ogni tipo d’attacco
differiscono tra loro, tutte hanno un denominatore
comune:



SQL injection
Unix command line
Perl code injection
l’attaccante inserisce e fa eseguire codice di sua
scelta: codice macchina, shell commands, SQL
queries,…
code injection attacks
sql injection
attacks
Perl code
injection
unix shell
commands
da tale fatto, si ricava che alla base di ogni code
injection attack c’è la conoscenza da parte
dell’attaccante circa l’ambiente / linguaggio
interpretato di programmazione del sistema target
contromisura: un approccio generale di prevenzione verso qualsiasi code
injection attack: Instruction-Set Randomization
6
Un pò di storia…

inquadramento storico:

anno 2003 Columbia University :

Countering Code-Injection Attacks With
Instruction-Set Randomization
Gaurav S. Kc, Angelos D. Keromytis, Vassilis Prevelakis
applicazione del metodo ISR
al linguaggio SQL

anno 2004 Columbia University:

SQLrand: Preventing SQL Injection Attacks
Stephen W. Boyd, Angelos D. Keromytis
nostro articolo
7
Instruction-Set Randomization
per ogni processo, attraverso una chiave di codifica la più grande possibile, viene creato un
insieme unico di istruzioni randomizzate
tali nuove istruzioni andranno a sostituire il codice sorgente del programma originale


verrà creato un ambiente di esecuzione unico per il running process così che l’attaccante
non conosce il “linguaggio” usato e di conseguenza non puo’ “speak” alla macchina (non
conosce la key di randomizzazione)

due alternativi approcci nell’uso della chiave per la codifica/decodifica (architettura x86 a 32
bits):


XOR bit a bit tra istruzione e chiave:
ENCODING KEY
D xor KEY = E
E xor KEY= D
(codifica e decodifica hanno la stessa chiave)
attacco brute force: 232

trasposizione randomizzata (basata sulla
chiave) dei bit:
(la chiave di decodifica sarà l’inversa)
attacco brute force: 32! ( 32! >> 232)
=> sicurezza maggiore

ENCODED
INSTRUCTION
STREAM
CPU
xor
decoded instruction
stream
in ogni caso, una chiave di 32 bits è sufficiente per una protezione verso attacchi di
code injection
8
Esecuzione di un randomized program


ISR è focalizzato primariamente su attacchi contro remote
services (http, dns,…): attacchi che non richiedono un local
account sul sistema target
Esecuzione di un generico programma:





il codice di ciascun processo (P) è caricato dal rispettivo file eseguibile memorizzato su
disco (efP)
tale ‘executable file’ contiene all’interno
dell’header, l’appropriata chiave di decodifica
(DkeyP) del processo caricato in memoria
SO
PCB:
nel frattempo, il sistema operativo estrae la
chiave di decodifica dall’header dell’eseguibile
e la memorizza nel rispettivo Process Control
Block del processo
quando la cpu eseguirà il processo P, la chiave
di decodifica (DkeyP) sarà presa dal PCB e
copiata in un speciale registro del processore
ciò avviene attraverso un’istruzione privilegiata
GAVL che permette un accesso in sola scrittura
nel speciale registro di CPU.
ram
P
CPU
registers:
DkeyP
DkeyP
efP
DkeyP
disco
9
Ambiente di esecuzione (1/2)


per quei programmi che non sono stati randomizzati, viene fornita una speciale
chiave (chiave nulla), che quando caricata attraverso l’istruzione GAVL, disabilita
il processo di decodifica
l’esecuzione delle randomization instructions, necessita della scelta tra due
possibili soluzioni:
l’utilizzo di una apposita
categoria di processori
programmabili
(e.g. TransMeta Crusoe,
alcuni ARM-based systems)
l’introduzione di un ambiente di
esecuzione protetto che emuli una CPU
convenzionale
sandboxing environment sarà composto da:
• un CPU emulator: bochs (emulatore open
source architetture x86)
• sistema operativo
• l’insieme di processi che si vuole proteggere
10
Performance


risultati sperimentali:
ftp
sendmail
fibonacci
bochs
39.0s
≈28 s
5.73s (93s)
linux
29.2s
≈ 1.35s
0.322s
ftp & sendmail (processi I/O intensive):


tempo di esecuzione (in secondi) per identici
file binari su Bochs e una macchina Linux
(sulla quale è stato fatto girare bochs)
una perdita contenuta nelle performance
fibonacci (CPU intensive application):

tremendo slowdown (inaccettabile)
11
ISR su altri linguaggi (1/2)

Le idee e i concetti, introdotti al fine di ottenere un’esecuzione sicura
delle istruzioni macchina, sono state estese per garantire la sicurezza
d’esecuzione di diverse tipologie di programmi:

Perl files:

utilizzo dello script Perltidy:

input: ns. programma perl P
foreach $k (sort keys %$tre){
$v = $tre ->{$k};
die ``duplicate key $k\n’ ’
if defined $list {$k};
push @list, @{ $list{$k} };
}

output: programma P’, dove ad ogni costrutto perl in P è stata appesa la chiave (‘tag’)
foreach123456789 $k (sort123456789 keys %$tre){
$v =123456789 $tre ->{$k};
die123456789 ``duplicate key $k\n’ ’
if123456789 defined123456789 $list {$k};
push123456789 @list, @{ $list{$k} };
}


la chiave (‘tag’) viene fornita via a command line argument
è necessario una modifica dell’analizzatore lessicale dell’interprete Perl, affinchè
possa riconoscere le keywords seguite dal corretto ‘tag’
12
ISR su altri linguaggi (2/2)

Script Unix:



utilizzo di uno script CGI per la generazione di randomized bash
scripts
ogni shell command dello script unix avrà in append la chiave di
randomizzazione (‘tag’)
l’interprete bash dovrà essere modificato al fine di riconoscere le
nuove keywords (commad+tag)
#!/bin/sh
if987654 [ x$1 ==987654 x””; then987654
echo987654 “Must provide directory name.”
exit987654 1
fi987654
/bin/ls987654 –l $1
exit987654 0
13
SQL Injection Attacks:

SQL Injection Attacks:

SQL Injection Attacks è un code injection attack verso un DB…

Attacchi orientati verso script CGI che creano dinamicamente query SQL


OBIETTIVO: carpire/modificare/inserire informazioni verso un DB
interfacciato da una web application
Diverse tipologie di attacco possibile, le quali sfruttano vulnerabilità
differenti…
14
Esempi di SQL Injection Attacks [1/5]
• CONTESTO: pagina di login ad un servizio web, realizzata mediante
un’applicazione CGI (si richiedono username e password)
• Nel momento in cui l’utente inserisce i dati viene generata la query:
“select * from mysql.user
where username = ’ ” . $uid . ” ’ and
password = password(’ ” . $pwd . ” ’);”
• Un eventuale utente maligno inserendo nel campo username la
stringa ‘or 1=1; --’ causa la generazione da parte dello script della
query:
“select * from mysql.user
where username = ’ ’ or 1=1; --’ ’ and
password = password(’_any_text_’);”
15
Esempi di SQL Injection Attacks [2/5] (animata)
• CONTESTO: applicazione ASP che si interfaccia tramite driver ODBC
SQL Server Driver ad un generico DBMS
• Esiste la possibilità di attaccare il DB sfruttando i messaggi di errore
forniti:
• Se l’utente password
inserisse un username fasullo aaa’ verrebbe invocata la
URL:
http://127.0.0.1/login.asp?userid=aaa‘
• L’apice finale porterebbe però al seguente messaggio di errore:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Unclosed quotation
mark before the character string 'aaa' AND password = ''.
/login.asp, line 7
16
Esempi di SQL Injection Attacks [3/5] (animata)
• Si può sfruttare la conoscenza acquisita per invocare una nuova URL
fittizia in modo da ottenere il nome delle colonne di una tabella:
http://127.0.0.1/login.asp?userid=ddd'%20group%20by%20(password)-tblUsers
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
username
password
[Microsoft][ODBC
SQL Server Driver][SQL Server]Column
'tblUsers.username' is invalid in the select list because it is
not contained in either an aggregate function or the GROUP BY
clause.
/login.asp, line 7
• Il procedimento prosegue fino a quando tutti i nomi delle colonne
sono scoperti…
17
Esempi di SQL Injection Attacks [4/5] (animata)
http://127.0.0.1/login.asp?userid=aaa'%20group%20by%20(username)-Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]Column
tblUsersin the select list because it
'tblUsers.lastloggedin' is invalid
is not contained in either an aggregate function or the GROUP BY
clause.
lastloggedin
username
password
/login.asp, line 7
• E’ anche possibile determinare il tipo relativo a ciascuna colonna della tabella:
nvarchar
http://127.0.0.1/login.asp?userid=aaa'%20compute%20sum(username)-Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average
aggregate operation cannot take a nvarchar data type as an
argument.
/login.asp, line 7
18
Esempi di SQL Injection Attacks [5/5] (animata)
• Dopo aver a disposizione la struttura della tabella sarà possibile da
parte dell’attaccante inserire un nuovo account fasullo nel DB:
tblUsers
http://127.0.0.1/login.asp?userid=aaa' insert into
tblusers(username,password,lastloggedin,status) values
status
username 31lastloggedin
('jsmith','secret','Oct
2000 8:52PM','foo')-password
nvarchar
secret
nvarchar
jsmith
date
nvarchar
Oct 31 2000 8:52PM
foo
19
SQL Injection Attacks – alcune soluzioni
•
Come si possono fronteggiare gli SQL Injection Attacks?
•
Accorgimenti per aumentare la sicurezza dell’applicazione (uso di caratteri
di escape, filtraggio dei messaggi di errore, limitare la lunghezza dei campi
di input, ecc.);
•
Utilizzo di costrutti “safe” (es. Prepared statement):
 Libreria per la gestione in automatico della formattazione dei tipi
rappresentabili nel DBMS (stringhe, date, ecc.)
 Garantisce una sicurezza sull’esatta sintassi della query SQL risultante
PreparedStatement ps = conn.prepareStatement (“SELECT * FROM
mysql.user WHERE username = ? AND password = ?”);
String user = req.getParameter(“userid”);
String pwd = req.getParameter(“password”);
ps.setString(1, user);
ps.setString(2, pwd);
ResultSet rs = ps.executeQuery();
20
SQL Injection Attacks – SQL Randomization [1/6]
• Si possono inoltre utilizzare delle tecniche specializzate molto
interessanti, SQL Randomization:
 Soluzione efficace per fronteggiare SQL Injection Attacks
 Tecniche e principi derivati dall’ Instruction Set Randomization
 Query randomizzate prodotte dallo script CGI
SQL Randomization

Necessità di modificare l’interprete SQL del
DB (in analogia all’approccio seguito per ISR)



introduzione di un ling. sql modificato
riscrittura dei precedenti programmi

Introduzione di un proxy per
effettuare la de-randomizzazione
delle query
Possibilità di usare:


una key per ogni applicazione
keys differenti per applicazioni differenti
21
SQL Injection Attacks – SQL Randomizations [2/6]
• Introduzione di un proxy per de-randomizzare le query prodotte lato
client:
• In questo modo le query prodotte lato client saranno comprensibili
dall’interprete SQL del DB
• Il proxy lavora esclusivamente a livello sintattico, effettuando anche il
filtraggio dei messaggi di errore provenienti dal DB
22
SQL Injection Attacks – SQL Randomizations [3/6]
• Le 2 principali componenti del proxy sono:
1) Elemento di de-randomizzazione:
 presenza di un parser FLEX modificato (legge un array di caratteri di
input in arrivo dalla rete)
 trattamento esplicito per gli errori sintattici (disconnessione del client ed
invio di un generico messaggio di sintax error)
2) Protocollo di comunicazione:
 MYSQL fornisce API per l’accesso al DB ma non fornisce librerie serverside che accettano e disassemblano i pacchetti inviati
 Utilizzo di una libreria di base per gestire query, errori e pacchetti di
disconnessione
23
SQL Injection Attacks – SQL Randomizations [4/6] (animata)
• La soluzione finale proposta per gestire le comunicazioni è la
seguente:
api mysql LATO CLIENT
CLIENT
C
S
PROXY
api mysql LATO CLIENT
C
S MYSQL DBMS
Libreria: gestisce
query, errori e
pacchetti di
disconnessione
• Proxy componente invisibile verso il client
proxy e DBMS sono sulla stessa macchina
(è necessario solamente specificare la porta relativa al proxy)
24
SQL Injection Attacks – SQL Randomizations [5/6]
• Vediamo un semplice esempio pratico di randomizzazione. Partiamo
dalla seguente query:
select gender, avg (age)
from cs101.students
where dept = %d
group by gender
• La randomizzazione è basata sull’append di una sequenza di interi
random applicata alle keywords di ogni query. Nel nostro esempio:
select123 gender, avg123 (age)
from123 cs101.students
where123 dept = %d
group123 by123 gender
25
SQL Injection Attacks – SQL Randomizations [6/6]
• A questo punto se un utente maligno volesse formulare un tipico attacco
mediante l’inserimento della stringa ’ or 1=1; --’ causerebbe la generazione della
query:
select gender, avg (age)
from cs101.students
where dept = ’ or 1=1; --’
group by gender
• La randomizzazione della query comporta che ogni keyword del linguaggio SQL
sia randomizzata. Ma la or, essendo una parola dell’input utente, non è soggetta
a randomizzazione  la query viene considerata maligna!
select123 gender, avg123 (age)
from123 cs101.students
where123 dept = ’ or 1=1; --’
group123 by123 gender
26
Prove sperimentali
Sono state effettuate due tipologie di test:

1.
un’applicazione CGI creata (ad hoc) dagli autori stessi:


nessuna validazione sull’input
possibilità di inserire codice SQL nella clausola “where” che si aspetta
un account ID


2.
senza SQLrand proxy: un attaccante facilmente ottiene informazini sugli
account degli utenti
con SQLrand proxy: injected statement identificato ed emissione di un
generico messaggio d’errore
identificare SQL injection attacks su applicazioni web pre-esistenti e
molto diffuse:


phpBB v2.0.5
php-Nuke
attacchi neutralizzati con
l’uso del proxy
27
Performance evaluation

Scenario di test:








3 insiemi di utenti concorrenti: 10 - 25 - 50
esecuzione delle classi in modo round robin
in totale 100 prove: ciascuna con 5 differenti query concorrenti
lunghezza chiave: 32 bytes
lunghezza media queries: 639 bytes
la dimensione dei record delle tabelle ranged da 20 a poco piùdi 11.000 records
database, proxy e client running su separate macchine x86 con SO RedHat Linux, e tutte sulla stessa rete
Users
Min
Max
Mean
Std
10
74
1300
183.5
126.9
25
73
2782
223.8
268.1
50
73
6533
316.6
548.8
proxy overhead (in microsecondi)
Nel peggior dei casi, si ottiene un ritardo di 6.5 millisecondi per ciascuna query

sapendo che se intercorre un tempo che varia da pochi secondi a 10 secondi (a seconda dello scopo
dell’applicazione) la risposta di una web application è considerata persa
l’overhead introdotto dal proxy è insignificante

future work: sviluppo di developing tools per assistere i programmatori
nell’utilizzo di SQLrand
28
ISR: vantaggi - svantaggi

riportandoci al contesto più generale: Instruction-Set Randomization

Vantaggi:

possibile ri-randomizzazione periodica dei programmi in modo da minimizzare il rischio
di attacchi persistenti. Ovvero:





nei sistemi operativi open source: quando il sistema viene ricompilato
nelle distribuzioni binarie: periodica re-randomization attraverso un automated script
in fase d’installazione
ISR offre trasparenza ad applicazioni, linguaggi e compilatori, nessuno dei quali deve
essere modificato
Svantaggi:

l’utilizzo di cpu programmabili per il supporto di istruzioni randomizzate


feature non implementata dallla maggioranza dei processori in commercio
alternativamente: emulatore

inaccettabile overhead in tutte le applicazioni CPU intesive
29
Estensioni & sviluppi futuri [1/4]
•
4 filoni di ricerca contro i Buffer Overflow Attacks:
1) Safe Languages and Compilers: - introduzioni di linguaggi di programmazione
safe (Java, Modula3, ecc.)
- estensioni dei vecchi linguaggi per renderli
safe (es. C), senza snaturarne le proprietà
▪ linguaggi ad alto livello e astratti
Java/Modula3
▪ nessuna gestione esplicita della memoria
▪ no al controllo dei dati a basso livello
30
Estensioni & sviluppi futuri [2/4]
•
Come è possibile rendere un linguaggio d’origine “safe” ?
Vantaggi:
 semplice utilizzo da
parte del programmatore
Librerie sicure  librerie condivise e precaricate per intercettare le chiamate di
funzione delle librerie – trasparenti al
programmatore;
API  librerie esplicitamente richiamabili da
un programma. Forniscono delle primitive
maggiormente sicure.
 non è necessario
passare ad un nuovo
linguaggio di
programmazione
Svantaggi:
 protezione riferita solo
ad alcune primitive
specifiche
31
Estensioni & sviluppi futuri [3/4]
2) Compiler Tricks: utilizzo di patch per i più diffusi compilatori (es. gcc)
 protezione verso accessi/allocazioni di memoria, gestione
corretta dei puntatori, controllo sulle dimensioni e rispetto
dei limiti degli array, ecc.
 contro: mancanza di protezione verso alcuni tipi di code
injection attack / introduzione di overhead
3) Process Sanboxing: esecuzione dei processi in un ambiente protetto
 filtraggio degli accessi alle system calls
 effettuare dei checks a run-time del programma,
monitorando i trasferimenti del controllo del flusso del
programma (salti condizionati, salti incondizionati, ecc.)
32
Estensioni & sviluppi futuri [4/4]
4) Source Code Analysis: rilevazione di vulnerabilità nel codice (es. gets() in C)
 tipicamente si sollevano dei warning a tempo di compilazione del
programma
 esistono 2 tipi di approcci:

approccio statico: tecniche di analisi statica per rilevare classi

approccio dinamico: analisi a run-time per effettuare dei
di attacchi e vulnerabilità conosciute
controlli sulle procedure/funzioni richiamate, grazie
all’introduzione di una data structure che fornisca
informazioni sulle strutture allocate nel programma
33
Bibliografia





G. S. Kc, A. D. Keromytis, and V. Prevelakis. Countering Code-Injection Attacks With
Instruction-Set Randomization. In Proceedings of the ACM Computer and Communications
Security (CCS) Conference, pages 272–280, October 2003.
Luigi Auriemma. Buffer overflow: spiegazione tecnica ed esempio pratico. Aprile 2003.
http://www.siforge.org/articles/2003/04/15-bofexp.html
G. Mazzei, A. Paolessi, S. Volpini. Buffer Overflow. In Corso di Sistemi Operativi, Facoltà di
Ingegneria, Università degli studi di Siena, anno accademico 2001/2002.
http://www.clusit.it/whitepapers/GASBof.pdf
T. Jim, G. Morrisett, D. Grossman, M. Hicks, J. Cheney, and Y. Wang. Cyclone: A safe dialect
of C. In Proceedings of the USENIX Annual Technical Conference, pages 275–288,
Monterey, California, June 2002.
T. C. Miller and T. de Raadt. strlcpy and strlcat: Consistent, Safe, String Copy and
Concatentation. In Proceedings of the USENIX Technical Conference, Freenix Track, June
1999.

A. Baratloo, N. Singh, and T. Tsai. Transparent run-time defense against stack smashing
attacks. In Proceedings of the USENIX Annual Technical Conference, June 2000.

D. Litchfield. Web Application Disassembly wth ODBC Error Messages.
http://www.nextgenss.com/papers/webappdis.doc
34
Scarica

SQL Injection Attacks