PDA

View Full Version : Non sempre disabilitare JavaScript equivale a migliore sicurezza: un esempio


Sisupoika
18-07-2009, 23:25
Come gia' spiegato nel precedente post (http://www.hwupgrade.it/forum/showthread.php?t=2018333), in questo momento sto lavorando alla implementazione, in un framework sul quale sto lavorando, di un numero di pratiche per la prevenzione dalla maggior parte dei possibili attacchi.

Mentre testavo un paio di cose in uno scenario con JavaScript disabilitato o "castrato" con NoScript (che, come detto spesso, odio perche' non e' la soluzione, e per lo piu' ha l'unico effetto di portare il web indietro di anni), e mi e' venuta in mente una considerazione del tipo di quelle che a volte passano per la testa ma sulle quali non ci si sofferma, di solito, nei dibattimenti, e che solitamente rimangono non documentate, non discusse, spesso ignorate.

C'e una pratica sulla quale molti appassionati (come si puo' spesso notare anche in questo stesso forum) concordano forse all'unanimita', spesso con quella particolare forma di "entusiasmo" che deriva da un falso senso di sicurezza, a sua volta a causa - imho - di scarsita' di informazione ecc.

E' quella di disabilitare JavaScript by default, nella convizione che JavaScript disabilitato sia sinonimo di maggiore sicurezza.

Naturalmente, non sono d'accordo, come gia' detto in diverse occasioni quando si e' parlato di numerose possibilita' di attacco che con JavaScript hanno nulla a che vedere - di recente di parlava di alcune varianti di Click Jacking (http://en.wikipedia.org/wiki/Clickjacking), e ci fu un certo clamore. Un po' come la colossale balla, in cui molti purtroppo credono, secondo cui un sito che faccia uso di SSL / HTTPS sia sicuro (http://www.hwupgrade.it/forum/showthread.php?p=27595055#post27595055).

Bene, forse non molti si saranno resi conto che c'e' almeno un aspetto, legato a possibili attacchi di tipo XSRF (http://www.hwupgrade.it/forum/showthread.php?t=2018333) o di simile classificazione, che rende piu' sicuri con JavaScript abilitato.

Mi riferisco alla Same origin policy (http://en.wikipedia.org/wiki/Same_origin_policy) di cui si e' spesso parlato, incluso il mio precedente post.
Assumo si sara' ormai inteso che molti attacchi di vario tipo fanno uso di tags in una pagina maligna che, di nascosto, inducono il browser ad effettuare delle richieste HTTP verso un sito vittima. O meglio: la vittima e' l'utente, poiche' si cerca di fargli, in pratica, compiere azioni a sua insaputa.

Ci sono moltissime varianti, ma in genere questo tipo di roba e' chiamata request forgery.

Bene, senza ripetere cose di cui si e' parlato piu' in dettaglio in apposite sedi, voglio soltanto ricordare che questi attacchi, generalmente parlando, per funzionare con successo hanno bisogno che:

- il sito attaccato utilizzi cookies per verificare se una richiesta e' autenticata oppure no (cioe' se l'utente per conto del quale essa viene operata, e' loggato oppure no). E cio' viene per mezzo di cookies di autenticazione

- l'utente abbia una sessione attiva al sito attaccato (cioe', anche se non e' sul sito in quel momento, e' sufficiente che il browser conservi un cookie di autenticazione ancora valido, non scaduto, ecc)

Ricordo anche che questo e' necessario affinche' request forgery funzioni nelle sue principali varianti: infatti, nel momento in cui una richiesta viene effettuata di nascosto verso il sito attaccato in una delle modalita' descritte negli altri threads, il browser invia assieme alla richiesta i cookie che conserva per il dominio del sito attaccato. E' questo funzionamento base del web che rende l'attacco possibile poiche' la richiesta viene autenticata come se l'utente l'avesse generata durante l'uso del sito attaccato stesso.

Veniamo dunque alla considerazione: il browser, nell'inviare il cookie di autenticazione assieme alla richiesta nascosta, non si preoccupa di verificare il dominio della pagina dalla quale quella richiesta e' stata generata. Questo perche' il protocollo HTTP di per se' non prevede restrizioni come quelle dettate dalla same origin policy, per l'effettuazione delle semplici richieste GET/POST ecc.

A precindere se JavaScript e' disabilitato o meno in quel momento, quel cookie di autenticazione verra' inviato comunque e la richiesta verra' soddisfatta per molte varianti di XSRF (non tutte, come e' stato spiegato nell'altro post).
Questo, a meno che l'applicazione verifichi il referer (http://en.wikipedia.org/wiki/HTTP_referrer) (in breve, il referrer e' un header inviato con la richiesta, che identifica l'indirizzo che ha originato la richiesta stessa. Se per esempio nella pagina http://miosito.com/pagina.html c'e' uno SCRIPT tag che genera un' altra richiesta per scaricare lo script, il referrer per questa seconda richiesta sara' http://miosito.com/pagina.html).

Ma controllare il referrer e' qualcosa che quasi nessuno fa, e comunque sarebbe poco utile perche' alcune estensioni nei browsers, o proxy in alcuni casi, eliminano il referrer. E' anche molto facile fare "spoofing (http://en.wikipedia.org/wiki/Referrer_spoofing)" del referrer in molti casi. Quindi controllare il referrer non e' molto pratico.

Dunque rimane che a prescindere da JavaScript, il cookie di autenticazione viene inviato con la richiesta anche se tale richiesta e' generata da un dominio diverso.

Cosa accade invece se JavaScript e' disponibile?

Accade che e' possibile ovviare a quel problema, e far si' con un piccolo trucchetto che la same origin policy venga rispettata, e che il cookie di autenticazione, o meglio le informazioni di autenticazione in esso contenute, vengano correttamente inviate con la richiesta soltanto se la richiesta e' originata dallo stesso dominio dell'indirizzo di destinazione della richiesta stessa.

Come? Semplice (e' una delle mille pratiche che sto implementando nel mio framework :D)

Invece di verificare - server side - il cookie di autenticazione direttamente, le informazioni di autenticazione possono essere passate alla richiesta mediante JavaScript:

1) JavaScript legge, client side, il cookie che contiene le informazioni di autenticazione

2) estrae dal contenuto del cookie l'informazione necessaria per l'autenticazione

