Desenvolvimento

5 out, 2016

Impeça ataques do tipo cross-site timing com cookies SameSite

Publicidade

Vamos dizer que nós temos um cliente que pode iniciar uma solicitação de rede para qualquer URL na web, mas a resposta é opaca e não pode ser inspecionada. O que podemos aprender sobre o cliente ou a resposta? Como se constata, armado com um pouco de paciência e estatísticas rudimentares, “um monte”.

Por exemplo, a duração de busca é uma combinação do tempo de rede que leva para atingir o tempo do servidor, o tempo de processamento do servidor, e a resposta de rede. Cada passo e todas as etapas “vazam” informações, tanto sobre o cliente quanto o servidor.

Por exemplo, se a duração total é muito pequena (digamos, <10ms), então podemos razoavelmente inferir que poderíamos estar falando com um cache local, o que significa que o cliente já havia buscado esse recurso. Alternativamente, se a duração é um pouco maior (digamos, <50ms), então podemos razoavelmente supor que o cliente está em uma rede de baixa latência (por exemplo, 4G ou Wi-Fi). Podemos também acrescentar dados aleatórios para a URL para torná-la única e descartar os vários caches HTTP ao longo do caminho. A partir daí, podemos tentar fazer mais pedidos para o servidor e observar como a alteração na duração muda a chance de inferência no tempo de processamento do servidor e/ou nas respostas maiores a serem enviadas para o cliente.

Se nós formos realmente inteligentes, também podemos usar as propriedades do transporte de rede como CWND roundtrips induzidas no TCP (veja TCP Slow Start), e outras peculiaridades da configuração de rede local, como sinais adicionais para inferir propriedades (por exemplo tamanho) da resposta – veja TIME, ataques HEIST. Se a resposta é comprimida e também acontece espelhamento dos dados apresentados, então há também a possibilidade de usar um ataque de compressão oracle (ver BREACH) para extrair dados a partir da resposta.

Em teoria, o cliente pode tentar frustrar esses ataques, fazendo com que todas as operações levem um tempo constante, mas, na realidade, essa solução não é prática nem aceitável devido à experiência do usuário e às implicações de tal estratégia de desempenho. Injetar atrasos aleatórios não é algo muito melhor, uma vez que contém implicações semelhantes.

Rede termodinâmica

Todo e cada passo no processo de busca – do cliente gerando uma requisição e colocando no cabo, a mudança da rede para o servidor, o tempo de processamento do servidor, as propriedades de resposta, e a rede devolvendo de volta para o cliente – “vaza” informações sobre as propriedades do cliente, rede, servidor, e a resposta. Isso não é um erro; é um fato da vida. Tomando emprestada uma explicação de nossos amigos físicos: colocando um sistema para lidar com valores, extraindo energia a partir dele, o qual podemos então medir e discutir para aprender fatos sobre o referido sistema.

Olhos vidrados ainda? A implicação prática é que, se as precauções necessárias do servidor estiverem em falta, o uso das técnicas acima pode revelar informações privadas sobre você e seu relacionamento com esse servidor – por exemplo, status de login, afiliação de grupo e muito mais. Isso requer um pouco mais de explicação…

Os perigos de cross-origem credenciados, pedidos “no-cors”

O fato de que podemos usar informações side-channel, tais como a duração de uma busca, para extrair informação sobre a resposta não é, por si, toda útil. Afinal, se eu der a você uma URL, você pode apenas usar seu próprio cliente HTTP para buscá-la e inspecionar os bytes sobre o fio. No entanto, o que faz com que seja perigoso é se você puder cooptar o meu cliente (meu navegador) para fazer uma solicitação autenticada em meu nome e inspecionar a resposta (opaca) que contém o meu conteúdo privado. Então, mesmo que você não possa acessar a resposta diretamente, pode observar qualquer uma das propriedades acima mencionadas da busca e extrair informações privadas sobre meu cliente e a resposta. Vamos tornar isso concreto…

  1. Eu gostaria de visitar kittens.com, onde eu tenho uma conta para fixar minhas imagens favoritas:
    1. O mecanismo de autenticação é um formulário de login com todas as precauções necessárias (tokens CSRF etc.);
    2. Uma vez autenticado, o servidor define um cookie HTTP específico para kittens.com com um token particular que é usado para autenticar-me em visitas futuras.
  2. Alguém mais me convence a visitar shady.com para ver mais fotos de gatinhos …
    1. Enquanto eu estou me divertindo com as fotos dos gatinhos em shady.com, a página emite uma requisição em background sobre o meu interesse em kittens.com com o objetivo de tentar aprender alguma coisa sobre o meu status no referido site.

