Políticas simples de segurança de conteúdo para defesa contra ataques XSS

 

Nas últimas semanas, abordamos no blog vários cabeçalhos HTTP relacionados à segurança, mas o principal de todos eles é o Content-Security-Policy(CSP). O chefe, tanto pelo nível de proteção que oferece quanto, infelizmente, pela dificuldade de implementá-lo corretamente na primeira vez. Assim como todas as regras de gerenciamento de tráfego do flightPATH que discutimos recentemente, nós mesmos as usamos para proteger o site da edgeNEXUS e seus visitantes.

Fizemos o trabalho duro e sentimos a dor para que você não precise fazer isso, mas não há como negar que é necessário pensar e planejar um pouco antes da implementação. No entanto, vale a pena. O conceito por trás desse cabeçalho é bastante simples e igualmente poderoso. Em poucas palavras, você o usa para especificar as origens permitidas do conteúdo que pode ser carregado no seu site. Isso oferece uma forte proteção contra vários ataques de injeção de código predominantes na Internet cada vez mais dinâmica de hoje, como XSS (Cross Site Scripting) e Clickjacking.

Os tipos de conteúdo que podem ser controlados incluem: JavaScript, CSS (sim, o CSS pode ser perigoso), quadros HTML, fontes, imagens e objetos incorporáveis, como applets Java. É ótimo ter tantas opções, mas é aí que surge a dificuldade. Os sites atuais (inclusive o nosso) contêm uma infinidade desses tipos de conteúdo de várias fontes, e identificar e contabilizar todos eles em uma política pode ser um grande esforço.

Antes de entrarmos nesse assunto, vamos dar uma olhada nos elementos do valor do cabeçalho e na aparência de uma política. Como você verá, ela é essencialmente uma longa lista de tipos de conteúdo (todos terminando com -src neste exemplo) e as fontes permitidas para cada tipo. Juntos, eles são conhecidos como diretivas de política.

default-src “self” data:; script-src “self” “unsafe-inline”; connect-src “self”; img-src “self” data:; style-src “self” “unsafe-inline” data:; font-src “self” data:; child-src “self”

Há outros tipos de conteúdo que podemos considerar, mas as diretrizes mostradas acima são as mais importantes (em nossa opinião, com base no risco e na prevalência). Aqui você encontra os detalhes sobre o conteúdo a que cada uma delas se refere;

  • default-src – Valores padrão para a maioria dos tipos de conteúdo (mas não todos) se não forem especificados posteriormente
  • script-src – Fontes permitidas para scripts (incluindo JavaScript)
  • connect-src – Fontes permitidas para conexões (como WebSockets e EventSource usados, por exemplo, com aplicativos de bate-papo)
  • img-src – Fontes permitidas para imagens
  • style-src – Fontes permitidas para CSS
  • font-src – Fontes permitidas para fontes
  • child-src – Fontes permitidas para quadros e iframes

Esses tipos de conteúdo e seus valores são separados uns dos outros (delimitados) por um ponto e vírgula. Cada tipo pode ter um ou mais dos seguintes valores;

  • “none” – não permite esse tipo de conteúdo
  • “self” – permite esse tipo de conteúdo se ele for originado diretamente deste site (mas não de subdomínios)
  • “unsafe-inline” – permite CSS e JavaScript inline (infelizmente, isso é muito comum)
  • dados: – permitir fontes de dados em linha (normalmente usadas para fornecer fontes e imagens em linha para melhorar o desempenho)
  • https: – permite apenas esse tipo de conteúdo em HTTPS
  • “unsafe-eval” – permite a análise de texto usando métodos potencialmente perigosos que podem resultar na execução de código
  • domain-name – permite esse tipo de conteúdo se ele for originário do domain-name especificado (em outras palavras, um domínio remoto) – isso pode ser usado várias vezes
  • * – qualquer domínio

Um espaço simples é usado para delimitar cada valor. As aspas simples ‘ são necessárias, a menos que o valor seja um nome de domínio. Observe que as extensões e os plug-ins do navegador estão isentos, pois são considerados seguros porque têm a confiança do usuário (que os instalou, afinal).

Tudo isso parece um tanto técnico e complexo, mas se você abordar uma etapa de cada vez, será muito rápido criar uma política. Vamos analisar rapidamente dois exemplos. Primeiro, vamos tentar um site interno simples servido por HTTP. Aqui está o que você precisa;

  • dados default-src “self”: – permitir conteúdo apenas de nosso próprio site, incluindo objetos inline
  • script-src “self” “unsafe-inline” – permite scripts de nosso próprio site, inclusive os inline
  • connect-src “self” – permite conexões de/para nosso próprio site
  • dados img-src “self”: – permitir imagens de nosso próprio site, incluindo as inline
  • style-src “self” “unsafe-inline” data: – permitir CSS de nosso próprio site, incluindo estilos inline
  • dados font-src “self”: – permite fontes de nosso próprio site, incluindo as inline