3) calcola l'hash con MD5 (http://en.wikipedia.org/wiki/MD5) o altro (l'importante e' usare un argomento abbastanza veloce, visto che esso deve essere elaborato col lento JavaScript)

4) appende l'hash calcolato alla richiesta, ad esempio come parametro nella query string per richieste GET, oppure come campo nascosto nei form POST.

5) l'applicazione server side leggera' il contenuto del cookie, calcolera' allo stesso modo l'hash MD5 dell'informazione di autenticazione in esso contenuta, e ne comparira' il valore con quello inviato come parametro direttamente con la richiesta.

Perche' funziona?

Funziona perche' JavaScript rispetta* (http://www.hwupgrade.it/forum/showthread.php?t=1987360) la same origin policy.

Caso A: La richiesta viene effettuata dal sito originale:

JavaScript puo' leggere il cookie dal dominio attraverso document.domain, proprio grazie al fatto che il codice JavaScript viene eseguito nello stesso dominio nel quale il cookie di autenticazione e' stato salvato dalla applicazione. Pertanto l'MD5 potra' essere calcolato e il valore confrontato server side come spiegato. Autenticazione OK! La richiesta puo' essere esaudita.

Caso B: La richiesta viene effettuata di nascosto, ecc, da un altro sito, quello dell'attaccante:

Il codice JavaScript eseguito nella pagina del sito attaccante - dominio diverso - non puo' leggere il contenuto del cookie del sito attaccato con document.domain, a causa della same origin policy.
Pertanto non sara' in grado di calcolare l'MD5 giusto, e il confronto server side fallira'.
Risultato: i dati richiesti non verranno inviati al client. :)

Note per chi non ha famigliarita' con alcuni termini:
- MD5 e' un algoritmo che, come altri consente di (detta in parole mooolto semplici) giungere ad una stringa B a partire da una stringa A. Caratteristiche: e' molto semplice, e richiedere piccolo sforzo computazionale il passaggio A -> B. Ottenere B da A e' invece una mostruosita' in termini di sforzo computazionale e dunque di tempo necessario.
Un attaccante che pure, in qualche modo, riesca a "catturare" un numero sufficiente di valori cosi' generati, non sarebbe in grado di determinare i valori di partenza e dunque capire come essi vengono generati e gestiti.
- Come spiegato in un altro post (http://www.hwupgrade.it/forum/showthread.php?t=1987360), esiste la possibilita' di ottenere cookies da un dominio diverso anche con JavaScript, ma questa possibilita' e' attuabile soltanto in determinate condizioni e per le ragioni descritte nel post, e' un problema probabilmente destinato a scomparire nell'immediato futuro.

Questo e' soltanto un esempio di casi in cui JavaScript disabilitato non significa automaticamente migliore sicurezza.

A questo punto, in chiusura, i piu' attenti si saranno chiesti:
OK, se JavaScript e' disabilitato e dunque il trucchetto MD5 eccetera non puo' essere usato, il cookie di autenticazione viene passato, la richiesta viene autenticata correttamente, e i dati richiesti inviati al client.
Ma non e' comunque necessario JavaScript per accedere ai dati ottenuti?

La risposta e': non necessariamente :D
Durante esperimenti e ricerche, ho trovato due siti vulnerabili (uno l'ho trovato attraverso la signature di un utente qui sul forum! :sbonk: ) grazie al fatto che questi siti si comportano in maniera diversa a seconda se JavaScript e' abilitato oppure meno. :D
Non scendo nei dettagli perche' sto ancora sperimentando ma anche perche' non ricordo di aver letto di tecniche simili, quindi per ovvie ragioni. :p

ciaps

riazzituoi
19-07-2009, 17:03
.

Sisupoika
19-07-2009, 18:18
A quali specifiche ti riferisci di preciso?