Volver al blog

Cabeceras de seguridad: HSTS, CSP, X-Frame-Options y otras

· 7 min de lectura

En resumen: Las cabeceras HTTP de seguridad son líneas que el servidor añade a cada respuesta HTTP para decir al navegador cómo tratar tu sitio. Correctamente configuradas eliminan clases enteras de ataques (XSS, clickjacking, MITM) - y son gratis.

En resumen: Las cabeceras HTTP de seguridad son líneas que el servidor añade a cada respuesta HTTP para decir al navegador cómo tratar tu sitio. Correctamente configuradas eliminan clases enteras de ataques (XSS, clickjacking, MITM) - y son gratis.

Por qué importan

Una aplicación puede ser perfectamente segura del lado backend, pero sin cabeceras correctas sigue siendo vulnerable a ataques del lado navegador: cross-site scripting (XSS), clickjacking, protocol downgrade, MIME confusion. Las cabeceras de seguridad mueven la defensa al navegador.

Strict-Transport-Security (HSTS)

Fuerza HTTPS para todas las visitas futuras. Tras la primera visita HTTPS el navegador recuerda el dominio y él mismo reescribe cualquier enlace http:// a https://, incluso si el usuario hace clic en una respuesta mala.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age=63072000 = válido 2 años
  • includeSubDomains = la regla se aplica también a todos los subdominios (cuidado: si tienes un subdominio HTTP-only, lo rompe)
  • preload = permite inclusión en la lista HSTS preload integrada en Chrome / Firefox / Safari

Atención: HSTS con preload tarda 6+ meses en quitarse de la lista. No incluyas preload antes de verificar que HTTPS funciona de manera estable también para todos los subdominios.

Content-Security-Policy (CSP)

La cabecera más poderosa pero también la más difícil de configurar. Whitelist de dónde puede el navegador cargar scripts, estilos, imágenes, iframes. Sin CSP un atacante que puede inyectar etiqueta <script> puede ejecutar cualquier JS - con CSP solo código de fuentes aprobadas.

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'

Directivas comunes:

  • default-src 'self' = por defecto permite solo recursos de mi dominio
  • script-src = fuentes JS (especifica hash o nonce para scripts inline)
  • style-src = fuentes CSS
  • img-src = imágenes
  • connect-src = AJAX, WebSocket, EventSource
  • frame-ancestors 'none' = nadie puede embed-ear la página en iframe (mejor que X-Frame-Options)
  • report-uri /csp-report = el navegador envía JSON en cada violación (tú capturas en backend y registras)

X-Frame-Options

Alternativa antigua a frame-ancestors. Previene clickjacking - el atacante inserta tu página como iframe y la cubre con botones invisibles.

X-Frame-Options: DENY

Valores: DENY (nadie), SAMEORIGIN (solo mi dominio), ALLOW-FROM uri (deprecated).

X-Content-Type-Options

X-Content-Type-Options: nosniff

Desactiva el MIME sniffing - el navegador respetará el Content-Type que devolvió el servidor. Sin esto un atacante puede subir un archivo con tipo incorrecto (p.ej. una imagen que en realidad es HTML con script) y el navegador puede ejecutarlo como web page.

Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin

Controla cuánta información sobre la página anterior envía el navegador en el header Referer al hacer clic. El default en navegadores modernos ya es strict-origin-when-cross-origin, pero el header declarativo explícito asegura consistencia.

Permissions-Policy

Desactiva las API que no necesitas - cámara, micrófono, GPS, geolocation. Un atacante vía XSS no puede pedir estas API.

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Configuración práctica en nginx

server {
  listen 443 ssl http2;
  server_name example.com;

  add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
  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 es extensa - defínela según tu aplicación
  add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
}

La clave es always - sin él nginx omite las cabeceras en respuestas error (4xx, 5xx).

Audit del estado actual

Lo más fácil vía herramienta online. Nuestro header check te mostrará qué cabeceras faltan y cuáles son incorrectas. Para auditoría exhaustiva securityheaders.com también da puntuación A-F.

Conclusión

Las cabeceras de seguridad son una de las mejores inversiones en proporción esfuerzo a beneficio en el área de seguridad - típicamente media hora de configuración en reverse proxy contra toda una categoría de ataques del lado navegador. Auditoría una vez cada medio año como parte del mantenimiento regular es mínimo razonable.

Auditoría gratuita de security headers

Sin registro, resultado en tres segundos.

Probar el sitio web →


Prueba ePulz.io gratis - 7 días sin tarjeta de crédito.

Crear cuenta