HTTP: Cookies

O protocolo HTTP é do tipo sem estado (stateless, no original em inglês). Isso significa que a cada ciclo requisição-processamento-resposta nenhuma informação fica armazenada, nem no lado cliente nem no lado servidor.

Em aplicações para web essa característica do protocolo HTTP normalmente é um problema pois há a noção de usuário. Assim, cookies são usados para:

  • gerenciamento de sessão. Exemplo: carrinho de compras que armazena os itens que usuário deseja comprar enquanto está navegando pelas páginas da aplicação.
  • personalização. Armazena as preferências do usuário.

  • tracking. Armazena o comportamento do usuário (páginas visitadas, por exemplo).

Funcionamento

Ao requisitar uma página, o servidor pode incluir na resposta HTTP, além da página, uma série de cookies que nada mais são do que duplas chave-valor. Estes cookies são então armazenados pelo navegador. Na próxima requisição para o mesmo host os cookies serão automaticamente enviados.

O servidor define um cookie adicionando na resposta o cabeçalho Set-Cookie.

O navegador envia um cookie adicionando na requisição o cabeçalho Cookie.

Segurança

Cookies, por definição, contêm informações que só dizem respeito ao usuário e à aplicação. As informações devem, portanto, serem protegidas.

Tempo de Vida (Expires ou Max-Age)

Por quanto tempo um navegador deve armazenar um cookie? Cabe ao servidor definir. O cabeçalho Set-Cookie pode incluir uma data de validade, um prazo de validade (em segundos) ou nenhuma informação sobre a validade. Neste caso, o cookie é removido assim que o navegador é fechado. O mais recomendado é definir uma data ou um prazo de validade, o mais breve possível.

Exemplo:

 Set-Cookie: id=leandro; Max-Age=600

Secure

Com este atributo o cookie só será enviado caso a requisição seja do tipo HTTPS.

Exemplo:

 Set-Cookie: id=leandro; Max-Age=600; Secure

HttpOnly

Com este atributo, um cookie não é acessível via script JavaScript. Sem ele, o código abaixo tem acesso ao cookie.

\\ obtém os cookies armazenados na página
let cookie = document.cookie

Armazenamento de Dados

Os cookies, originalmente, foram pensados para armazenar dados no lado cliente de uma aplicação para web. Há, no entanto, pelo menos dois grandes problemas com esta abordagem:

  1. Cookies podem armazenar relativamente pouca informação. O padrão é armazenar no máximo 4KB.
  2. Cookies são intrinsecamente inseguros pois qualquer pessoa com acesso ao navegador tem condições de olhar e copiar as informações contidas no cookie.

Para tentar minimizar os problemas acima, recomenda-se que:

  • cookies armazenem, pelo menor tempo possível, apenas um identificador que represente a ideia de sessão vinculada ao usuário. Os dados, por exemplo, identificação do usuário e seus itens no carrinho de compras, devem ser armazenados no lado servidor
  • codificar as informações do cookie usando, por exemplo, JSON Web Tokens (JWT). Assim, apenas o servidor tem condições de acessar as informações.
  • usar a API Web Storage para armazenar os dados.

CSRF

Talvez o principal problema de segurança relacionado aos cookies é a ameaça Cross-Site Request Forgery (CSRF) (em português, Requisição Falsificada Entre Sites).

A ameaça funciona assim:

  1. Um usuário acessa uma aplicação para web da sua confiança (por exemplo seu home banking) e, após autenticado, recebe um cookie que representa um identificador único do usuário. Toda requisição enviada para a aplicação conterá, automaticamente, esse cookie. O lado servidor da aplicação reconhece a requisição como sendo legítima pois ela contém o cookie esperado e processa a requisição (por exemplo, uma transferência de dinheiro para outra conta).
  2. Enquanto o usuário está usando sua aplicação de confiança, ele abre uma segunda aba no seu navegador e acessa uma página HTML de um site malicioso. Esta página, quando carregada, dispara uma requisição HTTP cuja URL é igual à requisição feita pela aplicação de confiança. A esta requisição, naturalmente, é anexado o cookie que o navegador armazenou quando o usuário acessou a aplicação de confiança. A requisição é chamada de falsificada (forgery request) pois não tem origem na aplicação de confiança (que emite requisições legítimas).

  3. Do ponto de vista do lado servidor da aplicação de confiança, no entanto, não há como distinguir uma requisição legítima e uma falsificada. A aplicação considera que uma requisição é legítima se ela contiver um cookie válido. E ambas contém um cookie válido.

Prevenção contra CSRF

Um ataque do tipo CSRF funciona baseado nos seguinets pressupostos:

  • cookies são enviados automaticamente pelos navegadores. O código malicioso, que envia a requisição falsificada, não precisa nem saber que o cookie existe.
  • a aplicação que recebe a requisição analisa apenas o cookie para saber se ela é válida.

Assim, dentre diversas técnicas para evitar o ataque, uma delas consiste em adicionar na requisição um token secreto (que o código malicioso não conseguirá adivinhar), único e não previsível (aleatório). O lado servidor, ao receber a requisição analisa o cookie para garantir que há um usuário autenticado e também este token secreto que deve ser o mesmo enviado pela aplicação.

Leitura Obrigatória
Cookies
Definição de CSRF
Post sobre CSRF
Leitura Sugerida
Post sobre Cookies e Segurança
Sobre Web Storage API

results matching ""

    No results matching ""