Le insidie di WordPress.com : Link Injection

[English Version: here]

Chi di voi , come il sottoscritto, fosse un affezionato utente della piattaforma wordpress.com credo sarebbe d’accordo con me sull’utilità e la praticità della voce “statistiche” nella gestione dei nostri blog. Essa infatti ci riporta diversi dati relativi alle visite al nostro blog: Visite giornaliere, notorietà dei nostri articoli, commenti, parole cercate nei motori di ricerca ma soprattutto i referer: ovvero da quale url gli utenti sono giunti nel nostro blog.

Questa funzionalità ci aiuta a capire se i nostri articoli vengono linkati dall’esterno e in tal caso ci permette di scoprire cosa si dice a proposito di quanto abbiamo scritto.

La pagina delle statistiche di questo Blog

Alcuni di voi avranno già capito dove voglio andare a parare: Il referer è un campo dell’header della request HTTP che il browser dell’utente che raggiunge il nostro blog, scambia con il server in cui il nostro blog è hostato. In particolare, questo campo indica qual’è l’url che conduce l’utente all’elemento corrente, in questo caso al nostro blog.
Come si potrebbe utilizzare questo referer per compiere un attacco al gestore di un blog WordPress.com?

L’hacker potrebbe modificare il campo referer dell’header HTTP e così pubblicare un qualsiasi link nella pagina di amministrazione del blog. Inoltre, l’hacker potrebbe creare diverse richieste http con il campo referer modificato così che la vittima, incuriosita da questa discreta “fonte di visite”, segua il link. A questo punto la vittima si ritroverebbe a scaricare la pagina indicata dall’hacker, esponendosi a diversi potenziali rischi (per l’hacker, il più è fatto).

La prima riflessione su quanto esposto riguarda la pericolosità di questo tipo di attacchi, infatti la piattaforma wordpress.com (come altre piattaforme esistenti e gratuite) risulta essere molto user friendly e non sempre chi ne fa uso possiede conoscenze in ambito di web security.

A questo bisogna aggiungere la semplicità dell’attacco : basta essere in grado di modificare un campo dell’header della richiesta http cosa realizzabile in modo estremamente semplice grazie all’estensione per firefox: modify headers, reperebile Qui

La finestra principale di Modify Headers

anche se personalmente preferisco utilizzare un tool avanzato come Webscarab, che mette a disposizione sotto un’unica interfaccia una miriade di funzionalità per l’analisi delle comunicazioni HTTP/S. Webscarab è un progetto parte dell’OWASP (Open Web Application Security Project).

Un aspetto molto importante riguarda la possibilità di inserire codice javascript nel referer, poiché nella pagina delle statistiche, viene stampato un input utente, l’applicazione è potenzialmente esposta al Cross Site Scripting (sono già alla ricerca di un possibile vettore javascript 😉 )

Concludo dicendo che l’utilizzo di questa tecnica per portare la vittima nella pagina web infetta è molto efficiente, in quanto non richiede un contatto diretto con la vittima (irc, mail , msn ecc).

Annunci

Session Storage: sicurezza delle applicazioni php ed insicurezze degli hosting condivisi

Php salva i dati relativi alle sessioni tramite la serializzazione, ovvero l’array $_SESSION viene linearizzato e salvato in un supporto come un file o un record di un database.

session storage

Il comportamento di questa caratteristica di php può essere controllato da due variabili di configurazione di php:

Session.save_handler: indica a php come viene salvata la sessione e in quale supporto, il valore di default è file (quindi php out of the box scrive i dati di sessione su un file) mentre gli altri valori possibili son user, mm e sqlite.

Session.save_path: indica la directory in cui le sessioni saranno salvate e mantenute. Il valore di default è /tmp (la mia installazione di xampp ad esempio salva in C:\xampp\tmp).

Al giorno d’oggi la maggior parte dei servizi di hosting forniscono un servizio di hosting condiviso, molto gettonato perchè abbassa di molto i costi sia per la gestione che per l’utente finale. Un setup del genere però, in cui diverse web application girano sullo stesso server in cui tutte le sessioni vengono salvate nella stessa directory porta degli enormi problemi di sicurezza, vediamo un esempio:

Un cliente del servizio di hosting ha due applicazioni web che girano sullo stesso server. Entrambe fanno uso di sessioni ma sono destinate ad utilizzi diversi; entrambe fanno uso di form per inserire dati nel sito ma la prima delle due applicazioni salva nella sessione anche l’input utente non filtrato, mentre la seconda mantiene in sessione soltanto dati filtrati.

Poiché le due applicazioni condividono lo spazio in cui vengono salvate le sessioni un possibile attacco consiste nel:

  1. Popolare la sessione della prima applicazione (che non filtra l’input) con dati creati ad hoc
  2. Modificare il cookie della sessione relativa all’applicazione 2 inserendo il session id dell’applicazione 1 (questa sessione contiene dati non filtrati)
  3. L’attaccante utilizza i dati non filtrati dell’applicazione 1 per danneggiare l’applicazione 2.

Altro scenario ancora più pericoloso riguarda la condivisione di spazio di salvataggio delle sessioni e dell’implementazione dell’applicazione: capita spesso che i servizi di hosting php mettano a disposizione alcuni CMS per facilitare l’avvio di un sito web, ecco quali sono i rischi:

  1. L’attaccante è un utente dell’applicazione 1 con certi privilegi, magari è un editor o un moderatore. In particolare l’applicazione 1 si apoggia su un CMS.
  2. L’applicazione 2 condivide la directory di salvataggio delle sessioni (sempre lo stesso servizio di web hosting un pò farlocco) ma in più si appoggia allo stesso CMS dell’applicazione 1.
  3. L’attaccante logga nella applicazione 2 come utente senza privilegi, copia il session id dell’applicazione 1 nel cookie dell’applicazione 2 e si ritrova loggato con gli stessi privilegi che aveva nell’applicazione 1 (perchè le due applicazioni fanno uso dello stesso sistema di gestione dei ruoli).

Vediamo quindi che potenzialmente, se un servzio di hosting, ospitante un sito non protetto, non si occupasse di dividere le directory dedicate alle sessioni, i problemi di sicurezza del sito non protetto potrebbero ripercuotersi anche sugli altri.

Ne consegue che la precauzione necessaria al fine di evitare queste falle di sicurezza è la divisione delle directory di salvataggio delle sessioni in applicazioni, così che ogni applicazione avrà la propria directory, ad esempio:

/tmp/applicazione1

/tmp/applicazione2 ecc..

Se il servizio di hosting in cui ci appoggiamo non ha già pensato a modificare la variabile del php.ini possiamo provare ad aggiungere la seguente riga di codice nella nostra applicazione:

ini_set(‘session.save_path‘, ‘/tmp/nostra_app‘);

Incrociando le dita e sperando che la funzione ini_set non sia inibita dal servizio di hosting.

Un’altra soluzione è quella di aggiungere una variabile all’interno della nostra sessione che identifichi univocamente la nostra applicazione, ad esempio:

session_start();

if (!isset($_SESSION[‘application’]) || ((string)$_SESSION[‘application’] !== ‘application_1’)) {

session_regenerate_id();

$_SESSION = array(‘application’ => ‘application_1′);

}

In questo modo il cookie modificato dall’attaccante sarà diverso dai cookie della nostra applicazione e l’id di sessione viene rigenerato.

Un metodo forse ancora più efficiente per gestire il mantenimento delle sessioni nel web server consiste nell’implementazione manuale delle funzioni di session storaging tramite la funzione set_session_save_handler(): essa permette di definire quali funzioni si occupano delle diverse operazioni di gestione delle sessioni.

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.