O valor completo do cabeçalho é razoavelmente curto:

default-src “self” data:; script-src “self” “unsafe-inline”; connect-src “self”; img-src “self” data:; style-src “self” “unsafe-inline” data:; font-src “self” data:

Segundo, um site protegido por SSL/TLS voltado para a Internet que usa o Google Analytics (GA), CSS em linha, fontes e imagens, CSS do seu site e imagens de vários outros sites. Vamos analisar o que você precisa, peça por peça (não é muito diferente);

  • default-src “self” data: https: – permite apenas o conteúdo de nosso próprio site, inclusive objetos embutidos, somente por HTTPS
  • script-src “self” “unsafe-inline” https: – permite scripts de nosso próprio site, inclusive os inline, somente por HTTPS
  • img-src “self” “unsafe-inline” \* https: – permite imagens de qualquer site, inclusive as inline do nosso, somente por HTTPS
  • style-src “self” “unsafe-inline” https: – permite somente CSS de nosso próprio site, inclusive os inline, somente por HTTPS
  • font-src “self” “unsafe-inline” https: – permite fontes somente de nosso próprio site, inclusive as inline, somente por HTTPS

Somando tudo isso, temos essa política um pouco mais longa:

default-src “self” data: https:; script-src “self” “unsafe-inline” *.google-analytics.com https:; img-src “self” “unsafe-inline” * https:; style-src “self” “unsafe-inline” https:; font-src “self” “unsafe-inline” https:

Eu diria que é bem fácil. No passado, o Google não era tão “amigável” com o CSP (esse valor de cabeçalho costumava ter pelo menos o dobro do comprimento), mas, felizmente, eles fizeram grandes progressos recentemente. Você notará que não foi necessário adicionar o domínio *.google-analytics.com ao script-src como um valor de tipo de conteúdo, pois o código deles é executado como um script em linha.

O ideal é que você crie uma política por página do seu site, pois os recursos carregados, sem dúvida, serão diferentes de acordo com a página, mas isso é bastante oneroso e é muito mais simples, mas ainda assim eficaz, criar uma política que abranja todas as fontes possíveis. A maioria dos exemplos em nossa página do GitHub adota essa abordagem, mas também há um exemplo se você quiser oferecer maior proteção a páginas específicas.

Para testar e solucionar problemas, recomendo que você use as Ferramentas do desenvolvedor do Google Chrome. Vá para o site em questão e pressione F12, clique em Rede, verifique se Desativar cache está marcado e recarregue a página. Todos os erros serão destacados claramente. Na parte inferior deste blog há uma tela do que você poderá ver se sua política estiver bloqueando o unsafe-inline e você estiver usando o Google Analytics; as mensagens de erro são muito úteis.

Ajuste sua política conforme necessário, enxágue e repita. O ideal é que você faça isso usando um serviço virtual de teste dedicado com a regra flightPATH que você está testando aplicada, mas que atenda ao mesmo site, apenas por meio de um IP virtual diferente para não afetar clientes reais enquanto estiver testando.

Como sempre acontece, a grande vantagem de usar um balanceador de carga é que só precisamos fazer isso em um local central para proteger todos os nossos servidores (e sites). Não precisamos depender de desenvolvedores ou de reconfigurações de servidores da Web. No balanceador de carga edgeNEXUS, basta importar um modelo de configuração automática do jetPACK e atribuir uma regra de tráfego flightPATH ao(s) serviço(s) virtual(is) que desejamos proteger (após as modificações adequadas).

A regra só adiciona o cabeçalho se ele não existir, portanto, funcionará mesmo quando nossos servidores da Web já o inserirem ou talvez só o insiram em páginas específicas. Essa regra deve fazer parte da configuração padrão do Virtual Service – você não tem nada a perder, seja qual for o site, embora, é claro, seja sempre recomendável fazer testes. Você pode fazer o download desse jetPACK e de muitos outros no site do Github da edgeNEXUS.

O flightPATH é um mecanismo de regras dinâmico e baseado em eventos desenvolvido pela edgeNEXUS para manipular e rotear de forma inteligente o tráfego IP, HTTP e HTTPS com balanceamento de carga. Ele é altamente configurável e poderoso, mas muito fácil de usar.

Vale a pena ler esses links relacionados se você quiser saber mais;

http://www.html5rocks.com/en/tutorials/security/content-security-policy/

https://developer.mozilla.org/en/docs/Web/Security/CSP/CSP_policy_directives

http://content-security-policy.com/

https://www.clickintelligence.co.uk/header-response-checker/

Nas últimas semanas, abordamos vários cabeçalhos HTTP relacionados à segurança no blog, mas o mais importante de todos é o Content-Security-Policy (CSP).

About Donna Toomey