Scopriamo cosa sono e a cosa servono le intestazioni HTTP di sicurezza (Security HTTP Headers). Questo articolo elenca gli HTTP Security Header più importanti che puoi utilizzare per proteggere il tuo sito web.
Dato che avevamo trattato a livello generale le intestazioni HTTP in una guida dedicata, non entrerò nei dettagli di cosa siano e come funzionano. Se avete letto quel contenuto avrete capito che sono elementi importanti, pieni di sorprese e di possibilità per migliorare le prestazioni di un sito web.
Oggi vediamo alcune intestazioni HTTP relative alla sicurezza, che aiutano a proteggere gli utenti da attacchi web particolarmente diffusi. Come vedremo alcune saranno di facile implementazione per un web master o un sistemista, altre invece sono più complesse e andrebbero considerate durante la fase di sviluppo del sito web.
Minacce note sul Web
Prima di approfondire le intestazioni di sicurezza, vediamo alcune minacce note sul web e perché dovresti utilizzare gli HTTP Security Headers se hai un sito web che genera denaro e tratta dati sensibili, oppure semplicemente se vuoi renderlo più sicuro.
Proteggi il tuo sito dalle vulnerabilità da injection
Le vulnerabilità da injection si verificano quando dati non attendibili elaborati dall’applicazione possono influire sul suo comportamento e, in genere, portare all’esecuzione di script controllati da un utente malintenzionato.
La vulnerabilità più comune causata da bug di injection è il Cross-Site Scripting (XSS) nelle sue varie forme, inclusi reflected XSS, stored XSS, DOM-based XSS e altre varianti.
Una vulnerabilità XSS può in genere fornire a un utente malintenzionato l’accesso completo ai dati utente elaborati dall’applicazione e a qualsiasi altra informazione ospitata nella stessa origine web, tra le quali potrebbero esserci dati sensibili.
Le difese tradizionali contro le minacce da injections includono:
- l’uso coerente di sistemi di modelli HTML con escape automatico (autoescaping HTML), evitando l’uso di API JavaScript pericolose;
- la post elaborazione dei dati degli utenti ospitando i caricamenti di file in un dominio separato e ripulendo l’HTML controllato o modificato dall’utente.
Autoescaping HTML significa che un input, {$x} viene sottoposto a escape ovvero, sostituire questi caratteri con sequenze di caratteri normali, tradizionalmente chiamate sequenze di escape, in modo diverso a seconda di dove deve essere inserito nell’output del modello, ad esempio, in HTML, JavaScript, CSS, … Questo è ciò che si intende per contextual autoescaping (cioè dipendente dal contesto).
Le intestazioni HTTP di sicurezza per proteggersi da injection sono:
- Content Security Policy (CSP) per controllare quali script possono essere eseguiti dall’applicazione per ridurre il rischio di injection.
- Trusted Types per imporre la pulizia dei dati passati alle API JavaScript pericolose.
- X-Content-Type-Options per impedire al browser di interpretare erroneamente i tipi MIME delle risorse del tuo sito web, il che può portare all’esecuzione di script.
Isola il tuo sito dagli altri siti web
L’apertura intrinseca del web consente ai siti di interagire tra loro in modi che possono violare le aspettative di sicurezza di un’applicazione. Ciò include l’esecuzione imprevista di richieste autenticate o l’incorporamento di dati da un’altra applicazione nel documento dell’attaccante, consentendo all’attaccante di modificare o leggere i dati dell’applicazione.
Le vulnerabilità comuni che minano l’isolamento del web includono:
- Il clickjacking, un attacco che induce un utente a fare clic su un elemento di una pagina web invisibile o mascherato da un altro elemento. Ciò può indurre gli utenti a scaricare inconsapevolmente malware, visitare pagine web dannose, fornire credenziali o informazioni riservate, trasferire denaro o acquistare prodotti online. In genere, il clickjacking viene eseguito visualizzando una pagina invisibile o un elemento HTML, all’interno di un iframe, nella parte superiore della pagina visualizzata dall’utente. L’utente crede di fare clic sulla pagina visibile ma in realtà sta facendo clic su un elemento invisibile nella pagina aggiuntiva trasposta sopra di essa.
- la falsificazione di richieste tra siti (CSRF – Cross-Site Request Forgery), un attacco che costringe un utente finale a eseguire azioni indesiderate su un’applicazione web in cui è attualmente autenticato. Con un piccolo aiuto di ingegneria sociale (come l’invio di un collegamento tramite e-mail o chat), un utente malintenzionato può indurre gli utenti di un’applicazione web a eseguire azioni a scelta dell’attaccante. Se la vittima è un utente normale, un attacco CSRF riuscito può costringere l’utente a eseguire richieste di modifica dello stato come il trasferimento di fondi, la modifica del proprio indirizzo e-mail e così via. Se la vittima è un account amministrativo, un attacco CSRF può compromettere l’intera applicazione web.
- l’inclusione di script tra siti (XSSI – Cross-Site Script Inclusion), vulnerabilità che sfrutta il fatto che, quando una risorsa viene inclusa utilizzando il tag script, la SOP non si applica, perché gli script devono poter essere inclusi tra domini. Un utente malintenzionato può quindi leggere tutto ciò che è stato incluso utilizzando il tag script. Ciò è particolarmente interessante quando si tratta di JavaScript dinamico o JSONP quando le cosiddette informazioni come i cookie vengono utilizzate per l’autenticazione. I cookie sono inclusi quando si richiede una risorsa da un host diverso.
- vari Cross-Site Leaks, ovvero tecniche che attraverso i browser possono essere utilizzate per dedurre e raccogliere informazioni sugli utenti.
Per fortuna ci sono possibilità per evitare questo tipo di comportamenti. Le intestazioni HTTP di sicurezza per proteggersi dall’esecuzione imprevista di richieste autenticate o l’incorporamento di dati da un’altra applicazione nel documento dell’attaccante sono:
- X-Frame-Options per impedire che i tuoi documenti vengano incorporati da un sito web dannoso.
- CORP (Cross-Origin Resource Policy) per evitare che le risorse del tuo sito web vengano incluse da un sito web multi-origine.
- COOP (Cross-Origin Opener Policy) per proteggere le finestre del tuo sito web dalle interazioni di siti web dannosi.
- CORS (Cross-Origin Resource Sharing) per controllare l’accesso alle risorse del tuo sito web da documenti multi-origine.
Costruisci un sito web potente in modo sicuro
Meltdown e Spectre sfruttano le vulnerabilità critiche nei processori moderni. Queste vulnerabilità hardware consentono ai programmi di rubare i dati che vengono attualmente elaborati sul computer. Sebbene i programmi in genere non siano autorizzati a leggere dati da altri programmi, un programma dannoso può sfruttare Meltdown e Spectre per ottenere dati protetti archiviati nella memoria di altri programmi in esecuzione. Ciò potrebbe includere le tue password memorizzate in un gestore di password o in un browser, le tue foto personali, e-mail, messaggi istantanei e persino documenti business-critical.
I browser limitano le funzionalità che potrebbero sfruttare la vulnerabilità dietro un ambiente speciale chiamato isolamento tra le origini (Cross-Origin Isolation). Con il Cross-Origin Isolation puoi utilizzare potenti funzionalità come SharedArrayBuffer.
Le intestazioni HTTP di sicurezza che possono proteggere da attacchi Spectre sono:
- COEP (Cross-Origin Embedder Policy) insieme a COOP per abilitare il Cross-Origin Isolation.
Crittografa il traffico verso il tuo sito
I problemi di crittografia si verificano quando un’applicazione non crittografa completamente i dati in transito, consentendo a malintenzionati che vogliono intercettare dati di conoscere le interazioni dell’utente con l’applicazione.
Una crittografia insufficiente può verificarsi nei seguenti casi: mancato utilizzo del protocollo HTTPS, la presenza di contenuto misto nella pagina (file richiamati in HTTP), impostazione di cookie senza Secure Attribute (oppure __Secure prefix), oppure senza Lax CORS Validation Logic.
Le intestazioni HTTP di sicurezza che possono proteggere dall’intercettazione dei nostri dati sono:
- HTTP Strict Transport Security (HSTS) per servire in modo coerente i tuoi contenuti tramite protocollo HTTPS.
Come testare le intestazioni HTTP di sicurezza di un sito web
Prima di procedere con le spiegazioni dei singoli HTTP Security Header che possiamo implementare ti consiglio di verificare con un tester affidabile quali intestazioni HTTP di sicurezza sta inviando il tuo web server. Se il tuo web server è stato ben configurato, potresti avere già attive diverse intestazioni di sicurezza.
Io mi trovo bene con il tester Mozilla Observatory, ha un report abbastanza rapido, chiaro e con link di approfondimento. Un altro tool interessante è https://securityheaders.com/.
Dato che l’implementazione nei web server delle intestazioni HTTP che vedremo varia da sistema a sistema, per abilitarle ti consiglio di fare riferimento alla documentazione del tuo web server. Inoltre, dato che la questione è molto più tecnica di quello che posso approfondire io, ti consiglio di mettere nei preferiti del tuo browser il sito web di riferimento per lo sviluppo web: web.dev, portale nel quale puoi trovare dettagli tecnici che non ho trattato in questa guida.
Fatte queste dovute premesse, vediamo le caratteristiche e funzionalità delle intestazioni HTTP di sicurezza più importanti oggi disponibili e compatibili con i browser.
Content Security Policy (CSP)
Il Cross-Site Scripting (XSS) è un attacco in cui una vulnerabilità su un sito web consente l’iniezione e l’esecuzione di uno script dannoso.
L’intestazione Content-Security-Policy fornisce un livello aggiuntivo per mitigare gli attacchi XSS limitando gli script che possono essere eseguiti dalla pagina. CSP può essere configurato in molti modi e livelli, da leggero ad estremamente vincolante. Ad esempio, puoi impostare direttive e definire “allowlist” di domini specifici per poter richiamare le dipendenze da terze parti (immagini, script, font, css, frame, …). Tuttavia, raggiungere la massima sicurezza non è semplicissimo perché alcune impostazioni potrebbero comportare modifiche alle logiche di sviluppo del sito web, e non è detto che ciò si possa sempre fare.
Ad esempio, style che i tag di stile dovrebbero essere consolidati in fogli di stile esterni per proteggersi da una varietà di metodi di estrazione dei dati sorprendentemente intelligenti abilitati dai CSS. Quindi in pratica per sfruttare a fondo l’header CSP dovresti avere un sito web senza alcuno script o style inline nell’HTML.
Si consiglia di abilitare strict CSP utilizzando uno dei seguenti approcci:
- Se esegui il rendering delle tue pagine HTML sul server, utilizza un nonce-based strict CSP.
- Se il tuo codice HTML deve essere servito in modo statico o memorizzato nella cache, ad esempio, se si tratta di un’applicazione a pagina singola, utilizza un hash-based strict CSP.
Come usare CSP – Usi consigliati
Un CSP può essere una protezione aggiuntiva contro gli attacchi XSS; dovresti comunque assicurarti di bypassare (e ripulire) l’input dell’utente. Questa intestazione di sicurezza è consigliata per i siti web che gestiscono dati utente sensibili. Se hai un semplice blog o sito informativo, la sua utilità si riduce molto.
Inoltre, come accennato non è semplicissimo abilitare tutte le funzioni di sicurezza CSP dato che potrebbero servire numerose customizzazioni al codice del CMS o del sito web. Ad esempio, per abilitare nonce-based strict CSP dovrai editare i richiami a tutte le dipendenze usate dal sito web, e non è sempre cosa banale. Se invece vuoi scegliere di abilitare hash-based strict CSP dovrai inserire nel tuo template HTML tutti gli script inline, perché non è consentito ai browser usare gli hash su dipendenze esterne. Due metodi contrapposti che richiedono interventi importanti ai template HTML e le inclusioni delle dipendenze.
Sebbene i criteri CSP siano consentiti nella pagina HTML anche attraverso Meta tag, è impossibile usare la funzione report-uri in questo modo.
<meta http-equiv="Content-Security-Policy" content="default-src https://cdn.example.net; child-src 'none'; object-src 'none'">
Ciò significa che quando un utente riscontra un errore, non ci sarà alcun sistema di log/registrazione e fallirà silenziosamente. Per questo motivo è generalmente consigliato utilizzare un’intestazione HTTP Content-Security-Policy dal tuo server web al posto del meta tag.
Utilizzare nonce-based strict CSP
In sistemi SSR, ovvero se esegui il rendering delle tue pagine HTML sul server, utilizza la modalità nonce-based strict CSP.
Un nonce è un numero casuale utilizzabile una sola volta. Un CSP basato su nonce è sicuro solo se puoi generare un nonce diverso per ogni risposta. Se non puoi farlo, usa invece un CSP basato su hash.
Esempio di intestazione:
Content-Security-Policy:
script-src 'nonce-{RANDOM1}' 'strict-dynamic' https: 'unsafe-inline' 'unsafe-eval' https://www.evemilano.com;
object-src 'none';
base-uri 'none';
Questo dovrebbe essere il punto di partenza.
- Strict-dynamic si applica solo alla voce script-src (che definisce le regole per i soli script). Ciò significa che dovrai comunque inserire nella allowlist altre voci, ovvero i domini in white-list dai quali il browser potrà caricare script esterni.
- unsafe-inline consente al browser di eseguire JavaScript e CSS in linea.
- none non corrisponde a nulla.
- self corrisponde all’origine corrente, ma non ai suoi sottodomini.
- unsafe-eval consente meccanismi text-to-JavaScript come eval.
Tutte le dipendenze richiamate da domini non elencati useranno le regole di default-src e vedrai un errore nella console del browser se vengono servite da un dominio diverso.
Dicevamo che l’implementazione non è semplice. Infatti, inserire l’intestazione HTTP non basta per implementare correttamente CSP.
Per prima cosa è necessario aggiungere il segnaposto nonce al tuo modello HTML. Dobbiamo impostare un nuovo window.nonce su ogni pageload in modo che possa essere applicato a tutti gli script. Per farlo creiamo un segnaposto, in questo caso ho scelto {RANDOM1}.
In HTML, per caricare gli script oppure per inserirli inline, imposta l’attributo nonce di tutti i tag relativi a script sulla stessa stringa {RANDOM1}.
# esempio per dipendenza esterna
<script nonce="{RANDOM1}" src="https://example.com/script1.js"></script>
# esempio per script inline
<script nonce="{RANDOM1}">
// Inline scripts can be used with the `nonce` attribute.
</script>
Ora manca l’ultimo step per l’implementazione: istruire il web server a generare il valore randomico.
Passiamo a Nginx dove creiamo una variabile e la applichiamo all’intestazione. Uso una variabile perché mi ha permesso di organizzare le intestazioni CSP per sezione così da poter separare facilmente il CSP di sviluppo e il CSP di produzione.
Quindi dobbiamo effettivamente trasformare {RANDOM1} in una stringa crittograficamente casuale. Fortunatamente con Nginx possiamo usare la variabile “$request_id”.
server{
set csp "script-src 'nonce-$request_id' 'strict-dynamic' 'unsafe-inline' https:; object-src 'none'; base-uri 'self'; default-src 'self'; report-uri https://example.com/csp"
..
..
location / {
..
add_header Content-Security-Policy "${csp}"
sub_filter_once off;
sub_filter {RANDOM1} $request_id;
try_files /path/to/index.html =404;
}
Usa uno strict CSP basato su hash (hash-based strict CSP)
Se il tuo HTML deve essere servito in modo statico o memorizzato nella cache, ad esempio, se stai creando un’applicazione a pagina singola, utilizza uno strict CSP basato su hash.
Esempio di configurazione del server:
Content-Security-Policy:
script-src 'sha256-{HASH1}' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
Il segnaposto {HASH1} deve essere sostituito con un hash SHA-256 con codifica base64 di uno script inline che può essere utilizzato per caricare altri script. Puoi calcolare gli hash SHA di blocchi statici in linea con questo strumento. Un’alternativa è esaminare gli avvisi di violazione CSP nella console per sviluppatori di Chrome, che contiene hash di script bloccati, e aggiungere questi hash al criterio come “sha256-…”. Uno script iniettato da un utente malintenzionato verrà bloccato dal browser poiché solo lo script inline con hash e tutti gli script aggiunti dinamicamente da esso potranno essere eseguiti dal browser.
Nel template HTML, dovrai incorporare i tuoi script inline per applicare una policy basata su hash, perché la maggior parte dei browser non supporta l’hashing di script esterni.
<script>
...// your script1, inlined
</script>
<script>
...// your script2, inlined
</script>
Tutti gli script di origine esterna devono essere caricati dinamicamente tramite uno script inline, poiché gli hash CSP sono supportati tra i browser solo per gli script inline (gli hash per gli script di origine non sono ben supportati tra i browser).
CSP Evaluator è un buon strumento fornito da Google per valutare il tuo CSP, ma allo stesso tempo un buon esempio di nonce-based strict CSP.
Note: https: è un fallback per Safari e unsafe-inline è un fallback per versioni di browser molto vecchie. https: e unsafe-inline non rendono la tua policy meno sicura perché verranno ignorate dai browser che supportano la strict-dynamic. * Safari non supporta ancora la strict-dynamic. Ma uno strict CSP come negli esempi precedenti è più sicuro di un allowlist CSP (e molto più sicuro di nessun CSP) per tutti i tuoi utenti. Anche in Safari, uno strict CSP protegge il tuo sito da alcuni tipi di attacchi XSS, perché la presenza del CSP non consente determinati pattern non sicuri.
Altre informazioni su CSP
- La direttiva frame-ancestors protegge il tuo sito dal clickjacking, un rischio che sorge se consenti a siti non attendibili di incorporare il tuo. Se preferisci una soluzione più semplice, puoi utilizzare X-Frame-Options per bloccare il caricamento, ma i frame-ancestors ti offrono una configurazione avanzata per consentire solo origini specifiche come embedder.
- Potresti già aver utilizzato un CSP per assicurarti che tutte le risorse del tuo sito siano caricate su HTTPS. Tuttavia, questo è diventato meno rilevante: al giorno d’oggi, la maggior parte dei browser blocca i contenuti misti.
- Puoi anche impostare un CSP in modalità solo rapporto.
- Se non puoi impostare un CSP come header lato server, puoi anche impostarlo come meta tag. Tieni presente che non puoi utilizzare la modalità report-uri per i meta tag (sebbene questo possa cambiare in futuro).
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
Trusted Types
Trusted Types è un nuovo meccanismo di sicurezza del browser sviluppato dagli ingegneri della sicurezza di Google.
Il cross-site scripting (DOM XSS) basato su DOM è una delle vulnerabilità della sicurezza web più comuni ed è molto facile introdurlo nella tua applicazione. I trusted-types offrono gli strumenti per scrivere, esaminare la sicurezza e mantenere le applicazioni libere da vulnerabilità DOM XSS rendendo sicure le funzioni potenzialmente pericolose dell’API Web per impostazione predefinita.
Quando vengono utilizzate, queste funzioni accettano solo valori tipizzati non falsificabili creati da criteri di tipo attendibile e rifiutano le stringhe.
La direttiva trusted-types consente agli autori di definire regole che proteggono i valori di scrittura nel DOM e riducendo così la superficie di attacco DOM XSS a piccole parti isolate della base di codice dell’applicazione web, facilitandone il monitoraggio e revisione del codice.
Possiamo definire criteri in cui è possibile garantire che le regole di sicurezza (come l’escape o la sanificazione/pulizia) vengano applicate in modo coerente prima che i dati vengano scritti nel DOM. Queste policy sono quindi gli unici posti nel codice che potrebbero potenzialmente introdurre DOM XSS.
Esempi di utilizzo:
Content-Security-Policy: require-trusted-types-for 'script'
// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
// Name and create a policy
const policy = trustedTypes.createPolicy('escapePolicy', {
createHTML: str => {
return str.replace(/\</g, '<').replace(/>/g, '>');
}
});
}
Questo codice crea un criterio chiamato escapePolicy che può produrre oggetti TrustedHTML tramite la sua funzione createHTML(). Le regole definite eseguiranno l’escape del carattere HTML < per impedire la creazione di nuovi elementi HTML.
Vediamo un esempio di codice errato e uno corretto:
// Assignment of raw strings is blocked by Trusted Types.
el.innerHTML = '<img src=xyz.jpg>'; // This throws an exception.
// Assignment of Trusted Types is accepted safely.
el.textContent = '';
const img = document.createElement('img');
img.src = 'xyz.jpg';
el.appendChild(img);
Come utilizzare i Trusted Types – Usi consigliati
Questa intestazione di sicurezza è consigliata per i siti web che gestiscono dati utente sensibili. L’implementazione è complessa dato che impatta anche su logiche di sviluppo.
Applica i tipi attendibili per i sink DOM pericolosi
Esempio di intestazione CSP e Trusted Types:
Content-Security-Policy: require-trusted-types-for 'script'
Attualmente ‘script’ è l’unico valore accettabile per la direttiva require-trusted-types-for. Naturalmente, puoi combinare i tipi attendibili con altre direttive CSP.
Vediamo come fare un’unione di un nonce-based CSP con i Trusted Types:
Content-Security-Policy:
script-src 'nonce-{RANDOM1}' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
require-trusted-types-for 'script';
È possibile limitare i nomi di criteri Trusted Types consentiti impostando un’ulteriore direttiva trusted Types (ad esempio, trusted-types myPolicy). Tuttavia, questo non è un requisito.
Definisci una policy
Policy:
// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
// Name and create a policy
const policy = trustedTypes.createPolicy('escapePolicy', {
createHTML: str => {
return str.replace(/\</g, '<').replace(/>/g, '>');
}
});
}
È possibile definire criteri con nomi arbitrari a meno che non si limitino i nomi dei criteri di Trusted Types consentiti impostando la direttiva trusted-types.
Applicare la policy
Utilizzare la policy durante la scrittura dei dati nel DOM:
// Assignment of raw strings are blocked by Trusted Types.
el.innerHTML = 'some string'; // This throws an exception.
// Assignment of Trusted Types is accepted safely.
const escaped = policy.createHTML('<img src=x onerror=alert(1)>');
el.innerHTML = escaped; // '<img src=x onerror=alert(1)>'
Con require-trusted-types-for ‘script’, l’utilizzo di un Trusted Type è un requisito. L’utilizzo di qualsiasi API DOM pericolosa con una stringa risulterà in un errore.
X-Content-Type-Options
Questa intestazione è molto semplice da implementare ed è suggerita per tutti i siti web. Quando un documento HTML dannoso viene servito dal tuo dominio (ad esempio, se un’immagine caricata su un servizio fotografico contiene markup HTML valido), alcuni browser lo tratteranno come un documento attivo e gli consentiranno di eseguire script nel contesto dell’applicazione, portando a un bug di scripting tra siti (cross-site scripting bug).
X-Content-Type-Options: nosniff lo impedisce indicando al browser che il tipo MIME impostato nell’intestazione Content-Type per una determinata risposta è corretto. Questa intestazione è consigliata per tutte le tue risorse.
Esempio di utilizzo:
X-Content-Type-Options: nosniff
Come usare X-Content-Type-Options – Usi consigliati
X-Content-Type-Options: nosniff è consigliato per tutte le risorse servite dal tuo server insieme all’intestazione Content-Type corretta.
Intestazioni di esempio inviate con un documento HTML:
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Per abilitare l’intestazione HTTP X-Content_Tyoe-Options su web server Nginx, aggiungi il seguente parametro in nginx.conf sotto il blocco del server:
add_header X-Content-Type-Options nosniff;
Nosniff: questa direttiva (l’unica disponibile) blocca una richiesta se la destinazione della richiesta è di tipo style e il tipo MIME non è testo/css o di tipo script e il tipo MIME non è un tipo MIME JavaScript.
Salva il file nginx.conf e riavvia Nginx per vedere i risultati.
Browser supportati:
- Chrome
- Firefox
- Edge
- Safari
X-Frame-Options
Questa intestazione è molto semplice da implementare ed è suggerita per tutti i siti web. Se un sito web dannoso potesse incorporare il tuo sito come iframe, ciò potrebbe consentire agli aggressori di invocare azioni indesiderate da parte dell’utente attraverso la tecnica del clickjacking. Inoltre, in alcuni casi, gli attacchi di tipo Spectre offrono ai siti web pericolosi la possibilità di conoscere il contenuto di un documento incorporato.
X-Frame-Options indica se a un browser dovrebbe essere consentito o meno il rendering di una pagina in un <frame>, <iframe>, <embed>, o <object>. Si consiglia a tutti i documenti di inviare questa intestazione per indicare se è possibile incorporarli in altri documenti.
Se è necessario un controllo più granulare, ad esempio, consentire solo a un’origine specifica di incorporare il documento, utilizzare la direttiva CSP frame-ancestors.
Esempio di utilizzo:
X-Frame-Options: DENY
Come usare X-Frame-Options – Usi consigliati
Tutti i documenti che non sono progettati per essere incorporati devono utilizzare l’intestazione X-Frame-Options.
Protegge il tuo sito Web dall’essere incorporato da qualsiasi altro sito web
Nega di essere incorporato da qualsiasi altro documento.
X-Frame-Options: DENY
Protegge il tuo sito Web dall’essere incorporato da qualsiasi sito web multi-origine
Consenti di essere incorporato solo da documenti della stessa origine.
X-Frame-Options: SAMEORIGIN
Puoi anche specificare i singoli domini a cui è concesso embeddare i tuoi documenti:
add_header X-Frame-Options ALLOW-FROM http://mysite.com/
add_header X-Frame-Options ALLOW-FROM http://www.mysite.com/
add_header X-Frame-Options ALLOW-FROM https://mysite.com/
add_header X-Frame-Options ALLOW-FROM https://www.mysite.com/
Per abilitare l’intestazione HTTP X-Frame-Options su web server Nginx aggiungi il seguente parametro in nginx.conf nella sezione server:
add_header X-Frame-Options "SAMEORIGIN";
Riavvia il web server Nginx per vedere i risultati.
Nota: i documenti sono incorporabili per impostazione predefinita, questo significa che gli sviluppatori devono inviare esplicitamente DENY o SAMEORIGIN per bloccare l’incorporamento e proteggersi dagli attacchi. Il team di Chrome sta valutando la possibilità di passare al blocco degli incorporamenti di documenti per impostazione predefinita in modo che i siti web siano sicuri anche se non impostano esplicitamente l’intestazione. In quel nuovo mondo, i documenti dovrebbero accettare esplicitamente di essere incorporati.
Browser supportati:
- Chrome
- Firefox
- Edge
- Safari
Cross-Origin Resource Policy (CORP)
Un utente malintenzionato può incorporare risorse provenienti da un’altra origine, ad esempio, dal tuo sito, per ottenere informazioni su di esse sfruttando le così chiamate web-based cross-site leaks.
L’intestazione di sicurezza Cross-Origin-Resource-Policy attenua questo rischio indicando l’insieme di siti web da cui può essere caricato. L’intestazione assume uno dei tre valori:
- same-origin
- same-site
- cross-origin
Si consiglia a tutte le risorse di inviare questa intestazione per indicare se consentono il caricamento da altri siti web.
Esempio di utilizzo:
Cross-Origin-Resource-Policy: same-origin
Come usare CORP – Usi consigliati
Si consiglia di servire tutte le risorse con una delle tre intestazioni seguenti.
Puoi provare in che modo le seguenti configurazioni influiscono sul caricamento delle risorse in un Cross-Origin-Embedder-Policy: require-corp ambiente in questa demo. Modificare il menu a discesa Cross-Origin-Resource-Policy e fare clic sul pulsante Ricarica l’iframe o Ricarica l’immagine per vedere l’effetto.
Cross-origin – Consenti il caricamento delle risorse tra le origini
È consigliabile che i servizi simili a CDN applichino l’origine incrociata alle risorse (poiché di solito vengono caricate da pagine con origine incrociata), a meno che non siano già serviti tramite CORS, il che ha un effetto simile.
Cross-Origin-Resource-Policy: cross-origin
Same-origin – Limita le risorse da caricare dalla stessa origine
la stessa origine deve essere applicata alle risorse destinate ad essere caricate solo da pagine della stessa origine. Dovresti applicarlo alle risorse che includono informazioni riservate sull’utente o alle risposte di un’API che dovrebbe essere chiamata solo dalla stessa origine.
Tieni presente che le risorse con questa intestazione possono comunque essere caricate direttamente, ad esempio, accedendo all’URL in una nuova finestra del browser. La politica delle risorse tra origini protegge solo la risorsa dall’essere incorporata da altri siti Web.
Cross-Origin-Resource-Policy: same-origin
Same-site – Limita le risorse da caricare dallo stesso sito
si consiglia di applicare lo stesso sito a risorse simili alle precedenti ma destinate ad essere caricate da altri sottodomini del tuo sito.
Cross-Origin-Resource-Policy: same-site
Per abilitare l’intestazione HTTP Access-Control-Allow-Origin su web server Nginx devi aggiungere la direttiva add_header al server block del tuo file di configurazione Nginx:
server{
...
add_header Access-Control-Allow-Origin "example1.com";
add_header Access-Control-Allow-Origin "example2.com";
add_header Access-Control-Allow-Origin "example3.com";
...
}
Riavvia Nginx per vedere i risultati.
Browser supportati:
- Chrome
- Firefox
- Edge
- Safari
Cross-Origin Opener Policy (COOP)
Il sito web di un utente malintenzionato può aprire un altro sito in una finestra popup per ottenere informazioni su di esso. In alcuni casi, ciò può consentire anche lo sfruttamento di attacchi side-channel basati su Spectre.
Abilitando la direttiva COOP: same-origin su un documento di primo livello, le finestre con la stessa origine e le finestre aperte dal documento avranno un gruppo di contesto di navigazione separato a meno che non si trovino nella stessa origine con la stessa impostazione COOP. Pertanto, viene applicato l’isolamento per le finestre aperte e la comunicazione reciproca tra entrambe le finestre è disabilitata.
Un gruppo di contesto di navigazione è un insieme di finestre che possono comunicare. Ad esempio, un documento di primo livello e i suoi documenti figlio incorporati tramite iframe. Se un sito web (https://a.esempio) apre una finestra popup (https://b.esempio), la finestra di apertura e la finestra popup condividono lo stesso contesto di navigazione, quindi hanno accesso l’una all’altra tramite API DOM come come window.opener.
L’intestazione Cross-Origin-Opener-Policy consente a un documento di isolarsi dalle finestre di origine incrociata aperte tramite window.open() o un collegamento con target=”_blank” senza rel=”noopener”. Di conseguenza, qualsiasi apri cross-origine del documento non avrà alcun riferimento ad esso e non sarà in grado di interagire con esso.
Esempio di utilizzo:
Cross-Origin-Opener-Policy: same-origin-allow-popups
Come usare COOP – Usi consigliati
Puoi provare in che modo le seguenti configurazioni influiscono sulla comunicazione con una finestra popup multi-origine in questa demo. Modifica il menu a discesa Cross-Origin-Opener-Policy sia per il documento che per la finestra popup, fai clic sul pulsante Apri un popup, quindi fai clic su Invia un postMessage per vedere se il messaggio è stato effettivamente recapitato.
Ecco cosa devi fare a seconda della natura della risorsa:
- Se si prevede che la risorsa venga caricata solo dalla stessa origine, impostare l’intestazione Cross-Origin-Resource-Policy: same-origin
- Se si prevede che la risorsa venga caricata solo dallo stesso sito ma da un’origine incrociata, impostare l’intestazione Cross-Origin-Resource-Policy: same-site
- Se la risorsa viene caricata da origini incrociate sotto il tuo controllo, imposta l’intestazione Cross-Origin-Resource-Policy: cross-origin
- Per le risorse con origini incrociate su cui non hai il controllo:
- Utilizzare l’attributo crossorigin nel tag HTML di caricamento se la risorsa è servita con CORS. (Ad esempio, <img src=”***” crossorigin>)
- Chiedi al proprietario della risorsa di supportare CORS o CORP.
- Per gli iframe, segui gli stessi principi di cui sopra e imposta Cross-Origin-Resource-Policy: cross-origin (o same-site, same-origin a seconda del contesto).
- Gli script caricati con un WebWorker devono essere serviti dalla stessa origine, quindi non sono necessarie intestazioni CORP o CORS.
- Per un documento o un worker servito con COEP: require-corp, le sottorisorse multi-origine caricate senza CORS devono impostare l’intestazione Cross-Origin-Resource-Policy: cross-origin per attivare l’inclusione. Ad esempio, questo vale per <script>, importScripts, <link>, <video>, <iframe>, etc.
Dopo aver implementato le nuove intestazioni e direttive, puoi monitorare eventuali errori o blocchi nei caricamenti delle dipendenze attraverso la console del browser.
Isolare un documento dalle finestre di origine incrociata
L’impostazione della stessa origine consente di isolare il documento dalle finestre dei documenti con origini diverse.
Cross-Origin-Opener-Policy: same-origin
Isola un documento dalle finestre con origini diverse ma consenti i popup
L’impostazione same-origin-allow-popups consente a un documento di conservare un riferimento alle sue finestre popup a meno che non imposti COOP con popup consentiti della stessa origine. Ciò significa che i popup della stessa origine possono comunque proteggere il documento dal riferimento quando viene aperto come finestra popup, ma consentirgli di comunicare con i propri popup.
Cross-Origin-Opener-Policy: same-origin-allow-popups
Consenti a un documento di essere referenziato da finestre di origine incrociata
unsafe-none è il valore predefinito, ma puoi indicare esplicitamente che questo documento può essere aperto da una finestra multi-origine e mantenere l’accesso reciproco.
Nota: essendo unsafe-none l’impostazione predefinita significa che gli sviluppatori devono inviare esplicitamente popup della stessa origine per proteggere il proprio sito web dagli attacchi.
Cross-Origin-Opener-Policy: unsafe-none
Funzionalità come SharedArrayBuffer o performance.measureUserAgentSpecificMemory() sono disabilitate per impostazione predefinita. Alcuni browser ti consentono di utilizzarli in contesti “isolati da più origini”, che richiedono l’impostazione di intestazioni COOP e COEP.
Segnala modelli incompatibili con COOP
Puoi ricevere rapporti quando COOP impedisce interazioni tra finestre con l’API di reporting.
Cross-Origin-Opener-Policy: same-origin; report-to="coop"
COOP supporta anche una modalità di solo report in modo da poter ricevere report senza bloccare effettivamente la comunicazione tra documenti di origine incrociata.
Cross-Origin-Opener-Policy-Report-Only: same-origin; report-to="coop"
Browser supportati:
- Chrome
- Firefox
- Edge
- Safari
HTTP Strict Transport Security (HSTS)
Come sappiamo la comunicazione su una semplice connessione HTTP non è crittografata, rendendo i dati trasferiti accessibili agli intercettatori a livello di rete.
L’intestazione Strict-Transport-Security informa il browser che non dovrebbe mai caricare il sito utilizzando HTTP e utilizzare invece HTTPS. Una volta impostato, il browser utilizzerà HTTPS anziché HTTP per accedere al dominio senza reindirizzamento per una durata definita nell’intestazione.
Esempio di utilizzo:
Strict-Transport-Security: max-age=31536000
Usi consigliati
Tutti i siti web che passano da HTTP a HTTPS devono rispondere con un’intestazione Strict-Transport-Security quando viene ricevuta una richiesta con HTTP.
Strict-Transport-Security: max-age=31536000
max-age definisce la durata in secondi.
Per abilitare l’intestazione HTTP Strict-Transport-Security su web server Nginx aggiungi la seguente configurazione al tuo file di configurazione.
server {
...
add_header Strict-Transport-Security "max-age=31536000;
includeSubDomains" always;
...
Browser supportati:
- Chrome
- Firefox
- Edge
- Safari
Cross-Origin Resource Sharing (CORS)
A differenza di altri elementi in questo articolo, Cross-Origin Resource Sharing (CORS) non è un’intestazione, ma un meccanismo del browser che richiede e consente l’accesso alle risorse multi-origine.
Per impostazione predefinita, i browser applicano la politica same-origin per impedire a una pagina web di accedere a risorse multi-origine. Ad esempio, quando viene caricata un’immagine con origini incrociate, anche se viene visualizzata visivamente sulla pagina web, il JavaScript nella pagina non ha accesso ai dati dell’immagine. Il fornitore di risorse può allentare le restrizioni e consentire ad altri siti Web di leggere la risorsa utilizzando la direttiva CORS.
Esempio di utilizzo:
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
Come usare CORS
Prima di esaminare come configurare CORS, è utile comprendere la distinzione tra i tipi di richiesta. A seconda dei dettagli della richiesta, una richiesta verrà classificata come richiesta semplice o richiesta preflight.
Criteri per una semplice richiesta:
- Il metodo è GET, HEAD o POST.
- Le intestazioni personalizzate includono solo Accept, Accept-Language, Content-Language e Content-Type.
- Il tipo di contenuto è application/x-www-form-urlencoded, multipart/form-data o text/plain.
Tutto il resto è classificato come richiesta preflight. Per maggiori dettagli, consulta Condivisione risorse tra origini (CORS) – HTTP | MDN.
Usi consigliati
Questa intestazione HTTP di sicurezza è consigliata per siti web con funzionalità avanzate.
Richiesta semplice
Quando una richiesta soddisfa i criteri di richiesta semplice, il browser invia una richiesta multi-origine con un’intestazione Origin che indica l’origine della richiesta.
Esempio di intestazione della richiesta
Get / HTTP/1.1
Origin: https://example.com
Esempio di intestazione di risposta
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
- Access-Control-Allow-Origin: https://example.com indica che https://example.com può accedere al contenuto della risposta. Le risorse destinate a essere leggibili da qualsiasi sito possono impostare questa intestazione su *, nel qual caso il browser richiederà solo che la richiesta venga effettuata senza credenziali.
- Access-Control-Allow-Credentials: true indica che le richieste che contengono credenziali (cookie) possono caricare la risorsa. In caso contrario, le richieste autenticate verranno rifiutate anche se l’origine richiedente è presente nell’intestazione Access-Control-Allow-Origin.
Puoi provare in che modo la semplice richiesta influisce sul caricamento delle risorse in un ambiente Cross-Origin-Embedder-Policy: require-corp in questa demo. Fare clic sulla casella di controllo Condivisione risorse tra origini e fare clic sul pulsante Ricarica l’immagine per vedere l’effetto.
Richieste preflight
Una richiesta preflight è preceduta da una richiesta OPTIONS per verificare se la richiesta successiva può essere inviata.
Esempio di intestazione della richiesta
OPTIONS / HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
- Access-Control-Request-Method: POST consente di effettuare la seguente richiesta con il metodo POST.
- Access-Control-Request-Headers: X-PINGOTHER, Content-Type consente al richiedente di impostare le intestazioni HTTP X-PINGOTHER e Content-Type nella richiesta successiva.
Esempi di intestazioni di risposta:
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
- Access-Control-Allow-Methods: POST, GET, OPTIONS
- indica che le richieste successive possono essere effettuate con i metodi POST, GET e OPTIONS.
- Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
- indica che le richieste successive possono includere le intestazioni X-PINGOTHER e Content-Type.
- Access-Control-Max-Age: 86400
- indica che il risultato della richiesta preflight può essere memorizzato nella cache per 86400 secondi.
Browser supportati:
- Chrome
- Firefox
- Edge
- Safari
Cross-Origin Embedder Policy (COEP)
Per ridurre la capacità degli attacchi basati su Spectre di rubare risorse tra origini diverse, funzionalità come SharedArrayBuffer o performance.measureUserAgentSpecificMemory() sono disabilitate per impostazione predefinita.
Cross-Origin-Embedder-Policy: require-corp impedisce a documenti e lavoratori di caricare risorse multi-origine come immagini, script, fogli di stile, iframe e altro a meno che queste risorse non scelgano esplicitamente di essere caricate tramite CORS o intestazioni CORP. COEP può essere combinato con Cross-Origin-Opener-Policy per optare per un documento in isolamento tra origini.
Usa Cross-Origin-Embedder-Policy: require-corp quando vuoi abilitare l’isolamento tra origini per il tuo documento.
Esempio di utilizzo
Cross-Origin-Embedder-Policy: require-corp
Come usare COEP – Esempi di utilizzo
Questa intestazione HTTP di sicurezza è consigliata per siti web con funzionalità avanzate.
COEP assume un unico valore di require-corp. Inviando questa intestazione, puoi indicare al browser di bloccare il caricamento delle risorse che non accettano tramite CORS o CORP.
Puoi provare in che modo le seguenti configurazioni influiscono sul caricamento delle risorse in questa demo. Modifica il menu a discesa Cross-Origin-Embedder-Policy, il menu a discesa Cross-Origin-Resource-Policy, la casella di controllo Report Only ecc. per vedere come influiscono sul caricamento delle risorse. Inoltre, apri la demo dell’endpoint di reporting per vedere se le risorse bloccate vengono segnalate.
Abilita isolamento tra origini
Abilita l’isolamento tra le origini inviando Cross-Origin-Embedder-Policy: require-corp insieme a Cross-Origin-Opener-Policy: same-origin.
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
Segnala risorse incompatibili con COEP
È possibile ricevere report di risorse bloccate causate da COEP con l’API Reporting.
Cross-Origin-Embedder-Policy: require-corp; report-to="coep"
COEP supporta anche la modalità solo report in modo da poter ricevere report senza bloccare effettivamente il caricamento delle risorse.
Cross-Origin-Embedder-Policy-Report-Only: require-corp; report-to="coep"
Browser supportati:
- Chrome
- Firefox
- Edge
- Safari
Conclusione
Abbiamo visto diversi metodi per aumentare la sicurezza del sito web. Attraverso semplici impostazioni del web server che aggiungono intestazioni HTTP possiamo limitare le azioni dei browser ed impedire che vengano eseguite alcune attività potenzialmente a rischio.
Mi piace molto lavorare sulla sicurezza dei siti web ottimizzando il web server perché si possono creare molte regole utili con il minimo sforzo. Se avessi un eCommerce oppure un sito web che tratta dati sensibili, dovresti preoccuparti di raggiungere i più alti livelli di sicurezza per proteggere te e i tuoi utenti.
Cosa ne pensi? Hai dubbi o domande? Lascia un commento!