Content Security Policy: più sicurezza per i contenuti sul web
I contenuti attivi presenti sui siti web, come ad esempio JavaScript, CSS e ActiveX, rappresentano un pericolo per gli utenti e per i gestori delle pagine web poiché potreste essere manipolati dai cosiddetti Cross Site Scripting. Per fare sì che le pagine Internet possano essere utilizzate in modo esaustivo senza correre rischi, è stata introdotta la Content Security Policy (CSP). Questo standard di sicurezza, supportato dalla maggioranza dei browser moderni, ha l’obiettivo di difendere i siti web dagli attacchi cibernetici e, contemporaneamente, di proteggere gli utenti. Ma cosa si nasconde dietro la CSP e come funziona?
Evoluzione della Content Security Policy
La Content Security Policy ha origini nel 2014 ed era inizialmente conosciuta con il nome di “Content Restriction”. La nascita di questo progetto è stata provocata dalla quantità crescente di falle di sicurezza negli script di Internet; in particolare il Cross Site Scripting (XSS), un metodo criminale per far entrare clandestinamente dei malware in un determinato sito web, molto rischioso per gli utenti.
Può infatti accadere che si apra un sito Internet considerato affidabile, ma poi viene eseguito uno script che carica dati dannosi da una fonte sconosciuta. I criminali informatici possono utilizzare a questo scopo le falle di sicurezza presenti, ad esempio, nella funzione di inserimento commenti di un sito web. In questo modo i malintenzionati possono riuscire ad ottenere l’accesso al PC dell’utente senza che questo se ne accorga. Neanche i webmaster riescono a capire immediatamente quand’è che un codice esterno entra clandestinamente in un sito Internet.
Per ovviare a questo problema, Mozilla Foundation ha deciso di accelerare lo sviluppo della CSP. Il vantaggio degli standard di sicurezza consiste nel fatto che è possibile stabilire quali script devono essere eseguiti dal software e quali no. Per fare questo la Content Security Policy ricorre agli header HTTP.
Mozilla Foundation è l’organizzazione che si occupa dello sviluppo del browser di Firefox. Questa organizzazione no-profit gestisce il progetto di Mozilla e le innovazioni riguardo Internet. Mozilla Foundation è stata fondata dagli ex dipendenti di Netscape, che hanno sviluppato il primo browser web.
Come funziona la Content Security Policy?
Durante la trasmissione di informazioni tramite Internet, tra i client e i server avviene uno scambio di dati mediante l’Hypertext Transfer Protocol (HTTP). Una delle componenti principali delle request e delle response sono gli header HTTP: questi campi vengono utilizzati per trasmettere parametri e argomenti, importanti per lo scambio dei dati tra emittente e ricevente, ossia tra client e server. Sono generalmente suddivisi in campi di richiesta e risposta e, ad esempio, possono contenere informazioni sul set di caratteri, sulla lingua e sui cookie. La CSP viene implementata in qualità di campo di intestazione della risposta. Ciò significa che il server fornisce le informazioni e il browser le elabora.
L’header della Content Security Policy viene implementato dal webmaster e inserito in tutte le sottopagine del sito web a cui si desidera applicare lo standard di sicurezza. Il gestore del sito Internet, inoltre, ha la possibilità di stabilire provvedimenti per la sicurezza che si differenziano da pagina a pagina. È possibile implementare il concetto di sicurezza più facilmente creando un file .htaccess nelle stesse cartelle (o in quelle gerarchicamente più alte) delle pagine web corrispondenti o ancorando la CSP direttamente nella configurazione del server.
Se un utente vuole verificare se il proprio browser supporta o meno la Content Security Policy, è possibile eseguire il test per browser per CSP. Il test consiste nel provare ad eseguire alcuni script e a richiamare immagini da fonti sconosciute (non dannose), mostrando all’utente se il procedimento è andato a buon fine. Il browser in esame è sicuro se non ha caricato i dati delle fonti sconosciute poiché ciò implica che capisce e utilizza la CSP.
In una Content Security Policy e al fine di prevenire lo scripting tra siti diversi, i webmaster dovrebbero memorizzare tutti gli script in file separati e non incorporarli direttamente nel codice sorgente del proprio sito Internet. Questo indica che la CSP funziona secondo il principio della whitelist: nell’header vengono elencate le fonti da cui è possibile caricare gli script e i dati. Dunque, nel momento in cui viene inserito uno script sconosciuto nel codice HTML della pagina, il browser dell’utente deve proibire il caricamento di dati esterni. Per impostazione predefinita, la CSP blocca tutti gli script inseriti direttamente nel codice (inline scripting). Questo protegge sia il sito web che gli utenti, e soprattutto i loro dati sensibili.
Per i cybercriminali le manipolazioni tramite Cross Site Scripting sono relativamente semplici da attuare. Infatti quasi tutti i siti Internet sono dotati di un campo di input, come ad esempio la funzione di inserimento commenti, la barra di ricerca o il campo per effettuare il login: in queste sezioni, invece di inserire delle semplici parole, spesso vengono eseguiti degli script.
Dunque, se il server non è correttamente cautelato, i criminali informatici possono implementare interfacce di phishing, causare un blocco del sito web oppure utilizzare dei malware per ottenere il controllo dell’utente tramite browser. La CSP (o più precisamente: l’header corrispettivo) comunica al browser web da quali fonti è consentito caricare dei dati. Se la policy è implementata nel codice del sito web, al tentativo di recuperare quel codice introdotto tramite XSS viene risposto con un messaggio di errore.
Tramite l’utilizzo della Content Security Policy i webmaster possono modificare numerose impostazioni, ad esempio, tramite le seguenti direttive:
- base-uri: limita gli URL che possono comparire nell’elemento <base> della pagina web.
- child-src: stabilisce le fonti da cui trarre i dati che possono apparire nei frame, ad esempio i video forniti da terzi.
- connect-src: limita le fonti alle quali il sito Internet può connettersi, ad esempio tramite link.
- font-src: stabilisce da quali fonti possono essere caricati i font
- form-action: fornisce una lista di moduli endpoint validi.
- frame-ancestors: stabilisce quali domini possono strutturare la pagina in frame e iFrame.
- img-src: stabilisce da quali fonti possono essere caricate le immagini.
- media-src: determina da quali fonti possono essere caricati formati audio e video.
- object-src: controlla Flash e altri tipi di plug-in.
- plugin-types: limita le tipologie di plug-in.
- report-uri: specifica un URL a cui inviare i report in caso di violazione delle misure di sicurezza.
- script-src: determina quali fonti sono consentite per JavaScript.
- style-src: funziona come script-src, ma è usato per i fogli di stile.
- upgrade-insecure-requests: stabilisce che le pagine HTTP non protette vengano considerate come pagine HTTPS.
- sandbox: sposta la pagina in un sandbox in cui sono vietati moduli, pop-up e script.
Queste direttive sono valide solo se esplicitamente riconosciute, altrimenti restano aperte di default, costituendo così una falla di sicurezza nel sistema. Tuttavia tramite il default-src è possibile eludere questo problema: con questo metodo si stabiliscono le impostazioni di tutte le direttive che terminano con -src. Ad esempio, è possibile stabilire che il proprio sito Internet carichi soltanto i dati, a meno che non sia stato specificato diversamente nell'header HTTP di una singola pagina. Nelle direttive specifiche, inoltre, è possibile anche aggiungere atre fonti.
Nell’header è possibile immettere un numero potenzialmente infinito di direttive. Se si desidera includere più direttive, è necessario separarle con punto e virgola. Inoltre, il webmaster deve specificare tutte le sorgenti e le fonti all’interno di una direttiva. Non sono consentite citazioni multiple delle stesse direttive con fonti aggiuntive. L’esempio seguente mostra un comando non ammesso:
script-src esempio1.local; script-src esempio2.local
In questo caso, solo la prima sorgente è rilevante, la seconda invece viene ignorata dal client. Al contrario, in una direttiva si devono specificare entrambe le sorgenti:
script-src esempio1.local esempio2.local
Se non si ha bisogno di determinati tipi di contenuto per una pagina o per l'intero sito web, è possibile inserire il valore "none" nell’header corrispondente, specificando che non è possibile caricare alcuna fonte. È inoltre possibile utilizzare il valore "self" per specificare che il browser può caricare solo i contenuti provenienti dalla stessa sorgente. Entrambi i valori devono sempre essere inclusi in virgolette singole, altrimenti "none" e "self" saranno interpretati come domini.
Al fine di definire una Content Security Policy, nell’header possono essere inserite sintassi diverse:
- Content-Security-Policy
- X-Webkit-CSP
- X-Content-Security-Policy
Non tutti i browser supportano tutte le denominazioni. Tuttavia, il W3C (l’organismo che definisce gli standard per il web) propone una Content Security Policy universale. Pertanto tutti i browser più recenti si sono adattati a questo standard di sicurezza (le altre versioni sono considerate obsolete). Per essere sicuri di raggiungere il maggior numero possibile di utenti (anche quelli con versioni obsolete del browser) con la vostra CSP, è consigliabile implementare tutti gli header. Se un browser non è in grado di utilizzare l’header della Content Security Policy, lo ignora e visualizza il sito Internet facilmente, ma senza offrire alcuna protezione aggiuntiva.
Di solito gli header HTTP vengono impostati su tutte le pagine del dominio. Per le sottodirectory è possibile utilizzare il file .htaccess. Successivamente si utilizza lo standard di sicurezza CSP per definire regole speciali per le singole sottopagine. Ad esempio, se è stato implementato un pulsante per i social media in una pagina ma non in quella successiva, ha senso consentire l’accesso alla fonte esterna solo nel primo caso.
Le fonti possono essere immesse sia come indirizzi che come caratteri jolly. Sono pertanto consentiti i seguenti codici:
- script-src "https://example.com:443" - Gli script sono consentiti solo da questo dominio tramite HTTPS.
- script-src 'none'- Gli script non devono essere caricati.
- script-src 'self' - Gli script possono essere caricati dalla stessa fonte della pagina corrente, ma non dai sottodomini.
- script-src https: - Gli script possono essere caricati da qualsiasi dominio a condizione che si utilizzi il protocollo HTTPS.
- script-src example.com - Gli script possono essere caricati da questo dominio.
- script-src *.example.com - Gli script di questo dominio e di tutti i sottodomini sono ammessi.
- img-src data: - Le immagini possono essere caricate tramite lo schema data-URL.
In linea di massima una Content Security Policy stabilisce che gli script possono essere caricati solo da file, non direttamente dal codice del sito web. In alternativa è possibile utilizzare lo script di comando script-src 'unsafe-inline', ma non si deve dimenticare che questo non assicura la completa sicurezza del sito. La norma di sicurezza vieta anche la funzione eval (). In realtà con questo comando è possibile convertire il testo in un codice JavaScript, ma anche questo è un rischio per la sicurezza. Se avete ancora bisogno di questa funzione, potete riattivarla con script-src 'unsafe-eval'.
Tramite una piccola variazione è possibile rendere più sicuro l’unsafe inline: utilizzando gli hash oppure il Nonce-Source potrete colmare quasi totalmente le falle nel sistema di sicurezza.
Se non è più possibile visualizzare gli script direttamente nel codice, è necessario creare un file separato per ciascuno script. La funzione dello script è memorizzata in un file .js. Solo questi sono menzionati nel codice del sito web:
<script src='beispiel.js'></script>
Le azioni dello script sono descritte nel file example.js. È inoltre necessario memorizzare gli elementi di stile in fogli di stile separati. Se un webmaster vuole introdurre una Internet Security Policy, non è sufficiente implementare l’header. È inoltre necessario controllare e adattare il codice sorgente del vostro sito web.
Vuoi sapere quanto è sicuro il vostro sito web? Mozilla offre un test facile da usare: Observatory by Mozilla vi darà un punteggio dopo una scansione e vi dirà in quali punti rendere il vostro sito web più sicuro.
Content Security Policy: un esempio
Di seguito vi illustriamo come realizzare una Content Security Policy, vi spieghiamo come utilizzare l’header e quali risultati potete raggiungere.
- Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri 'https://example.org/report.html';
- X-Content-Security-Policy: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri 'https://example.org/report.html';
- X-WebKit-CSP: "default-src 'none'; script-src 'self' *.example.com; style-src 'self'; img-src 'self' data:; font-src 'self' https://fonts.google.com/; report-uri 'https://example.org';
Dall’esempio di cui sopra si può evincere che ogni variante di CSP compare nell’header in modo da poter richiamare quanti più browser possibili. Ogni nome dell’header riporta lo stesso contenuto: le fonti sono elencate una dopo l’altra e le direttive sono separate da un punto e virgola. La sintassi è quindi sempre la stessa. Infatti cambia solo il nome del campo, in modo da poterne semplicemente duplicare il contenuto.
In primo luogo bisogna specificare che, salvo altre indicazioni riportate in una direttiva, i dati non devono essere caricati da alcuna fonte (default-src). Operando in questo modo è possibile colmare falle nella sicurezza. Per questo motivo il default-src deve essere sempre specificato per primo. Questo evita che qualsiasi altra direttiva non specificata possa causare problemi nella vostra Content Security Policy.
Nel prossimo passaggio bisogna definire le fonti da cui possono essere caricati gli script (script-src). Nell’esempio abbiamo specificato che il browser esegue solo gli script provenienti dalla stessa sorgente e da example.com, inclusi tutti i suoi sottodomini (la wildcard viene assegnata tramite *). Inoltre i client possono caricare i fogli di stile solo dalla propria sorgente (style-src). Anche il caricamento delle immagini è consentito solo se effettuato dalla stessa fonte e come schema data-URL (img-src). A seconda dell’header della Content Security Policy, i font possono essere caricati solo dalla sorgente. Infine, nell'esempio, viene specificato un indirizzo a cui inviare i messaggi, nel caso si verificasse un tentativo di violazione dello standard di sicurezza (report-uri).
Noterete che nell’header non sono state implementate tutte le direttive, ma non è un fattore determinante: nel caso specificato poco sopra non si necessita di altre whitelist; e tramite il default-src le altre sorgenti vengono disattivate.
Su Internet sono disponibili diversi generatori di Content Security Policy. Con offerte come CSP Is Awesome oppure Report URI è possibile creare un header per CSP in modo semplice e affidabile.