Guides 6 min di lettura

Header di sicurezza HTTP: cosa inviare e come controllarli

HSTS, Content-Security-Policy, X-Content-Type-Options, protezione dai frame, Referrer-Policy e Permissions-Policy: cosa fa ciascuno e un valore sicuro da cui partire.

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.

Domande

Quali header di sicurezza HTTP dovrebbe inviare ogni sito web?

Strict-Transport-Security, X-Content-Type-Options: nosniff, X-Frame-Options o una direttiva CSP frame-ancestors, Referrer-Policy e Permissions-Policy sono semplici da aggiungere. La Content-Security-Policy offre la protezione maggiore, ma va prima testata in modalità Report-Only.

Cos'è Content-Security-Policy-Report-Only?

La stessa policy di Content-Security-Policy, ma il browser si limita a segnalare ciò che avrebbe bloccato invece di bloccarlo. Usala per individuare le fonti di cui il tuo sito ha davvero bisogno prima di applicare la policy.

Serve ancora X-Frame-Options se uso frame-ancestors?

I browser attuali seguono frame-ancestors e ignorano X-Frame-Options quando sono presenti entrambi. Inviarli entrambi non costa nulla e protegge i visitatori con browser più vecchi.

X-XSS-Protection serve ancora?

No. Il filtro che controllava è stato rimosso dai browser attuali. Ometti l'header o invia 0, e affidati invece a una Content Security Policy.

Continua a leggere

Guides 6 min di lettura

Error budget: che cos’è e come usarlo

Come calcolare un error budget a partire da uno SLO, che cosa lo consuma, come funziona il burn rate e come scrivere una error budget policy che il tuo team rispetterà davvero.

Leggi

I disservizi sono acqua passata.

Configura il tuo primo monitor in meno di un minuto, oppure esplora prima la demo live.

Prova gratuita di 14 giorni · Poi gratis con 5 monitor · Nessuna carta di credito