2010-07-23 9 views
21

Sto lavorando su un'applicazione completamente Ajax-driven in cui tutte le richieste passano attraverso quello che in pratica equivale a un controller principale che, nelle sue ossa nude, simile a questa:Un server di intestazione X-Requested-With è sufficiente per proteggere da un CSRF per un'applicazione basata su ajax?

if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { 
    fetch($page); 
} 

È questo generalmente sufficiente a proteggere contro falsi di richieste cross-site?

È piuttosto scomodo avere un token di rotazione quando l'intera pagina non viene aggiornata ad ogni richiesta.

Suppongo che potrei passare e aggiornare un token univoco come variabile javascript globale con ogni richiesta, ma in qualche modo mi sento goffo e sembra comunque insicuro.

EDIT - Forse un token statico, come l'UUID dell'utente, sarebbe meglio di niente?

EDIT # 2 - Come Il Rook ha sottolineato, questa potrebbe essere una domanda di divisione. Ho letto le speculazioni in entrambi i modi e ho sentito sussurri lontani riguardo alle versioni precedenti del flash che sono sfruttabili per questo tipo di imbrogli. Dal momento che non ne so nulla, sto mettendo una taglia per chiunque possa spiegare come questo sia un rischio CSRF. Altrimenti, lo darò a Artefacto. Grazie.

+0

per la cronaca Artefacto era corretta. Dovresti leggere il manuale sulla sicurezza del browser invece di chiedere SO. Molte delle risposte su SO non sono corrette, in particolare per argomenti relativi alla divisione dei capelli come questo. – rook

+0

C'erano effettivamente alcune [vulnerabilità] (http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_Flash) nelle versioni precedenti di Flash. Tuttavia, per gli utenti che utilizzano effettivamente queste vecchie versioni di Flash, direi che gli attacchi CSRF sono i più piccoli dei loro problemi di fronte a vulnerabilità arbitrarie nell'esecuzione di codice. – Artefacto

+0

http://stackoverflow.com/questions/17478731/whats-the-point-of-the-x-requested-with-header | http://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token –

risposta

13

Direi che è abbastanza. Se le richieste interdominio fossero consentite, saresti comunque condannato perché l'utente malintenzionato potrebbe utilizzare Javascript per recuperare il token CSRF e utilizzarlo nella richiesta forgiata.

Un token statico non è una grande idea. Il token dovrebbe essere generato almeno una volta per sessione.

EDIT2 Mike non ha ragione dopo tutto, mi dispiace. Non avevo letto la pagina che ho collegato correttamente. Dice:

una semplice richiesta di cross-site è uno che: [...] non imposta intestazioni personalizzate con la richiesta HTTP (ad esempio X-Modified, ecc)

Pertanto, se si imposta X-Requested-With, la richiesta deve essere pre-flown e, a meno che non si risponda alla richiesta di pre-volo OPTIONS che autorizza la richiesta cross-site, non verrà superata.

EDIT Mike ha ragione, a partire da Firefox 3.5, cross-site XMLHttpRequests sono permitted. Di conseguenza, devi anche verificare se l'intestazione Origin, quando esiste, corrisponde al tuo sito.

