Come funziona la politica di sicurezza dei contenuti?


248

Ricevo un sacco di errori nella console degli sviluppatori:

Rifiutato di valutare una stringa

Rifiutato di eseguire script inline perché viola la seguente direttiva sulla politica di sicurezza dei contenuti

Rifiutato di caricare lo script

Rifiutato di caricare il foglio di stile

Di cosa si tratta? Come funziona la politica di sicurezza dei contenuti? Come si usa l' Content-Security-Policyintestazione HTTP?

In particolare, come ...

  1. ... consentire più fonti?
  2. ... usi direttive diverse?
  3. ... usi più direttive?
  4. ... gestire le porte?
  5. ... gestire protocolli diversi?
  6. ... consentire il file://protocollo?
  7. ... usa stili, script e tag incorporati <style>e <script>?
  8. ... permetti eval()?

E infine:

  1. Cosa 'self'significa esattamente ?

Risposte:


557

Il Content-Security-Policymeta-tag consente di ridurre il rischio di attacchi XSS consentendo di definire da dove possono essere caricate le risorse, impedendo ai browser di caricare dati da qualsiasi altra posizione. Ciò rende più difficile per un utente malintenzionato inserire codice dannoso nel tuo sito.

Ho sbattuto la testa contro un muro di mattoni cercando di capire perché stavo ricevendo errori CSP uno dopo l'altro e non sembravano esserci istruzioni concise e chiare su come funziona. Quindi ecco il mio tentativo di spiegare brevemente alcuni punti del CSP, concentrandomi principalmente sulle cose che ho trovato difficile da risolvere.

Per brevità non scriverò il tag completo in ogni campione. Invece mostrerò solo la contentproprietà, quindi un esempio che dice content="default-src 'self'"significa questo:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'">

1. Come consentire più fonti?

Puoi semplicemente elencare le tue fonti dopo una direttiva come un elenco separato da spazi:

content="default-src 'self' https://example.com/js/"

Nota che non ci sono virgolette attorno a parametri diversi da quelli speciali , come 'self'. Inoltre, non esiste due punti ( :) dopo la direttiva. Solo la direttiva, quindi un elenco di parametri separato da spazi.

Tutto sotto i parametri specificati è implicitamente consentito. Ciò significa che nell'esempio sopra si tratterebbe di fonti valide:

https://example.com/js/file.js
https://example.com/js/subdir/anotherfile.js

Questi, tuttavia, non sarebbero validi:

http://example.com/js/file.js
^^^^ wrong protocol

https://example.com/file.js
                   ^^ above the specified path

2. Come usare direttive diverse, cosa fanno ognuna?

Le direttive più comuni sono:

  • default-src la politica predefinita per il caricamento di JavaScript, immagini, CSS, caratteri, richieste AJAX, ecc
  • script-src definisce fonti valide per file javascript
  • style-src definisce fonti valide per file css
  • img-src definisce fonti valide per le immagini
  • connect-srcdefinisce destinazioni valide per XMLHttpRequest (AJAX), WebSocket o EventSource. Se viene effettuato un tentativo di connessione a un host non consentito qui, il browser emulerà un 400errore

Ce ne sono altri, ma questi sono quelli di cui probabilmente avrai bisogno.

3. Come utilizzare più direttive?

Definisci tutte le tue direttive all'interno di un meta-tag terminandole con un punto e virgola ( ;):

content="default-src 'self' https://example.com/js/; style-src 'self'"

4. Come gestire le porte?

Tutto tranne le porte predefinite deve essere consentito esplicitamente aggiungendo il numero di porta o un asterisco dopo il dominio consentito:

content="default-src 'self' https://ajax.googleapis.com http://example.com:123/free/stuff/"

Quanto sopra comporterebbe:

https://ajax.googleapis.com:123
                           ^^^^ Not ok, wrong port

https://ajax.googleapis.com - OK

http://example.com/free/stuff/file.js
                 ^^ Not ok, only the port 123 is allowed

http://example.com:123/free/stuff/file.js - OK

Come ho già detto, puoi anche utilizzare un asterisco per consentire esplicitamente tutte le porte:

content="default-src example.com:*"

5. Come gestire protocolli diversi?

Per impostazione predefinita, sono consentiti solo protocolli standard. Ad esempio per consentire WebSocket ws://dovrete consentirlo esplicitamente:

content="default-src 'self'; connect-src ws:; style-src 'self'"
                                         ^^^ web sockets are now allowed on all domains and ports

6. Come consentire il protocollo file file://?

Se proverai a definirlo come tale non funzionerà. Invece, lo consentirai con il filesystemparametro:

content="default-src filesystem"

7. Come utilizzare gli script incorporati e le definizioni di stile?

A meno che non sia esplicitamente consentito, non è possibile utilizzare definizioni di stile in linea, codice all'interno di <script>tag o in proprietà tag come onclick. Li consenti in questo modo:

content="script-src 'unsafe-inline'; style-src 'unsafe-inline'"

Dovrai anche consentire esplicitamente immagini in linea con codifica base64:

content="img-src data:"

8. Come consentire eval()?

