technical

Bloquejar el clickjacking amb frame-ancestors

MetricSpot comprova X-Frame-Options o CSP frame-ancestors. Aquestes capçaleres impedeixen que un atacant incrusti el teu lloc en un iframe ocult per enganyar usuaris.

Què comprova aquesta auditoria

Inspecciona les capçaleres de resposta cercant una d’aquestes:

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

La comprovació falla quan cap de les dues hi és present i un atacant podria incrustar la teva pàgina en un iframe ocult en un lloc maliciós.

Per què importa

El clickjacking és un atac de redisseny d’interfície: l’atacant carrega el teu lloc en un iframe transparent superposat sobre un botó d’aspecte innocent (“iPad gratis! Fes clic aquí”). El clic de l’usuari acaba en un botó real del teu iframe, enviant un pagament, canviant una contrasenya, transferint diners.

  • L’atac funciona contra qualsevol sessió oberta. Si l’usuari ha iniciat sessió al teu lloc en una altra pestanya, l’iframe hereta les cookies de sessió, així que el clic s’executa com aquest usuari.
  • S’ha utilitzat contra bancs, xarxes socials i panells d’administració. Els fluxos OAuth i les pàgines d’alta de 2FA també han estat víctimes.
  • La solució és una capçalera. Els navegadors es neguen a renderitzar la teva pàgina en un iframe quan la capçalera hi és, l’atac deixa de ser possible.

La protecció contra framing és la mitigació més barata en seguretat web: una capçalera de resposta per pàgina, sense canvis de codi, sense cost de rendiment.

Com solucionar-ho

Tria un dels dos mecanismes. Els navegadors moderns prefereixen CSP frame-ancestors; X-Frame-Options és la capçalera heretada que també funciona en navegadors antics. Envia totes dues per cobertura màxima, no entren en conflicte.

Denega tot framing (recomanat per a llocs que no s’haurien d’incrustar):

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

Permet framing només des del teu propi origen:

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

Permet framing des d’orígens de confiança específics (només CSP ho admet, X-Frame-Options no pot llistar diversos dominis):

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;

El flag always és crític, sense ell, nginx omet la capçalera en respostes d’error.

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, afegeix totes dues capçaleres globalment. O fes servir Page Shield si vols control a nivell de 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'"] },
  })
);

Prova-ho:

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

Espera totes dues capçaleres o, com a mínim, frame-ancestors. Després intenta incrustar-ho en un iframe localment per confirmar que el navegador s’hi nega.

Preguntes freqüents

Haig de denegar tot el framing o només des del mateix origen?

Per defecte, frame-ancestors 'none' i només relaxa-ho si necessites incrustar les teves pàgines activament. La majoria de llocs de marketing, panells d’administració i aplicacions no s’haurien d’incrustar mai, i els proveïdors d’OAuth (Google, Apple, Stripe) que sí que necessiten framing tenen fluxos d’incrustació ben definits que no requereixen relaxar la teva CSP.

I X-Frame-Options: ALLOW-FROM?

Obsolet i no compatible amb Chrome ni Firefox. Fes servir Content-Security-Policy: frame-ancestors en el seu lloc, accepta múltiples orígens i funciona en tots els navegadors moderns.

Trenca això Google PageSpeed Insights o alguna eina?

No. Aquestes eines carreguen la pàgina directament, no en un iframe. La capçalera només afecta la incrustació en iframes.

Fonts

Última actualització 2026-05-11