Cabeçalhos de segurança: HSTS, CSP, X-Frame-Options e outros
· 7 min de leitura
O backend é uma fortaleza, mas metade da defesa está no navegador. HSTS, CSP e outros cabeçalhos bloqueiam XSS, clickjacking e MITM - e são grátis.
Porque importam
Uma aplicação pode ser perfeitamente segura no backend e ainda assim continuar vulnerável a ataques do lado do navegador: cross-site scripting (XSS), clickjacking, protocol downgrade, MIME confusion. Os cabeçalhos de segurança levam a defesa para o próprio navegador.
Strict-Transport-Security (HSTS)
Força HTTPS para todas as visitas futuras. Após a primeira visita por HTTPS, o navegador memoriza o domínio e reescreve por si mesmo qualquer link http:// para https://, mesmo que o utilizador clique num link errado.
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
max-age=63072000= válido 2 anosincludeSubDomains= a regra aplica-se também a todos os subdomínios; força HTTPS em todo o lado, por isso um subdomínio a correr só por HTTP, p. ex.staging.example.com, fica inacessível no navegadorpreload= permite a inclusão na lista HSTS preload integrada no Chrome / Firefox / Safari
Atenção:
Remover um HSTS com preload da lista demora 6+ meses. Não adiciones preload antes de verificares que o HTTPS funciona de forma estável em todos os subdomínios.
Content-Security-Policy (CSP)
O cabeçalho mais poderoso, mas também o mais difícil de configurar. Faz whitelist de onde o navegador pode carregar scripts, estilos, imagens e iframes. Sem CSP, um atacante que consiga injetar uma tag <script> pode executar qualquer JS; com CSP, apenas código de fontes aprovadas.
Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-...'; img-src 'self' data: https://cdn.example.com; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'
Diretivas comuns:
default-src 'self'= por defeito, permitir apenas recursos do meu próprio domínioscript-src= fontes JS (para scripts inline indica um hash ou nonce)style-src= fontes CSSimg-src= imagensconnect-src= AJAX, WebSocket, EventSourceframe-ancestors 'none'= ninguém pode incorporar a página num iframe (melhor que X-Frame-Options)report-uri /csp-report= o navegador envia um JSON em cada violação (apanha-la no backend e fazes log)- Nota:
report-uriestá hoje deprecated - os navegadores com suporte areport-toignoram-no. A forma moderna é a diretivareport-tomais um cabeçalhoReporting-Endpointsseparado; deixareport-uriapenas como fallback para o Firefox, que ainda não suportareport-to.
X-Frame-Options
Alternativa mais antiga ao frame-ancestors. Previne o clickjacking, em que o atacante incorpora a tua página como iframe e a cobre com botões invisíveis.
X-Frame-Options: DENY
Valores: DENY (ninguém), SAMEORIGIN (apenas o meu domínio), ALLOW-FROM uri (deprecated).
X-Content-Type-Options
X-Content-Type-Options: nosniff
Desliga o MIME sniffing, de modo que o navegador respeita o Content-Type que o servidor devolveu. Sem isso, um atacante pode fazer upload de um ficheiro com tipo errado (ex. uma imagem que é na realidade HTML com script) e o navegador pode executá-lo como página web.
Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
Controla quanta informação sobre a página anterior o navegador envia no cabeçalho Referer ao clicar. O valor por defeito nos navegadores modernos já é strict-origin-when-cross-origin, mas definir o cabeçalho de forma explícita garante um comportamento consistente.
Permissions-Policy
Desliga as APIs de que não precisas, como câmara, microfone, GPS e geolocalização. Um atacante que explore XSS não pode pedir estas APIs.
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Configuração prática em nginx
server {
listen 443 ssl http2;
server_name example.com;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
# omitimos preload aqui de propósito - adiciona-o só quando tiveres 100% de certeza (ver a armadilha do preload acima)
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# CSP é extensa - define-a conforme a tua aplicação
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
}
A chave é always - sem ele, o nginx omite os cabeçalhos nas respostas de erro (4xx, 5xx).
Auditoria do estado atual
O mais fácil é uma ferramenta online. O nosso header check mostra-te que cabeçalhos faltam e quais estão errados. Para uma auditoria aprofundada, o securityheaders.com dá ainda uma pontuação A-F.
Conclusão
Os cabeçalhos de segurança são um dos melhores investimentos em segurança na relação esforço-ganho: tipicamente meia hora de setup no reverse proxy contra uma categoria inteira de ataques do lado do navegador. Uma auditoria uma vez por semestre no âmbito da manutenção regular é um mínimo razoável.
Auditoria gratuita de security headers
Sem registo, resultado em três segundos.
Experimente o ePulz.io grátis - 7 dias sem cartão de crédito.
Criar conta