Sono sicuro che molte persone direbbero che non lo fai, dal momento che "eval is evil" e la causa più probabile per l'imminente fine del mondo. Quelle persone avrebbero torto. Certo, puoi sicuramente punzonare i buchi principali nella sicurezza del tuo sito con eval, ma ha casi d'uso perfettamente validi. Devi solo essere intelligente su come usarlo. Lo consenti in questo modo:

content="script-src 'unsafe-eval'"

9. Cosa 'self'significa esattamente ?

Potresti 'self'voler dire localhost, filesystem locale o qualsiasi cosa sullo stesso host. Non significa nessuno di quelli. Significa fonti che hanno lo stesso schema (protocollo), stesso host e stessa porta del file in cui è definita la politica dei contenuti. Servire il tuo sito su HTTP? Nessun https per te, a meno che tu non lo definisca esplicitamente.

Ho usato 'self'nella maggior parte degli esempi in quanto di solito ha senso includerlo, ma non è assolutamente obbligatorio. Lascialo fuori se non ne hai bisogno.

Ma aspetta un minuto! Non posso semplicemente usarlo content="default-src *"e finirlo?

No. Oltre alle ovvie vulnerabilità della sicurezza, anche questo non funzionerà come ti aspetteresti. Anche se alcuni documenti sostengono che consenta qualsiasi cosa, non è vero. Non consente inline o eval, quindi per rendere il tuo sito estremamente vulnerabile, dovresti usare questo:

content="default-src * 'unsafe-inline' 'unsafe-eval'"

... ma confido che non lo farai.

Ulteriori letture:

http://content-security-policy.com

http://en.wikipedia.org/wiki/Content_Security_Policy


6
Ottimo post. Una cosa: non è ovvio cosa succede quando vengono specificate più direttive; le impostazioni di style-src nell'esempio 3 hanno la precedenza su default-src? ecc ...
track0

30
Quindi, per consentire a tutto ciò che sarebbe contenutodefault-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;
Arnold Roa il

8
È importante sapere che content="default-src * 'unsafe-inline' 'unsafe-eval'"è necessario per far funzionare alcune applicazioni angolari.
flanger001,

2
@Mahesh Quel "blog" è pieno di post copiati da SO. Sembra improbabile che così tanti utenti SO possano copiare i contenuti di un blogger sconosciuto - so di non averlo fatto.
Schlaus,

2
Breve nota relativa a connect-srce percorsi: le barre finali sono obbligatorie se si desidera includere un intero sottopercorso. Ad esempio: il file http://foo.com/files/bar.txtverrà bloccato se la fonte è http://foo.com/files, ma servito quando èhttp://foo.com/files/
Griddo,

15

APACHE2 MOD_HEADERS

Potresti anche abilitare mod_headers di Apache2, su Fedora è già abilitato di default, se usi Ubuntu / Debian abilitalo in questo modo:

# First enable headers module for Apache2, 
# then restart the Apache2 service   
a2enmod headers
apache2 -k graceful

Su Ubuntu / Debian è possibile configurare le intestazioni nel file /etc/apache2/conf-enabled/security.conf

#
# Setting this header will prevent MSIE from interpreting files as something
# else than declared by the content type in the HTTP headers.
# Requires mod_headers to be enabled.
# 
#Header set X-Content-Type-Options: "nosniff"

#
# Setting this header will prevent other sites from embedding pages from this
# site as frames. This defends against clickjacking attacks.
# Requires mod_headers to be enabled.
#
Header always set X-Frame-Options: "sameorigin"
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Permitted-Cross-Domain-Policies "master-only"
Header always set Cache-Control "no-cache, no-store, must-revalidate"
Header always set Pragma "no-cache"
Header always set Expires "-1"
Header always set Content-Security-Policy: "default-src 'none';"
Header always set Content-Security-Policy: "script-src 'self' www.google-analytics.com adserver.example.com www.example.com;"
Header always set Content-Security-Policy: "style-src 'self' www.example.com;"

Nota: questa è la parte inferiore del file, solo le ultime 3 voci sono impostazioni CSP.

Il primo parametro è la direttiva, il secondo sono le fonti da elencare in bianco. Ho aggiunto Google Analytics e un adserver, che potresti avere. Inoltre ho scoperto che se hai degli alias, ad esempio www.example.com ed example.com configurati in Apache2, dovresti aggiungerli anche alla white list.

Il codice incorporato è considerato dannoso, dovresti evitarlo. Copia tutti i javascript e i CSS in file separati e aggiungili alla lista bianca.

Mentre ci sei, puoi dare un'occhiata alle altre impostazioni dell'intestazione e installare mod_security

Ulteriori letture:

https://developers.google.com/web/fundamentals/security/csp/

https://www.w3.org/TR/CSP/


2
Sono stato in grado di aggiungere quelle stesse direttive al mio file .htaccess, dal momento che non ho la possibilità di modificare le configurazioni di Apache sul mio host condiviso. Ho trovato strumenti eccellenti per regolare queste impostazioni su report-uri.io/home/tools .
Michael McGinnis,

Esiste un modo per risolvere questo problema con Tomcat 7. Ho provato ad aggiungere filtri e non ha funzionato.
Elshan,

0

Non dimenticare di font-src funziona come qualsiasi altro, ma se usi font caricati da altre origini, assicurati di aggiungerlo al meta tag

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.