Corso di Sicurezza Informatica Sicurezza del software Ing. Gianluca Caminiti
SQL Injection
Sommario Premessa sul funzionamento dei siti dinamici SQL Injection: Overview Scenari di attacco: Errata gestione dell input (mancato filtraggio o mancata gestione del tipo di dati) Strategie di attacco attacchi Blind Contromisure
Premessa: Siti Web Dinamici Interfaccia Web (lato client: HTML, Flash, Javascript) Linguaggio di programmazione orientato a web/database ( tipicamente lato server: PHP, ASP,.NET, JSP, ecc.) Database layer (lato server: MySQL, Oracle, SQL Server, ecc.)
Interfaccia verso il DB Il linguaggio di programmazione server-side permette di formulare queries in SQL, parametrizzabili mediante variabili tipicamente passate da un form HTML.
Esempi moduli HTML per ricercare nell archivio di un DB online (Amazon, IBS, ecc.) moduli per accesso a web-based email (login + password, es. Hotmail) moduli per inserimento di commenti sui siti (guestbook, forum, ecc.)
SQL Injection: Overview Tecnica che sfrutta una vulnerabilità presente nel linguaggio che funge da interfaccia al DB e/o nello strato del DB al fine di produrre un alterazione nella semantica del codice SQL inteso. Si fa in modo che l input dell utente contenga istruzioni SQL al fine di ottenere (lato server) una query differente da quella intesa dal programmatore.
Scenari tipici La vulnerabilità è presente quando si verifica una delle seguenti condizioni: L input inserito dall utente non è affatto o correttamente filtrato rispetto alle occorrenze di sequenze di escape (tipicamente presenza di apici). L input inserito dall utente non subisce verifiche sul tipo di dati e pertanto sono possibili esecuzioni inaspettate. Sono presenti errori di programmazione nel software del server di Database che consentono a utenti malicious di sfruttarne gli effetti per eseguire codice SQL arbitrario.
1. Sequenze di escape non filtrate correttamente un semplice modulo HTML per inserire username e password <form action='login.php' method='post'> Username: <input type='text' name='user' /> Password: <input type='password' name='pwd' /> <input type='submit' value='login' /> </form> I dati immessi sono passati al file login.php, rispettivamente nelle variabili $_POST['user'] e $_POST['pwd']. Una volta ricevuti questi dati, PHP esegue una query sul DB.
codice PHP <?php $query = "SELECT * FROM users WHERE user='".$_post['user']."' AND pwd='".$_post['pwd']. "'"; $sql = mysql_query($query,$db); //Se il numero di righe trovate > 0 allora i dati immessi sono corretti if(mysql_affected_rows($sql)>0) { //permette l'accesso alle pagine protette }?>
Esempio con input tipico L utente inserisce BillGates come user e Windows come password. La query sarà SELECT * FROM users WHERE user='billgates' AND pwd= 'Windows'
Esempio di attacco/1 L utente inserisce BillGates come user e ' OR user='billgates come password. La query sarà SELECT * FROM users WHERE user='billgates' AND pwd= '' OR user='billgates Quando funziona questo attacco?
Esempio di attacco/1 L utente inserisce BillGates come user e ' OR user='billgates come password. La query sarà SELECT * FROM users WHERE user='billgates' AND pwd= '' OR user='billgates L attacco funziona solo se esiste un utente BillGates
Esempio di attacco/2 Attacco blind: l utente inserisce x' OR 1=1 sia come user che come password. La query sarà SELECT * FROM users WHERE user='x' OR 1=1 AND pwd='x' OR 1=1 Qual è l effetto di questa query?
Esempio di attacco/2 Attacco blind: l utente inserisce x' OR 1=1 sia come user che come password. La query sarà SELECT * FROM users WHERE user='x' OR 1=1 AND pwd='x' OR 1=1 Il risultato non dipende dalla precedenza degli operatori: la condizione è sempre vera, ci si autenticherà come l utente rappresentato dalla prima tupla del DB (admin?)
Simulazione di Attacco
2. Scorretta gestione dei tipi di dati Attacco NON blind: si verifica quando mancano verifiche sui vincoli di tipo dei dati di input. Si pensi ad un modulo per la ricerca di prodotti in un catalogo in base al codice. $query = "SELECT * FROM data WHERE id=".$variabile_intera. ";" La variabile $variabile_intera è di tipo stringa, anche se il tipo di dati inteso per l input è int. L utente può inserire come id la stringa: 1; DROP TABLE data SELECT * FROM data WHERE id = 1; DROP TABLE data; Cosa succede se l utente inserisce come input 1; SELECT * FROM data?
Blind SQL Injection Per indovinare i nomi delle tabelle SELECT COUNT(*) FROM tabname (restituisce valori solo quando la tabella tabname esiste) Per indovinare i nomi dei campi delle tabelle SELECT x FROM users (con x che rappresenta il tentativo) Per indovinare i nomi degli utenti SELECT 1/0 FROM users WHERE username='ralph'
Contromisure Verificare bug ed exploit del sistema in uso fissare limitazioni sui diritti di accesso al DB filtrare opportunamente le sequenze di escape (ci sono funzioni appositamente definite nei linguaggi) whitelisting basate su espressioni regolari forzare la conversione di tipo delle variabili di input nel target desiderato (es. stringa int)