it-swarm-eu.dev

Un cookie CSRF deve essere HttpOnly?

Di recente ci è stato consegnato un rapporto sulla sicurezza contenente:

Cookie senza set di flag HttpOnly

vulnerabilità, che apparentemente avevamo in una delle nostre applicazioni interne.

La correzione applicata era semplice come l'impostazione di Django CSRF_COOKIE_HTTPONLY parametro di configurazione a True.

Ma questo è ciò che mi ha confuso. Django dice:

La designazione del cookie CSRF come HttpOnly non offre alcuna protezione pratica perché CSRF serve solo a proteggere dagli attacchi tra domini. Se un utente malintenzionato è in grado di leggere il cookie tramite JavaScript, sono già sullo stesso dominio per quanto ne sa il browser, quindi possono fare comunque quello che vogliono. (XSS è un buco molto più grande di CSRF.)

Sebbene l'impostazione offra pochi vantaggi pratici, a volte è richiesta dai revisori della sicurezza.

Questo significa che non esiste una vera vulnerabilità qui e dobbiamo solo rispettare le regole di controllo della sicurezza?

59
alecxe

Come dice Joe , non vi è alcun reale vantaggio in termini di sicurezza. È puro teatro della sicurezza. Vorrei evidenziarlo da la documentazione :

Se lo abiliti e devi inviare il valore del token CSRF con un AJAX, JavaScript deve estrarre il valore da un modulo di token CSRF nascosto inserito nella pagina anziché dal cookie.

Lo scopo del flag HttpOnly è rendere il valore del cookie non disponibile da JavaScript, in modo che non possa essere rubato in caso di vulnerabilità XSS. Ma il token CSRF deve in qualche modo essere disponibile in modo da poter essere doppio inviato - questo è tutto il punto con esso, dopo tutto. Quindi Django risolve questo problema includendo il valore in un campo modulo nascosto. Ciò annulla l'intero vantaggio di HttpOnly, poiché un utente malintenzionato può semplicemente leggere il valore del campo modulo anziché il cookie.

67
Anders

È corretto. Questo è un falso positivo e la persona che ti fornisce questo risultato non capisce purtroppo cosa sta facendo. Qualcuno che ha capito i rischi di attacchi mitm e csrf non te lo fornirebbe mai.

10
joe

Penso che il principale punto di confusione qui sia che il Django parlano specificamente del [~ # ~] csrf [~ # ~] caso d'uso per un biscotto. Per capire perché il flag httpOnly non aggiunge alcun valore nella prevenzione del CSRF, è necessario comprendere sia il CSRF sia il funzionamento dei cookie.

CSRF è quando una terza parte attiva il browser del tuo utente per effettuare una richiesta al tuo server e il suo browser invia automaticamente i cookie del tuo server insieme alla richiesta, come previsto. Quello che non vuoi è che il tuo server interpreti questa richiesta come effettivamente proveniente dal tuo utente, quindi usi una tecnica CSRF mitigation . Il punto centrale della mitigazione del CSRF è essere in grado di rilevare quando la richiesta non proviene dal tuo dominio (cioè dal tuo utente che interagisce con la tua applicazione) .

In breve, come funzionano i cookie: ogni volta che il browser di un utente invia una richiesta al tuo dominio/server, invia automaticamente tutti i cookie associati al tuo dominio, indipendentemente dal flag httpOnly. I cookie pertanto consentono al cliente o al server di allegare informazioni al browser di un utente che verranno automaticamente restituite al server insieme a eventuali richieste successive. I cookie con il flag httpOnly non sono accessibili da javascript. Probabilmente non dovrebbero essere considerati un luogo sicuro dove archiviare informazioni, ma forniscono la funzionalità pubblicizzata.

Torna a CSRF implementato usando un cookie - in questo caso il flag httpOnly è inutile - il punto cruciale di CSRF è che non lo fanno hanno bisogno di leggere i cookie del tuo utente, hanno solo bisogno del browser del tuo utente per inviare i cookie associati al tuo server insieme alla richiesta di rete che hanno costretto a inviare. Il flag httpOnly, in generale, fornisce valore in quanto impedisce l'accesso del client a quei cookie e se il tuo server restituisce dei cookie, dovresti probabilmente renderli httpOnly. Se stai usando un cookie per CSRF, allora non dovresti farlo e dovresti dedicare il tuo tempo a ripensarlo piuttosto che trasformarlo in un cookie httpOnly. Quindi, in generale, sembra che questa sia una buona regola empirica: il tuo server non dovrebbe inviare alcun cookie non -httpOnly a meno che non sia specificamente previsto per l'accesso dal client javascript.

5
colllin

L'unico modo in cui la prevenzione CSRF con doppio invio può funzionare è l'invio del nonce in un cookie. Se lo invii nel corpo della risposta HTTP, in alcuni casi può essere analizzato da uno script che invia una richiesta tra domini (se hai autorizzato CORS per quella pagina) che vanifica l'intero scopo della protezione da CSRF. L'idea è che gli script sul dominio X non possono ottenere il valore dei cookie sul dominio Y, questo è uno dei pilastri principali della sicurezza sul Web.

Con HTTPOnly cookie non sarai in grado di proteggere contro CSRF utilizzando il metodo più comune, ovvero l'invio doppio di un nonce tramite cookie e uno script sulla pagina in grado di leggere i cookie. Ecco come funziona questa tecnica:

1) Genera un valore nonce che memorizzi sul server per la sessione. Potrebbe essere l'ID sessione stesso o qualcosa archiviato nei dati associati alla sessione.

