Aprenda / Segurança web

FundamentosAula 3 de 1617 min0% da trilha

Os atributos de cookie que decidem sua segurança

HttpOnly, Secure e SameSite parecem detalhe de configuração — são, na prática, a diferença entre uma sessão protegida e uma sequestrável.

A lição anterior mostrou Set-Cookie: sessao=abc123; HttpOnly sem parar pra explicar cada parte depois do valor. Esses atributos não são cosmético — cada um fecha uma porta de ataque específica, e um cookie de sessão emitido sem eles está, na prática, exposto a pelo menos um dos três problemas que esta lição cobre.

Cookie de sessão vulnerável
Set-Cookie: sessao=abc123
Cookie de sessão protegido
Set-Cookie: sessao=abc123; HttpOnly; Secure; SameSite=Lax

HttpOnly — tirando o cookie do alcance do JavaScript

Por padrão, qualquer script rodando na página consegue ler cookies através de document.cookie. Isso inclui scripts legítimos seus — mas também inclui um script injetado por um ataque de XSS (lição 7). Se o cookie de sessão está ali, legível, um XSS bem-sucedido consegue roubá-lo e mandar pra um servidor do atacante, que passa a se autenticar como a vítima sem precisar de senha nenhuma.

dentro do console do navegador
document.cookie

HttpOnly instrui o navegador a nunca expor aquele cookie específico pra JavaScript — ele continua sendo enviado normalmente nas requisições HTTP (é isso que faz a sessão funcionar), só não pode ser lido por código rodando na página. Repare que isso não impede o XSS de acontecer; reduz o estrago se ele acontecer, tirando o cookie de sessão da lista de coisas que um script malicioso consegue roubar diretamente.

Secure — nunca em texto puro na rede

Secure diz ao navegador pra só enviar aquele cookie em conexões HTTPS — nunca em HTTP puro. Sem esse atributo, se por qualquer motivo (um link antigo, um redirecionamento mal configurado) uma requisição sair em HTTP, o cookie de sessão viaja sem criptografia nenhuma pela rede, legível por qualquer um no mesmo Wi-Fi ou no mesmo provedor — exatamente o cenário de interceptação (MITM) aprofundado na lição 14.

SameSite — controlando pedidos vindos de outro site

O atributo mais sutil dos três. Ele controla se o cookie é enviado quando a requisição parte de um site diferente daquele que emitiu o cookie — por exemplo, um formulário hospedado em site-malicioso.com enviando uma requisição pra banco.com. Sem restrição nenhuma, o navegador manda o cookie de sessão do banco.com mesmo numa requisição disparada por outro site, porque "reenviar cookie do domínio automaticamente" não sabe distinguir uma navegação legítima de um ataque. Isso é a base do CSRF, coberto de verdade na lição 8 — aqui fica só o mecanismo de defesa:

os três valores possíveis
SameSite=Strict  → o cookie NUNCA é enviado em requisição originada de outro site,
                    nem clicando num link vindo de fora (mais seguro, mas quebra alguns
                    fluxos legítimos, tipo abrir um link de e-mail e já chegar logado)

SameSite=Lax     → o cookie é enviado ao NAVEGAR pra o site (clicar num link), mas não
                    em requisições em segundo plano (POST de formulário, fetch) disparadas
                    por outro site — o equilíbrio padrão hoje na maioria dos frameworks

SameSite=None    → o cookie é enviado sempre, mesmo cross-site — precisa vir acompanhado
                    de Secure obrigatoriamente, e só faz sentido pra casos específicos
                    (ex.: um widget embutido em outros sites)

Repare a ordem de risco: None sem outra defesa deixa a porta do CSRF praticamente aberta; Lax (o padrão da maioria dos navegadores modernos quando nada é especificado) já bloqueia o cenário mais comum de ataque, o POST disparado silenciosamente por outro site.

Exercício

Um cookie de sessão está configurado como Set-Cookie: sessao=xyz; Secure (sem HttpOnly e sem SameSite). Um campo de comentário do site tem uma falha de XSS armazenado. Explique por que esse cookie específico ainda está em risco, mesmo com Secure presente, e o que faltou pra reduzir esse risco.

Quiz rápido

O que o atributo HttpOnly de um cookie impede especificamente?
Por que SameSite=Lax já bloqueia o cenário mais comum de CSRF (um POST de formulário disparado por outro site), mesmo sem ser tão restritivo quanto Strict?