Como a Política de Segurança de Conteúdo funciona?

248

Estou recebendo vários erros no console do desenvolvedor:

Recusou-se a avaliar uma sequência

Recusou-se a executar o script embutido porque viola a seguinte diretiva de política de segurança de conteúdo

Recusou carregar o script

Recusou-se a carregar a folha de estilo

O que é isso tudo? Como a Política de Segurança de Conteúdo funciona? Como uso o Content-Security-Policycabeçalho HTTP?

Especificamente, como ...

  1. ... permite múltiplas fontes?
  2. ... usar diretivas diferentes?
  3. ... usar várias diretivas?
  4. ... lidar com portas?
  5. ... lidar com protocolos diferentes?
  6. ... permitir file://protocolo?
  7. ... usar estilos, scripts e tags embutidos <style>e <script>?
  8. ... permitir eval()?

E finalmente:

  1. O que exatamente 'self'significa?
Schlaus
fonte

Respostas:

557

A Content-Security-Policymetatag permite reduzir o risco de ataques XSS , permitindo definir de onde os recursos podem ser carregados, impedindo que os navegadores carreguem dados de qualquer outro local. Isso torna mais difícil para um invasor injetar código malicioso no seu site.

Bati minha cabeça contra uma parede de tijolos tentando descobrir por que estava recebendo erros de CSP, um após o outro, e não parecia haver nenhuma instrução clara e concisa sobre como isso funciona. Então, aqui está minha tentativa de explicar brevemente alguns pontos do CSP, concentrando-me principalmente nas coisas que achei difíceis de resolver.

Por uma questão de brevidade, não escreverei a tag completa em cada amostra. Em vez disso, mostrarei apenas a contentpropriedade, portanto, uma amostra que diz content="default-src 'self'"significa isso:

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

1. Como permitir várias fontes?

Você pode simplesmente listar suas fontes após uma diretiva como uma lista separada por espaço:

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

Observe que não há aspas em torno de outros parâmetros além dos especiais , como 'self'. Além disso, não há dois pontos ( :) após a diretiva. Apenas a diretiva e, em seguida, uma lista de parâmetros separados por espaço.

Tudo abaixo dos parâmetros especificados é implicitamente permitido. Isso significa que no exemplo acima, essas fontes seriam válidas:

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

Estes, no entanto, não seriam válidos:

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

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

2. Como usar diretivas diferentes, o que cada uma delas faz?

As diretivas mais comuns são:

  • default-src a política padrão para carregar javascript, imagens, CSS, fontes, solicitações AJAX, etc.
  • script-src define fontes válidas para arquivos javascript
  • style-src define fontes válidas para arquivos css
  • img-src define fontes válidas para imagens
  • connect-srcdefine destinos válidos para XMLHttpRequest (AJAX), WebSockets ou EventSource. Se for feita uma tentativa de conexão com um host que não é permitido aqui, o navegador emulará um 400erro

Existem outros, mas esses são os de que você provavelmente precisará.

3. Como usar várias diretivas?

Você define todas as suas diretivas dentro de uma metatag encerrando-as com ponto-e-vírgula ( ;):

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

4. Como lidar com portas?

Tudo, exceto as portas padrão, precisa ser permitido explicitamente, adicionando o número da porta ou um asterisco após o domínio permitido:

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

O acima resultaria em:

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

Como mencionei, você também pode usar um asterisco para permitir explicitamente todas as portas:

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

5. Como lidar com diferentes protocolos?

Por padrão, apenas protocolos padrão são permitidos. Por exemplo, para permitir WebSockets, ws://você terá que permitir explicitamente:

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

6. Como permitir o protocolo de arquivo file://?

Se você tentar defini-lo como tal, não funcionará. Em vez disso, você o permitirá com o filesystemparâmetro:

content="default-src filesystem"

7. Como usar scripts embutidos e definições de estilo?

A menos que seja explicitamente permitido, você não pode usar definições de estilo embutido, codificar dentro de <script>tags ou em propriedades de tags como onclick. Você os permite assim:

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

Você também precisará permitir explicitamente imagens codificadas em linha de base64:

content="img-src data:"

8. Como permitir eval()?

