f in x
Protezione CSRF nei Form e API — Token Anti-CSRF che Funzionano Davvero
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sicurezza Informatica

Protezione CSRF nei Form e API — Token Anti-CSRF che Funzionano Davvero

[2026-06-25] Author: Ing. Calogero Bono
Zenithby Meteora Web Il sistema operativo della tua attività. Social, clienti, prenotazioni e fatture in un'unica piattaforma. Palestre, barber, professionisti. Scopri Zenith Demo gratis · senza carta

Il tuo modulo invia dati al server. Il tuo utente è autenticato. Un malintenzionato, con un semplice link o un'immagine craftata, può far eseguire quella richiesta a sua insaputa. Questo è CSRF (Cross-Site Request Forgery), e se non lo blocchi, stai lasciando aperta una porta al centro del tuo dominio. Noi, di Meteora Web, lo vediamo ogni giorno nei progetti che ci arrivano: form senza protezione, API che accettano richieste senza token, sessioni esposte. Peccato, perché la soluzione è semplice e già pronta. Parliamone.

Perché la protezione CSRF nei form e API è ancora oggi indispensabile?

CSRF funziona perché il browser include automaticamente i cookie di sessione nelle richieste verso il dominio di destinazione. Se un utente è loggato su tuobank.com e clicca un link malizioso su un altro sito, il browser invia la richiesta con i cookie di sessione. Senza un token di verifica, il server non capisce che la richiesta è stata originata da un contesto diverso.

Un esempio classico: cambiare la password con una GET request senza conferma. Oppure trasferire fondi. Nelle applicazioni moderne, i form e le API sono i vettori principali. Ignorare CSRF significa regalare il controllo della tua applicazione a chiunque sappia scrivere un tag <img> finto.

La protezione si basa su un segreto condiviso — il token anti-CSRF — che il server genera e il client deve inviare in ogni richiesta che modifica lo stato. Il server verifica che il token corrisponda. Semplice, efficace, ma solo se applicato correttamente.

Sponsored Protocol

Quanto costa non proteggersi?

Lo diciamo da contabili: un attacco CSRF riuscito può significare modifica di dati, furto di account, inserimento di contenuti malevoli. Il costo di implementazione? Poche righe di codice. Il costo di un incidente? Potenzialmente migliaia di euro e reputazione. Noi ragioniamo sui numeri del cliente: la sicurezza è un investimento con ROI altissimo, non una spesa.

Come funziona la protezione CSRF nei form HTML con token sincroni?

Il metodo più comune, definito Synchronizer Token Pattern, funziona così:

  1. Il server genera un token casuale e lo associa alla sessione dell'utente.
  2. Il token viene inserito nel form come campo nascosto.
  3. All'invio, il server confronta il token ricevuto con quello memorizzato in sessione.
  4. Se corrispondono, la richiesta è valida. Altrimenti, rifiutata.

Vediamo implementazione in PHP puro:

// Generazione e salvataggio
session_start();
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
?>

<form method="post" action="/update">
    <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
    <!-- altri campi -->
    <button type="submit">Salva</button>
</form>

<?php
// Verifica
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    die('Richiesta non valida');
}
?>

In Laravel, il meccanismo è automatico grazie al middleware VerifyCsrfToken. Basta aggiungere @csrf nel form Blade. Per escludere alcune route (es. webhook esterni), si configurano nell'array $except del middleware.

Sponsored Protocol

// App/Http/Middleware/VerifyCsrfToken.php
protected $except = [
    'webhook/*',
];

Attenzione al doppio invio (double submit)

Se il tuo server non mantiene sessioni (es. API stateless), non puoi salvare il token in sessione. La soluzione è il Double Submit Cookie: generi un token, lo scrivi in un cookie non http-only (sì, volutamente accessibile a JS) e lo invii anche come header o campo del form. Il server confronta il valore del cookie con quello ricevuto.

Esempio di implementazione API con Express.js:

const crypto = require('crypto');

// Genera token su login
app.post('/login', (req, res) => {
    const token = crypto.randomBytes(32).toString('hex');
    res.cookie('csrf_token', token, { httpOnly: false, sameSite: 'strict' });
    // Invia anche nella risposta
    res.json({ csrfToken: token });
});

// Middleware di protezione
function csrfProtection(req, res, next) {
    const cookieToken = req.cookies.csrf_token;
    const headerToken = req.headers['x-csrf-token'];
    if (!cookieToken || !headerToken || cookieToken !== headerToken) {
        return res.status(403).json({ error: 'CSRF token mismatch' });
    }
    next();
}

// Route protetta
app.post('/transfer', csrfProtection, (req, res) => {
    // trasferimento
});