Como é que shady.com faz um pedido credenciado? Um elemento de imagem simples é suficiente:

<img src="https://kittens.com/favorites" alt="Yay authenticated kittens!">

<!-- Image element is not the only mechanism with this behavior, others
     include script, object, video, etc. Also, there is JavaScript... -->

<script>
  var img = new Image();
  img.src = "https://kittens.com/favorites"
</script>

O navegador processa o elemento de imagem, inicializa um pedido para https://kittens.com/favorites, atribui meus cookies HTTP associados com kittens.com, e despacha o pedido. O servidor de destino (kittens.com) vê um cookie de autenticação válido e obedientemente envia de volta a resposta HTML contendo meus gatinhos favoritos. Claro, a tag de imagem vai engasgar com o HTML e irá disparar um retorno de chamada de erro, mas isso não importa, porque, embora não possamos inspecionar a resposta, ainda podemos aprender muito observando o momento do fluxo autenticado solicitação-resposta.

Com o benefício de algumas décadas de experiência, e se estávamos reconstruindo a plataforma web a partir do zero, nós provavelmente não iríamos permitir solicitações autenticadas como “no-CORS” sem CORS explícitas opt-in a partir do servidor, assim como o que fazemos hoje para XMLHttpRequest e Fetch API. Infelizmente, isso seria uma grande mudança de ruptura, assim, isso não está em jogo. No entanto, nem tudo está perdido também, porque kittens.com pode implantar lógica adicional para se proteger, e aos seus usuários, contra ataques cross-origin.

Neste artigo, nós estamos focando em ataques cross-site timing: por que eles existem e como mitigá-los. No entanto, note que essa é uma subclasse do maior tipo de ataque Cross-Site Request Forgery (CSRF), que pode causar o naufrágio no seu site e a destruição dos dados dos seus usuários. A boa notícia é: os atenuantes são os mesmos.

Declare seus cookies como “same-site”

A questão central é que o navegador atribui a origem dos alvos dos cookies nos pedidos “no-cors“, independentemente da origem que inicia o pedido. Em teoria, o alvo original poderia olhar para o cabeçalho de referência, mas o atacante poderia esconder a origem, por exemplo iniciando via no-referrer policy. Da mesma forma, o cabeçalho de origin é enviado somente em solicitações CORS, de modo que também nãos nos ajuda. No entanto, os cookies SameSite nos dão o comportamento exato que queremos:

Aqui, nós atualizamos [RFC6265] com uma estratégia de mitigação simples que permite que os servidores declarem determinados cookies como “same-site”, o que significa que não devem ser anexados às solicitações “cross-site”… Note que o mecanismo descrito aqui é compatível com a sintaxe existente de cookies. Servidores podem servir esses cookies para todos os agentes do usuário; aqueles que não suportam o atributo “SameSite” irão simplesmente armazenar um cookie que está ligado a todas as solicitações pertinentes, assim como fazem hoje.

Cookies SameSite têm dois modos: “strict” e “lax”. No modo strict, os cookies não são enviados em navegações de nível superior, o que oferece uma proteção forte, mas requer algumas considerações adicionais de implementação. No modo lax, os cookies são enviados para navegações de nível superior, por exemplo, navegações iniciadas por elementos <a>, window.open (), <link rel = prerender>, que oferecem uma proteção razoável. Leia a especificação IETF, que fornece uma boa orientação.

200 OK HTTP/1.1
...
Set-Cookie: SID=31d4d96e407aad42; SameSite=Strict

Usando nosso exemplo acima, se kittens.com definir o sinalizador SameSite em seu cookie de autenticação, a solicitação de imagem iniciada por shady.com não conterá o cookie de autenticação devido à incompatibilidade do início da origem e a origem que define o cookie, e isso resultaria numa resposta genérica não autenticada, por exemplo, um redirecionamento para uma página de login. Se você for kittens.com, permitirá que os cookies SameSite sejam um no-brainer.

De modo mais geral, se o seu site ou serviço não fornecer intencionalmente recursos cross-origin (por exemplo, widgets incorporáveis, plugins do site etc.), então você deve usar cookies SameSite como padrão.

Cookies SameSite são suportados no Chrome (desde M51) e no Opera 39, e estão sob consideração no Firefox. Vamos esperar que os outros navegadores sigam rapidamente. Por último, mas não menos importante, vale a pena notar que você também pode, como um usuário, bloquear cookies de terceiros no seu navegador para se proteger contra esse tipo de ataque cross-origin.

***

Ilya Grigorik faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://www.igvita.com/2016/08/26/stop-cross-site-timing-attacks-with-samesite-cookies/.