if (array_key_exists('HTTP_ORIGIN', $_SERVER)) { 
    if (preg_match('#^https?://myserver.com$#', $_SERVER['HTTP_ORIGIN']) 
     doStuff(); 
} 
elseif (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && 
     (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) 
    doStuff(); 
+0

Al signore che mi ha votato: puoi spiegare cosa c'è di sbagliato nella mia risposta? – Artefacto

+0

È una cattiva risposta perché l'aggiunta di qualcosa all'intestazione non offre assolutamente alcuna protezione perché può essere facilmente falsificata. Vedi la risposta accettata per una buona soluzione al problema. –

+0

@musicfreak Questa intestazione viene aggiunta solo quando la richiesta viene effettuata tramite Javascript. CSRF non può essere realizzato con Javascript a causa di restrizioni cross-site. Di conseguenza, è abbastanza. Certo, potresti "forgiare" l'intestazione, ad es. costruendo un browser che invierebbe sempre questa intestazione. Ma facendolo, ti spareresti ai piedi. La protezione contro CRFS è la protezione per gli utenti ** da soli **, contro richieste che sono state eseguite maliziosamente e programmaticamente da sole. – Artefacto

0

Non penso che questo offra alcun tipo di protezione. Un sito attaccante potrebbe ancora utilizzare xmlhttprequest per la sua richiesta cross-site ignorare il controllo.

+0

Ti piacerebbe sapere una soluzione adeguata? Non devi tenere la mia mano e camminarmi attraverso, ma forse potresti indicarmi la giusta direzione? :) – Greg

+0

@Greg: No, non proprio. Stavo pensando che usare un token di una volta sia la strada da percorrere. Ma non ne ho esperienza. – Alex

0

Risposta breve: no. Qualsiasi utente malintenzionato dovrebbe utilizzare lo stesso Ajax per attaccare il tuo sito web. Dovresti generare un token casuale con una durata breve ma non eccessiva che dovresti aggiornare durante ogni richiesta Ajax.

Dovresti utilizzare una serie di token in javascript in quanto potresti avere più richieste di ajax in esecuzione nello stesso momento.

+2

Avevo l'impressione che le richieste AJAX tra domini non siano consentite? Immagino ci siano soluzioni alternative? – Greg

+0

L'utente malintenzionato può utilizzare Firebug o un'altra console di sviluppo in AJAX nel dominio. –

+2

-1, ti interessa scrivere un exploit per eseguire il backup di quel commento? No? Non pensavo così. xmlhttprequest non può essere cross-site, è una violazione della stessa politica di origine. potrebbe non essere un metodo di sfida forte, ma non puoi scrivere un exploit per questo. Leggi il manuale sulla sicurezza del browser di Google. – rook

0

Quello che stai facendo è sicuro perché xmlhttprequest di solito non è vulnerabile alla falsificazione di richieste tra siti.

come questo è un problema lato client, il modo più sicuro sarebbe quello di controllare l'architettura di sicurezza di ciascun del browser :-)

(Questo è un riassunto, io sono l'aggiunta di questa risposta, perché questa domanda è molto confuso, vediamo cosa dicono i voti)

1

Non credo che questo sia sicuro. Le stesse politiche di origine sono progettate per impedire ai documenti di domini diversi di accedere al contenuto restituito da un dominio diverso. Questo è il motivo per cui i problemi XSRF esistono in primo luogo. In generale, XSRF non si preoccupa della risposta. È usato per eseguire un tipo specifico di richiesta, come un'azione di cancellazione. Nella forma più semplice, questo può essere fatto con un tag img correttamente formattato. La soluzione proposta impedirebbe questa forma più semplice, ma non protegge nessuno dall'uso dell'oggetto XMLHttp per effettuare la richiesta. È necessario utilizzare le tecniche di prevenzione standard per XSRF. Mi piace generare un numero casuale in javascript e aggiungerlo al cookie e una variabile del modulo. Questo assicura che il codice possa anche scrivere cookie per quel dominio. Se desideri maggiori informazioni, vedi this entry.

Inoltre, per anticipare i commenti su XMLHttp che non funzionano nello script. Ho usato il seguente codice con Firefox 3.5 per effettuare una richiesta di google da html in esecuzione nel dominio localhost. Il contenuto non verrà restituito, ma usando firebug, puoi vedere che la richiesta è stata fatta.

<script> 
var xmlhttp = false; 

if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { 
    try { 
     xmlhttp = new XMLHttpRequest(); 
    } catch (e) { 
     xmlhttp = false; 
    } 
} 
if (!xmlhttp && window.createRequest) { 
    try { 
     xmlhttp = window.createRequest(); 
    } catch (e) { 
     xmlhttp = false; 
    } 
} 

xmlhttp.open("GET", "http://www.google.com", true); 
xmlhttp.onreadystatechange = function() { 
    if (xmlhttp.readyState == 4) { 
     alert("Got Response"); 
     alert(xmlhttp.responseText) 
    } 
} 

xmlhttp.send(null) 
alert("test Complete"); 

+0

scusa ho dovuto modificarlo per poter rimuovere il mio upvote. – Artefacto

+0

Lo sto dando ad Artefacto, perché sembra che X-Requested-With non ce la faccia, ma è stato interessante. Grazie. – Greg

Problemi correlati