2) Invia questo al client tramite le intestazioni dei cookie senza HTTPOnly, fai in modo che Javascript lo catturi e lo memorizzi (ad es. A breve termine o in sessionStorage)

3) Invia questo con ogni richiesta che desideri proteggere da CSRF. La richiesta includerebbe il sessionId nel cookie, e anche questo nonce nel corpo della richiesta o nella querystring URL (ad es. Per richieste GET). Se sei preoccupato per la chiusura del nonce nei registri o altro, puoi invece utilizzare Web Crypto per firmare i payload di richiesta con HMAC utilizzando questo nonce

4) Il server cercherà i dati della sessione e verificherà se il nonce non corrisponde, genera un errore e genera un altro nonce e invia il cookie. Assicurati di inviare i nonces solo nei cookie!

È un peccato, ma è vero che molti strumenti di "audit di sicurezza" iniziano a contrassegnare i cookie non contrassegnati con httpOnly e raccomandano di aggiungere questo flag. Questa bandiera è purtroppo peggio che inutile: è teatro della sicurezza.

Sto parlando solo della bandiera httpOnly. È peggio che inutile perché ti fa pensare di aver schivato una specie di proiettile, quando in realtà quella stessa classe di attacco può ancora accadere: l'attaccante deve creare uno script per inviare il cookie al proprio server, quindi potrebbero anche avere quello script esegue le richieste effettive nel contesto della sessione autorizzata, allo stesso modo in cui lo farebbero se avessero i cookie. Avrebbero scritto la sceneggiatura in anticipo. Nessun vero aggressore sarebbe seduto lì alle 3 del mattino a fare richieste perché la loro vittima ha finalmente attivato uno script che ha inviato loro il cookie. Molto più probabilmente, quello script è già pre-programmato per fare ciò che deve fare. E se non esistessero solo i cookie http, le persone si interesserebbero di più alla sanificazione del loro output Javascript per prevenire XSS, che è l'unico modo corretto per prevenire questo attacco.

3

La designazione del cookie CSRF come HttpOnly non offre alcuna protezione pratica poiché CSRF serve solo a proteggere dagli attacchi tra domini.

Ciò può essere stipulato in un modo molto più generale e in un modo più semplice rimuovendo l'aspetto tecnico del "cookie CSRF".

La designazione di un cookie come HttpOnly, per definizione, protegge solo dall'accesso tramite document.cookie o metodi JS equivalenti. Non impedisce alcuna interazione HTTP che potrebbe essere stata causata dal codice JS; qualsiasi interazione che l'utente fa tramite elementi HTML, come l'invio di un modulo, può essere avviata da JS. Non vi è alcuna distinzione significativa di come è stato avviato qualcosa; in effetti, puoi rivendicare "l'utente l'ha avviato" indicando l'utente digitandolo l'URL della pagina Web corrente o quello di alcune pagine Web collegate alla pagina Web corrente.

