technical

Bloqueia o clickjacking com frame-ancestors

O MetricSpot procura X-Frame-Options ou CSP frame-ancestors. Estes cabeçalhos impedem que atacantes incorporem o teu site num iframe oculto para enganar utilizadores a clicar.

O que esta verificação faz

Inspeciona os cabeçalhos da resposta à procura de um dos seguintes:

  • X-Frame-Options: DENY ou X-Frame-Options: SAMEORIGIN
  • Content-Security-Policy: frame-ancestors 'none' ou frame-ancestors 'self'

A verificação falha quando nenhum está presente e um atacante poderia incorporar a tua página num iframe oculto num site malicioso.

Porque é importante

Clickjacking é um ataque de UI-redress: o atacante carrega o teu site num iframe transparente sobreposto a um botão que parece inofensivo (“iPad grátis! Clica aqui”). O clique do utilizador aterra, na verdade, num botão real dentro do teu iframe — a enviar um pagamento, a mudar uma palavra-passe, a transferir dinheiro.

  • O ataque funciona contra qualquer sessão autenticada. Se um utilizador tem sessão iniciada no teu site noutro separador, o iframe herda os cookies da sessão, pelo que o clique é executado em nome desse utilizador.
  • Já foi usado na prática contra sites de banca, redes sociais e dashboards de administração. Fluxos OAuth e páginas de inscrição em 2FA já foram atingidos.
  • A correção é um único cabeçalho. Os navegadores recusam-se a renderizar a tua página num iframe quando o cabeçalho está presente — o ataque deixa de ser possível.

A proteção contra framing é a mitigação mais barata em segurança web: um cabeçalho de resposta por página, zero alterações de código, zero custo de desempenho.

Como corrigir

Escolhe um dos dois mecanismos. Os navegadores modernos preferem o frame-ancestors do CSP; o X-Frame-Options é o cabeçalho legado que também funciona em navegadores antigos. Envia ambos para cobertura máxima — não entram em conflito.

Negar todo o framing (recomendado para sites que não devem ser incorporados):

Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENY

Permitir framing apenas a partir da tua própria origem:

Content-Security-Policy: frame-ancestors 'self'
X-Frame-Options: SAMEORIGIN

Permitir framing a partir de origens específicas de confiança (apenas o CSP suporta isto — X-Frame-Options não consegue listar vários domínios):

Content-Security-Policy: frame-ancestors 'self' https://partner.example.com

nginx:

add_header Content-Security-Policy "frame-ancestors 'none'" always;
add_header X-Frame-Options "DENY" always;

A flag always é crítica — sem ela, o nginx omite o cabeçalho em respostas de erro.

Apache:

Header always set Content-Security-Policy "frame-ancestors 'none'"
Header always set X-Frame-Options "DENY"

Caddy:

header {
  Content-Security-Policy "frame-ancestors 'none'"
  X-Frame-Options "DENY"
}

Cloudflare — Rules → Transform Rules → Modify Response Header, adiciona ambos os cabeçalhos globalmente. Ou usa o produto Page Shield se quiseres controlo ao nível do WAF.

Next.js (next.config.js):

module.exports = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [
          { key: "Content-Security-Policy", value: "frame-ancestors 'none'" },
          { key: "X-Frame-Options", value: "DENY" },
        ],
      },
    ];
  },
};

Express:

import helmet from "helmet";
app.use(helmet.frameguard({ action: "deny" }));
app.use(
  helmet.contentSecurityPolicy({
    directives: { frameAncestors: ["'none'"] },
  })
);

Testa:

curl -sI https://teudominio.com/ | grep -iE 'frame'

Espera ambos os cabeçalhos, ou pelo menos o frame-ancestors. Depois tenta incorporar num iframe localmente para confirmar que o navegador recusa.

Perguntas frequentes

Devo negar todo o framing ou apenas same-origin?

Por defeito, usa frame-ancestors 'none' e só relaxa se precisares ativamente de incorporar as tuas páginas. A maioria dos sites de marketing, dashboards de administração e aplicações nunca devem ser colocados em frames — e os fornecedores OAuth (Google, Apple, Stripe) que genuinamente precisam de framing têm fluxos de incorporação bem definidos que não exigem relaxar o teu CSP.

E quanto a X-Frame-Options: ALLOW-FROM?

Obsoleto e não suportado em Chrome e Firefox. Usa Content-Security-Policy: frame-ancestors em vez disso — aceita múltiplas origens e funciona em todos os navegadores modernos.

Isto parte o Google PageSpeed Insights ou alguma ferramenta?

Não. Essas ferramentas buscam a página diretamente, não num iframe. O cabeçalho só afeta a incorporação em iframes.

Fontes

Última atualização 2026-05-11