Gli header di sicurezza HTTP sono header di risposta che chiedono al browser di applicare protezioni che altrimenti il tuo sito dovrebbe costruirsi da solo: restare su HTTPS, eseguire solo script da fonti di cui ti fidi, non indovinare i tipi di file, non permettere ad altri siti di inserire la pagina in un frame e condividere meno informazioni sulla provenienza di un visitatore. Sei header coprono quasi tutto: Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, X-Frame-Options (o il frame-ancestors della CSP), Referrer-Policy e Permissions-Policy. La maggior parte richiede una sola riga di configurazione del server. La Content-Security-Policy va pianificata, quindi parti in modalità Report-Only.
I sei header in sintesi
HeaderProtegge daUn valore da cui partireStrict-Transport-SecurityConnessioni declassate a HTTP semplicemax-age=31536000Content-Security-PolicyScript iniettati (cross-site scripting)Una policy testata prima in Report-OnlyX-Content-Type-OptionsBrowser che eseguono un file come se fosse di un altro tiponosniffX-Frame-Options o frame-ancestorsClickjacking tramite frameSAMEORIGIN e frame-ancestors ‘self’Referrer-PolicyIndirizzi completi che trapelano verso altri sitistrict-origin-when-cross-originPermissions-PolicyRichieste di funzionalità del browser non utilizzatecamera=(), microphone=(), geolocation=()
Strict-Transport-Security (HSTS)
Anche con un redirect da HTTP a HTTPS, un visitatore che digita il tuo dominio fa la prima richiesta in HTTP semplice, dove può essere letta o modificata lungo il percorso. HSTS dice al browser di usare da quel momento HTTPS per il tuo dominio, per il tempo indicato da max-age, in secondi:
Strict-Transport-Security: max-age=31536000
Parti con un valore basso. I browser rispettano HSTS fino alla scadenza, quindi un errore resta. Prova max-age=300 per qualche giorno, poi alzalo a un anno (31536000).
includeSubDomains applica la regola a tutti i sottodomini. Aggiungilo solo quando funzionano tutti in HTTPS, compresi i vecchi host di staging e di posta.
preload chiede di integrare il dominio direttamente nei browser tramite hstspreload.org, che richiede un max-age di almeno un anno e includeSubDomains. La rimozione richiede molto tempo, quindi consideralo permanente.
I browser ignorano HSTS nelle risposte in HTTP semplice. Invialo in HTTPS e tieni d’occhio il certificato: con HSTS, un certificato scaduto non si può ignorare con un clic.
Content-Security-Policy
Una Content Security Policy elenca da dove la pagina può caricare script, stili, immagini, font e frame, e verso dove possono inviare i moduli. Se un attaccante riesce a inserire uno script nella pagina, tramite un campo commenti o un plugin compromesso, il browser si rifiuta di eseguirlo a meno che la policy non ne consenta l’origine. È il più efficace dei sei e il più facile da sbagliare, perché una policy troppo restrittiva blocca i tuoi stessi analytics, la chat o il modulo di pagamento.
Parti da Report-Only
Invia prima la policy come Content-Security-Policy-Report-Only. Il browser non blocca nulla, ma segnala ogni violazione all’indirizzo indicato in report-uri (o nel più recente report-to) e la registra nella console. Un punto di partenza per un sito che serve i propri file:
Content-Security-Policy-Report-Only: default-src ‘self’; script-src ‘self’; style-src ‘self’; img-src ‘self’ data:; font-src ‘self’; object-src ‘none’; base-uri ‘self’; form-action ‘self’; frame-ancestors ‘self’; report-uri /csp-report
Naviga il sito, raccogli le segnalazioni per una o due settimane e aggiungi le fonti che usi davvero, come il tuo servizio di analytics o il provider di pagamento. Quando le segnalazioni mostrano solo ciò che vuoi bloccare, invia la stessa policy come Content-Security-Policy.
Script inline: nonce, non unsafe-inline
Una policy restrittiva blocca i blocchi <script> inline e gli attributi onclick, perché uno script iniettato ha lo stesso aspetto. Aggiungere ‘unsafe-inline’ fa sparire il problema, e con lui gran parte della protezione. Invece, assegna a ogni risposta un nonce casuale, inseriscilo nella policy come ‘nonce-…’ e metti lo stesso valore sui tuoi tag script; sposta i gestori di eventi inline in file di script. I tag manager che iniettano i propri script richiedono un’attenzione in più, perché anche ogni tag che aggiungono deve essere consentito.
X-Content-Type-Options
Un tempo i browser indovinavano il tipo di un file dal suo contenuto quando il Content-Type del server sembrava sbagliato. Questo permetteva a una “immagine” caricata di essere eseguita come script. X-Content-Type-Options: nosniff disattiva questa ipotesi. Ha un solo valore valido e nessuno svantaggio noto, purché il tuo server invii content type corretti, quindi invialo su ogni risposta.
X-Frame-Options e frame-ancestors
In un attacco di clickjacking, un altro sito mostra la tua pagina in un frame invisibile e induce i visitatori a cliccarne i pulsanti. X-Frame-Options: DENY blocca qualsiasi inserimento in frame, mentre SAMEORIGIN consente solo le tue pagine. La direttiva CSP frame-ancestors fa lo stesso con più controllo, per esempio con un elenco di siti partner, e ha la precedenza nei browser che la supportano. Inviali entrambi: frame-ancestors per i browser attuali, X-Frame-Options per quelli più vecchi. Il vecchio valore ALLOW-FROM non è più supportato, quindi usa frame-ancestors per tutto ciò che va oltre la tua origine.
Referrer-Policy
Quando un visitatore segue un link, il browser comunica al sito successivo da dove arriva tramite l’header Referer. Senza limiti, può trattarsi dell’indirizzo completo, compresa una query di ricerca, un token di reset o un numero d’ordine nell’URL. strict-origin-when-cross-origin invia l’indirizzo completo all’interno del tuo sito, solo il dominio agli altri siti e nulla da HTTPS a HTTP. È ciò che fanno i browser attuali quando l’header manca, ma inviarlo rende la scelta esplicita. Usa no-referrer sulle pagine con dati privati negli URL ed evita unsafe-url, che invia tutto ovunque.
Permissions-Policy
Permissions-Policy, in passato Feature-Policy, disattiva le funzionalità del browser che il tuo sito non usa, per la pagina e per ogni frame incorporato al suo interno. Un elenco vuoto, (), significa che nessuno può usare la funzionalità:
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()
Escludi le funzionalità che usi, oppure consentile per la tua origine con (self), per esempio payment=(self) su un negozio online con un pulsante di pagamento.
Header di cui puoi fare a meno
X-XSS-Protection controllava un filtro che i browser attuali hanno rimosso. Omettilo, oppure invia 0.
Expect-CT e Public-Key-Pins sono obsoleti. Il pinning poteva tagliare fuori i visitatori da un sito, ed è per questo che i browser lo hanno abbandonato.
Server e X-Powered-By non sono header di sicurezza, ma i numeri di versione esatti che contengono aiutano gli attaccanti a scegliere un exploit. Riducili dove il tuo server lo consente.
Dove impostarli
Imposta gli header in un unico punto, il più vicino possibile al bordo: il web server, la CDN o il middleware dell’applicazione. In nginx e Apache:
# nginx (in the server block)
add_header Strict-Transport-Security “max-age=31536000” always;
add_header X-Content-Type-Options “nosniff” always;
add_header X-Frame-Options “SAMEORIGIN” always;
add_header Referrer-Policy “strict-origin-when-cross-origin” always;
add_header Permissions-Policy “camera=(), microphone=(), geolocation=()” always;
# Apache (.htaccess or virtual host, with mod_headers)
Header always set X-Content-Type-Options “nosniff”
Header always set Referrer-Policy “strict-origin-when-cross-origin”
Due dettagli di nginx colgono spesso in fallo. Senza always, gli header vengono aggiunti solo alle risposte riuscite, non alle pagine di errore. E un blocco location con anche un solo add_header proprio scarta tutti quelli del blocco server, quindi un singolo header di cache per le immagini può rimuovere in silenzio i tuoi header di sicurezza in quel punto. Fai attenzione anche allo stesso header impostato due volte, dal server e dall’applicazione o dalla CDN: i browser gestiscono i duplicati in modo diverso da header a header, quindi scegli un solo responsabile per ciascuno.
Come controllare i tuoi header
Da terminale, curl -sI https://example.com stampa gli header della risposta. Controlla anche l’indirizzo finale dopo i redirect, una pagina di errore e un file statico, perché ciascuno può essere servito da una parte diversa del tuo stack. Nel browser, la scheda Rete degli strumenti per sviluppatori mostra gli header di ogni richiesta e la console mostra le violazioni della CSP.
Oppure usa il nostro HTTP header checker gratuito. Elenca tutti gli header che un URL invia dopo aver seguito i redirect, indica quali dei sei header di sicurezza mancano, segnala alcuni valori che li vanificano, come un max-age HSTS troppo breve, una CSP solo in Report-Only o unsafe-url, e mostra come viene messa in cache la pagina e dove se ne va il tempo. Verifica che gli header ci siano; non valuta cosa consente una Content Security Policy, quindi quello controllalo tu.
Evita che spariscano
Gli header di sicurezza raramente si rompono in modo evidente. Spariscono quando un sito passa a un nuovo server, si cambia CDN, si aggiorna un plugin o qualcuno aggiunge un blocco location, e il sito continua a funzionare, quindi nessuno se ne accorge. Un monitor HTTP nel monitoraggio uptime di Uptimecheck può controllare gli header di risposta a ogni richiesta, fino a 10 controlli sulla risposta per monitor, per esempio:
Strict-Transport-Security è presente.
X-Content-Type-Options è uguale a nosniff.
Content-Security-Policy contiene frame-ancestors.
Ogni controllo deve essere soddisfatto perché il monitor risulti online, quindi un header mancante lo porta a down, un secondo controllo lo conferma e ricevi un avviso. Metti i controlli sugli header in un monitor a parte se non vuoi che incidano sull’uptime della pagina. I controlli girano fino a ogni minuto da Stoccolma, Londra e New York; leggi come monitorare un endpoint API per configurare i controlli sulla risposta e la checklist di manutenzione del sito per il resto della routine.
Scopri il giorno stesso quando un header sparisce. Prova Uptimecheck gratis per 14 giorni, senza carta di credito.