Questo è anche il motivo per cui il concetto di "riproduzione automatica di video" non è ben definito e non può essere prevenuto in modo affidabile: ciò che costituisce un'azione volontaria dell'utente per avviare un video è un concetto di interfaccia utente, non un DOM (Document Object Model) concetto. Il browser non sa che la riproduzione automatica da parte dell'utente ha fatto un gesto per riprodurre un video, a meno che il video non inizi prima che l'utente faccia qualsiasi mossa (come "spazio per scorrere verso il basso"). (In alcuni casi si può provare a "wack a mole" autoplay, come si può provare a "wack a mole" (rilevare, black list) fastidiosi annunci Web o condividere informazioni con domini di terze parti, ma senza garanzia di copertura .)

A meno che JS non sia completamente disattivato su un dominio, qualsiasi azione dell'utente all'interno del frame controllata dal sito Web dovrebbe semplicemente essere considerata fattibile dallo script del sito Web. Uno il Web moderno, che disattiva completamente JS sulla maggior parte dei domini? Quasi nessuno.

Quindi l'osservazione generalizzata è:

La designazione di cookie come HttpOnly non offre alcuna protezione pratica contro eventuali attacchi che eseguono azioni che l'utente potrebbe eseguire attraverso l'interfaccia del sito Web.

Si noti che la lettura di tutti i cookie (compresi quelli contrassegnati con HttpOnly) non viene eseguita dall'interfaccia del sito Web, può essere eseguita solo con lo strumento Inspector del browser o il proxy HTTP per i cookie inviati su HTTP.

3
curiousguy

L'attributo httpOnly può essere omesso dal cookie anti-CSRF in Django perché, come molte altre risposte e anche la domanda evidenziata, il codice javascript in esecuzione nei browser delle vittime che ha caricato un non autorizzato Origin non sarà in grado di leggere le risposte autenticate dall'origine autorizzata, con o senza l'attributo, a causa della stessa politica sull'origine.

(Non mescoliamo il requisito rigoroso per il cookie di sessione con quello per il cookie anti-CSRF).

Django si aspetta che gli sviluppatori compilino il modulo HTML con il token anti-CSRF correlato (o lo stesso) con il cookie XSRF-TOKEN.

https://github.com/Django/django/blob/f283ffaa84ef0a558eb466b8fc3fae7e6fbb547c/Django/middleware/csrf.py#L136

Gli Django sono abbastanza attenti da stabilire la necessità dell'attributo Secure (che si applica sia al cookie di sessione sia a quello anti-CSRF). Potrebbero anche menzionare il è necessario aggiungere l'intestazione della risposta Strict-Transport-Security per evitare l'iniezione di cookie e/o l'intercettazione dell'intera interazione lasciando che i browser scivolino nel collegamento http: // e riscrivendo il traffico non crittografato.

Gli autori del framework non sono rigidi riguardo all'attributo httpOnly perché, grazie alla stessa politica sulle origini, le origini non autorizzate non sarebbero in grado di leggere i cookie tramite il codice javascript che generano per i browser; i loro script lato server che provano a ottenere i dettagli del modulo e le intestazioni delle risposte dall'origine autorizzata riceveranno solo risposte non autenticate.

Mi sono appena imbattuto in un severo requisito di NON consentire httpOnly per un cookie XSRF-TOKEN Quando viene utilizzato come unica fonte per le applicazioni a pagina singola. Le SPA che fanno affidamento sul cookie di risposta XSRF-TOKEN Sono ancora sicure. Le origini non autorizzate, ancora una volta, non saranno in grado di leggere il cookie di risposta XSRF-TOKEN Corretto a causa della stessa politica di origine. E gli script lato server non autorizzati non sarebbero nemmeno in grado di precaricare il cookie di risposta XSRF-TOKEN Corretto (di nuovo, perché gli script non dispongono dell'autenticazione con il server autorizzato).

https://github.com/expressjs/csurf#single-page-application-spa

2
eel ghEEz

Sebbene il token CSRF non sia un segreto in una pagina con un modulo protetto CSRF (e potrebbe essere rubato usando XSS), in alcune pagine potresti avere una vulnerabilità XSS senza un modulo. Lì puoi ottenere il token solo dal cookie ma non da un campo nascosto. In questo caso la sicurezza viene migliorata utilizzando un cookie HttpOnly.

C'è ancora un modo per ottenere il token richiedendo una pagina che contiene un modulo tramite javascript. Ci possono essere modi per impedirlo, ma sulla maggior parte dei siti questo attacco sarà possibile.

1
allo