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.comDal 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ì:
- “Questa richiesta ha una sessione valida”
- “Quindi viene dall’utente”
- “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
