CSRF Explained: quando il browser attacca per noi

C’è un momento, nello sviluppo di un’applicazione web, in cui tutto sembra funzionare nel modo giusto:

  • L’utente ha fatto login.
  • La sessione è valida.
  • Il cookie è stato impostato correttamente.
  • Il backend risponde solo a chi è autenticato.

In quel momento nasce una convinzione silenziosa, quasi naturale:

“Se arriva una richiesta autenticata, allora è l’utente che l’ha voluta”.

Ed è proprio da questa convinzione — non da un bug, non da una falla evidente — che nasce la CSRF.

Non è un attacco rumoroso, né assomiglia ad un’iniezione. Non sfrutta input strani, né caratteri speciali. Sfrutta la solita fiducia che viene spesso e volentieri data per scontata.

1. Il browser: un alleato fin troppo diligente

Immagina il browser come un assistente estremamente zelante.

Gli abbiamo insegnato a:

  • ricordare le sessioni
  • conservare i cookie
  • reinviarli automaticamente
  • “farci risparmiare fatica”

Se ogni volta dovessimo reinserire username e password, il web sarebbe inutilizzabile.

Così il browser, quando vede una richiesta verso un sito per cui ha già una sessione valida, fa la cosa che gli abbiamo chiesto per anni:

“Ah, conosco questo sito. Ecco le credenziali”.

Non si chiede:

  • da dove arriva la richiesta
  • perché è partita
  • chi l’ha iniziata

Non perché sia stupido, ma perché non è stato progettato per porsi queste domande.

Il browser non decide, esegue.

2. Dove nasce davvero il problema

Dal punto di vista del server, la situazione è apparentemente perfetta:

  • Arriva una richiesta.
  • C’è un cookie di sessione.
  • La sessione è valida.

Per il backend, questa sequenza significa una cosa sola:

“Questa richiesta arriva dall’utente autenticato”.

Ma qui c’è il primo fraintendimento perché il server, in realtà, non osserva:

  • la pagina che l’utente stava visitando
  • il contesto in cui la richiesta è stata generata
  • l’intenzione reale dell’utente

Vede solo una richiesta HTTP ben formata.

La CSRF nasce quando autenticazione e intenzione vengono confuse.

3. Una richiesta che sembra innocua

Prendiamo un esempio volutamente semplice.

Un’applicazione permette di cambiare email con una richiesta del tipo:

POST /change-email
email=nuova@email.com

Dal punto di vista del backend:

  • è una POST → bene
  • arriva con cookie valido → bene
  • modifica i dati dell’utente → legittimo

Ora fermiamoci un attimo.

Questa richiesta non contiene nulla che dica:

“Sono stato io, utente, a cliccare su ‘Cambia email’”.

Contiene solo:

  • una sessione
  • un’azione

Il server non sa come è nata quella richiesta, sa solo che è arrivata.

4. Quando entra in scena un sito esterno

Immagina ora questo scenario:

  • l’utente è loggato sull’app
  • apre un’altra pagina, magari un blog, un forum, un link ricevuto via mail
  • quella pagina contiene una richiesta invisibile verso il sito originale

Il browser fa ciò che sa fare:

  • prepara la richiesta
  • allega automaticamente il cookie di sessione
  • la invia

Il server la riceve, la sessione è valida e quindi l’azione viene eseguita. Il tutto senza creare nessun allarme, o errore od apparente violazione.

Eppure, l’utente non ha mai deciso di cambiare email.

La CSRF non forza il server, ma lo convince, usando le sue stesse regole.

5. Perché questo tipo di attacco è così subdolo

La CSRF è difficile da “sentire” perché:

  • non ruba dati
  • non rompe nulla
  • spesso non produce output visibile

Modifica lo stato e lo fa in silenzio.

Cambiare:

  • un’email
  • una password
  • un’impostazione
  • un ruolo

Sono azioni piccole, ma persistenti, ed è proprio per questo che funzionano!

6. Cosa succede davvero nella testa del server

Il server ragiona così:

  1. “Questa richiesta ha una sessione valida”
  2. “Quindi viene dall’utente”
  3. “Quindi è legittima”

Manca completamente un passaggio:

“Questa azione è stata voluta dall’utente in questo momento?”

HTTP non fornisce questo concetto, va costruito: proprio qui che entrano in gioco le difese.

7. Il CSRF token: introdurre una prova di intenzione

Il CSRF token non serve a identificare l’utente perché lo fa già la sessione.

Serve a dimostrare un’altra cosa:

“Questa richiesta nasce da una pagina che ho generato io”

Quando il server crea una pagina:

  • genera anche un valore casuale
  • lo inserisce nel form o nello script
  • lo associa alla sessione

Quando la richiesta torna indietro:

  • il token deve esserci
  • deve essere corretto
  • deve corrispondere alla sessione

Un sito esterno non può:

  • leggere quel token
  • copiarlo
  • inventarlo

Non perché sia “bloccato”, ma perché non lo vede mai.

Narrativamente, è come chiedere:

“Dimmi qualcosa che solo io e te sappiamo, proprio ora.”

8. Perché il browser non può “aiutare” l’attaccante

Il browser può:

  • inviare cookie
  • inviare richieste
  • ripetere azioni

Ma non può:

  • generare token validi
  • leggere contenuti cross-site
  • ricostruire lo stato interno di un’altra app

Il token spezza la catena, ma non blocca il browser, da uno stop al fraintendimento.

9. SameSite cookie: una cintura di sicurezza, non un airbag

L’attributo SameSite dice al browser:

“Non inviare questo cookie in contesti esterni”

È una difesa utile perché così riduce molti casi semplici.

Ma da sola non possiamo considerarla sufficiente:

  • alcuni flussi richiedono SameSite=None
  • non copre tutti i casi
  • non sostituisce la verifica di intenzione

È una protezione in più non un fondamento.

10. Le false sicurezze più comuni

Molte applicazioni pensano di essere protette perché:

  • usano solo POST
  • controllano il Referer
  • richiedono un click visibile

Ma nessuna di queste garantisce l’intenzione.

La CSRF non gioca sulla forma della richiesta, ma come hai già letto precedentemente, gioca sulla fiducia.

11. Cosa dovrebbe ricordare chi inizia

  • Una richiesta autenticata non è automaticamente voluta
  • Il browser invia credenziali senza chiedere
  • Il server non vede l’origine reale dell’azione
  • I CSRF token servono a distinguere chi ha iniziato l’azione
  • SameSite aiuta, ma non basta

La sicurezza nasce quando smettiamo di dare per scontato ciò che sembra ovvio.

12. Epilogo: il browser non tradisce, obbedisce

La CSRF non è un tradimento del browser: è il risultato di anni di obbedienza perfetta.

Abbiamo chiesto al browser di ricordare tutto e lui lo fa per noi.
Abbiamo chiesto al server di fidarsi delle sessioni e così procede.

Il problema nasce quando nessuno chiede:

“Questa azione è stata davvero voluta?”

Inserire un CSRF token significa fare proprio questo, ovvero introdurre una domanda che prima non esisteva.

E quando quella domanda viene posta, il browser smette di attaccare per noi tornando a fare ciò che sa fare meglio: eseguire evitando fraintendimenti.

Questo nodo della rete è alimentato da conoscenza libera e caffeina.
Se hai trovato qualcosa di utile, puoi supportarci con un caffè digitale.
👉 Offrimi un caffè

Powered by Buttondown

Lascia un commento