Tenho certeza de que muitas pessoas diriam que não, pois 'eval é mau' e a causa mais provável para o fim iminente do mundo. Essas pessoas estariam erradas. Certamente, você pode definitivamente fazer grandes furos na segurança do seu site com avaliação, mas possui casos de uso perfeitamente válidos. Você só precisa ser esperto ao usá-lo. Você permite assim:

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

9. O que exatamente 'self'significa?

Você pode 'self'significar host local, sistema de arquivos local ou qualquer coisa no mesmo host. Isso não significa nada disso. Significa fontes que possuem o mesmo esquema (protocolo), mesmo host e mesma porta que o arquivo em que a política de conteúdo está definida. Servindo seu site por HTTP? Não há https para você, a menos que você o defina explicitamente.

Eu usei 'self'na maioria dos exemplos, pois geralmente faz sentido incluí-lo, mas não é de forma alguma obrigatório. Deixe de fora se não precisar.

Mas espere um minuto! Não posso simplesmente usar content="default-src *"e acabar com isso?

Não. Além das óbvias vulnerabilidades de segurança, isso também não funcionará como você esperaria. Embora alguns documentos afirmem que isso permite algo, isso não é verdade. Ele não permite inline ou avaliações; portanto, para realmente tornar seu site ainda mais vulnerável, você usaria o seguinte:

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

... mas eu confio que você não vai.

Leitura adicional:

http://content-security-policy.com

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

Schlaus
fonte
6
Ótimo post. Uma coisa: não é óbvio o que acontece quando várias diretivas são especificadas; as configurações de style-src no exemplo 3 têm precedência sobre default-src? etc ...
faixa0
29
Então, para permitir tudo, tudo, tudo o que o conteúdo seriadefault-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; img-src * data: 'unsafe-inline'; connect-src * 'unsafe-inline'; frame-src *;
Arnold Roa
8
É importante saber que content="default-src * 'unsafe-inline' 'unsafe-eval'"é necessário fazer com que alguns aplicativos Angular funcionem.
flanger001
2
@Mahesh Esse "blog" está cheio de postagens copiadas do SO. Parece improvável que tantos usuários de SO copiem conteúdo de um blogueiro desconhecido - eu sei que não.
Schlaus 17/07/19
2
Nota breve sobre connect-srce caminhos: as barras finais são obrigatórias se você deseja incluir um subcaminho inteiro. Por exemplo: o arquivo http://foo.com/files/bar.txtserá bloqueado se a fonte é http://foo.com/files, mas servido quando éhttp://foo.com/files/
Griddo
15

APACHE2 MOD_HEADERS

Você também pode ativar o Apache2 mod_headers, no Fedora já está ativado por padrão, se você usar o Ubuntu / Debian, habilite-o assim:

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

No Ubuntu / Debian, você pode configurar os cabeçalhos no arquivo /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: Esta é a parte inferior do arquivo, apenas as três últimas entradas são configurações de CSP.

O primeiro parâmetro é a diretiva, o segundo são as fontes a serem listadas em branco. Adicionei o Google Analytics e um servidor de anúncios, que você pode ter. Além disso, descobri que, se você tiver aliases, por exemplo, www.example.com e example.com configurados no Apache2, deverá adicioná-los também à lista branca.

O código embutido é considerado prejudicial, você deve evitá-lo. Copie todos os javascripts e css para separar arquivos e adicione-os à lista branca.

Enquanto você está nisso, você pode dar uma olhada nas outras configurações de cabeçalho e instalar mod_security

Leitura adicional:

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

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

Erik Hendriks
fonte
2
Consegui adicionar essas mesmas diretrizes ao meu arquivo .htaccess, pois não tenho a capacidade de editar as configurações do Apache no meu host compartilhado. Encontrei excelentes ferramentas para ajustar essas configurações em report-uri.io/home/tools .
Michael McGinnis 13/10
Existe alguma maneira de resolver esse problema com o tomcat 7. Tentei adicionar filtros e não funcionou.
Elshan #
0

Não se esqueça do font-src, ele funciona da mesma forma que qualquer outro, mas se você usar fontes carregadas de outras origens - adicione-as à metatag

Mikhail Andrianov
fonte