Come garantire la protezione CSRF nelle API REST senza stati di sessione?

Le API stateless, spesso usate con token JWT, non hanno una sessione server-side. Qui il Double Submit Cookie è la soluzione più pratica. In alternativa, puoi usare l'header SameSite dei cookie. Impostando SameSite=Strict o Lax, il browser blocca le richieste cross-site. Ma non è sufficiente per tutti i casi: il valore Strict impedisce anche i link normali da altri siti. L'approccio migliore è combinare SameSite con un token.

Sponsored Protocol

Per API pubbliche che usano chiavi API (non cookie), CSRF non è un problema perché non ci sono cookie di sessione. Il vettore CSRF esiste solo quando l'autenticazione è basata su cookie.

Esempio in Laravel per API stateless

Laravel può escludere le route API dal middleware CSRF (di default lo fa). Ma se usi token di sessione anche su API, devi proteggerle. La soluzione è usare Sanctum con SPA: esso utilizza cookie di sessione e fornisce protezione CSRF automatica tramite il token di sessione.

// config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,localhost:8000')),

// Durante il login, Sanctum invia un cookie 'XSRF-TOKEN' (cifrato)
// Il frontend deve includerlo in ogni richiesta come header 'X-XSRF-TOKEN'
// Axios lo fa automaticamente se configurato con withCredentials: true

Se stai sviluppando un'app React/Vue che consuma API Laravel con sessione, devi recuperare il token CSRF dalla route /sanctum/csrf-cookie e poi inviarlo in ogni richiesta.

Sponsored Protocol

Quali errori comuni evitare nella protezione CSRF nei form e API?

Ne abbiamo visti tanti:

  • Token prevedibili: usare md5(time()) o stringhe corte. Usa random_bytes() o openssl_random_pseudo_bytes() con 32 byte.
  • Token riutilizzabili: alcuni framework rigenerano il token a ogni richiesta (es. Laravel lo fa di default). Altri no. Se non rigeneri, un token rubato vale per l'intera sessione. Meglio rigenerare dopo ogni richiesta POST.
  • GET request con effetti collaterali: non fare mai modifiche di stato con GET. Se lo fai, CSRF è impossibile da bloccare con token (gli attaccanti possono innescare GET via tag <img>). Riscrivi le route in POST/PUT/DELETE.
  • Dimenticare le API: tante applicazioni proteggono i form ma lasciano le API scoperte. Se le API usano cookie di sessione, devono avere la stessa protezione.
  • Doppia protezione inutile: se usi già SameSite=Strict e token, è ridondante ma non dannoso. Se però il token è esposto in un cookie httpOnly? Non puoi leggerlo da JS, quindi non puoi inviarlo via header. In tal caso, usa Double Submit Cookie con cookie accessibile a JS.

Come testare la protezione CSRF nel tuo sito?

Strumenti pratici:

  • Burp Suite: intercetta la richiesta, rimuovi il token e vedi se il server lo accetta.
  • CURL: costruisci una richiesta cross-origin con un semplice form HTML e verifica se viene bloccata.
  • Estensione browser: esistono tool come CSRF Tester che generano automaticamente payload.

Creiamo un test rapido: apri la console del browser su un sito target, esegui:

Sponsored Protocol

// Prova a inviare una richiesta POST senza token
fetch('https://tuosito.com/update', {
  method: 'POST',
  credentials: 'include',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ data: 'test' })
}).then(r => console.log(r.status));

Se restituisce 200, la protezione CSRF manca o non è applicata correttamente.

Cosa fare adesso

  1. Controlla ogni form e ogni route POST/PUT/DELETE: verifica che esista un token CSRF valido, non solo presente ma verificato.
  2. Rigenera il token dopo ogni richiesta di scrittura: se usi framework, conferma che sia il comportamento predefinito. In Laravel, sì; in WordPress, il nonce viene rigenerato solo su alcune azioni.
  3. Proteggi le API che usano cookie di sessione: se hai una SPA con Sanctum o simile, assicurati che il frontend invii il token corretto.
  4. Imposta SameSite=Lax o Strict sui cookie di sessione. È un layer aggiuntivo che blocca molte richieste cross-site.
  5. Fai un audit di sicurezza: se non hai tempo, contattaci. Noi partiamo sempre da una domanda: quanto costa e quanto rende? La sicurezza non è un optional.

Per approfondire la sicurezza web a 360°, visita la nostra Pillar Guide sulla Sicurezza Web per Sviluppatori. Troverai anche altri spoke su XSS, SQL Injection, HTTPS e hardening server.

Riferimento ufficiale: OWASP CSRF.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()