Corso di Sicurezza Informatica Sicurezza del software Ing. Gianluca Caminiti SQL Injection Sommario • Premessa sul funzionamento dinamici • SQL Injection: Overview • Scenari di attacco: dei siti • 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)