DNS RobotDNS Propagation Checker
InicioDNSWHOISIPSSL
DNS RobotDNS Propagation Checker

Kit de herramientas DNS de nueva generación

Política de PrivacidadTérminos de ServicioAcerca de NosotrosBlogContacto

Herramientas DNS

Consulta DNSPrueba de Velocidad DNSDominio a IPConsulta NSConsulta MXVer todo

Herramientas de Correo

Verificador de Registro SPFVerificador DMARCVerificador DKIMHerramienta de Prueba SMTPAnalizador de Cabeceras de CorreoVer todo

Herramientas Web

Consulta WHOISComprobador de HostingDisponibilidad de DominioBuscador de SubdominiosDetector de CMSVer todo

Herramientas de Red

Herramienta PingTracerouteVerificador de PuertosVerificador de Cabeceras HTTPVerificador de Certificado SSLVer todo

Herramientas IP

Consulta de IPCuál Es Mi IPVerificador de Lista Negra IPIP a HostnameConsulta ASNVer todo

Herramientas Útiles

Escáner de Código QRGenerador de Código QRUPI QR Code GeneratorWiFi QR Code GeneratorTraductor de Código MorseVer todo
© 2026 DNS Robot. Desarrollado por: ❤ Shaik Brothers
Todos los sistemas operacionales
Made with
Inicio/Blog/Seguridad web: buenas prácticas capa por capa (guía 2026)

Seguridad web: buenas prácticas capa por capa (guía 2026)

Shaik Vahid29 sept 202630 min de lectura
Seguridad web en seis capas: dominio y DNS, TLS, cabeceras HTTP, aplicación, dependencias y servidor, con su verificación
Seguridad web en seis capas: dominio y DNS, TLS, cabeceras HTTP, aplicación, dependencias y servidor, con su verificación

Punto clave

La seguridad web funciona por capas: protege el dominio y el DNS (registrar lock, DNSSEC, CAA), fuerza TLS moderno con HSTS, envía un conjunto estricto de cabeceras de seguridad HTTP, aplica hash a las contraseñas con Argon2id respaldado por MFA y límites de tasa, valida las entradas y aplica el control de acceso en el servidor, fija y audita las dependencias, cierra todos los puertos que no uses y registra lo suficiente para detectar una brecha. Cada práctica de esta guía incluye la configuración exacta y una forma gratuita de comprobar que de verdad está activa, porque un control que no has probado es un control que no tienes.

Advertisement

Qué significan de verdad las buenas prácticas de seguridad web

Las buenas prácticas de seguridad web son el conjunto de controles que impiden que un sitio o una aplicación web acabe en manos de un atacante, sea desfigurado, se use para atacar a sus propios visitantes o pierda datos sin que nadie lo note. No son un producto ni un ajuste concreto. Son una pila de decisiones que empieza en el registrador del dominio y sigue por el DNS, el TLS, las cabeceras HTTP que envía tu servidor, el código que gestiona los inicios de sesión y las entradas, los paquetes de terceros sobre los que construyes, el propio servidor y, por último, los registros que te avisan de que algo ha ido mal.

La razón para pensar en capas es que los atacantes lo hacen. El Data Breach Investigations Report 2026 de Verizon concluyó que el 31 % de las brechas empieza ahora con la explotación de una vulnerabilidad de software, que por primera vez supera a las credenciales robadas como vía de entrada más habitual, y que el 48 % de todas las brechas implica ransomware. Basta un solo parche sin aplicar, una clave de API filtrada o una página de administración sin rate limiting. Ninguno de los controles de esta guía es exótico: los sitios que sufren brechas suelen ser los que se saltaron lo básico en una capa mientras pulían otra.

Esta guía va de fuera hacia dentro. Cada práctica explica por qué importa, qué configurar exactamente y cómo verificarlo con un comando o una herramienta gratuita, porque el fallo más común que vemos en las comprobaciones de cabeceras HTTP y las comprobaciones SSL no es una mala decisión, sino un ajuste que alguien creía activado y nunca confirmó.

Nota

Si solo tienes una hora: activa el registrar lock y la MFA en tu registrador, fuerza HTTPS con HSTS, añade las cabeceras de seguridad de la tabla de la capa 3, aplica hash a las contraseñas con Argon2id, actualiza todas las dependencias con un CVE conocido y cierra todos los puertos excepto el 80 y el 443. Eso cubre los puntos de entrada de la gran mayoría de las brechas web reales.

La pila de seguridad web: seis capas que proteger

Todo ataque a un sitio web recae en una de seis capas. La tabla siguiente es el mapa del resto de la guía: qué vive en cada capa, cómo suele atacarse y qué comprobación gratuita confirma que tu defensa está realmente en su sitio.

CapaQué hacen aquí los atacantesPrácticas claveVerificar con
1. Dominio y DNSSecuestran el dominio, cambian los servidores de nombres, toman subdominios huérfanos, obtienen certificados fraudulentosRegistrar lock, MFA, DNSSEC, CAA, auditoría de registros obsoletosConsulta WHOIS, Consulta DNS, Buscador de Subdominios
2. Transporte (TLS)Degradan la conexión a HTTP, eliminan el cifrado, explotan cifrados antiguos, aprovechan certificados caducadosTLS 1.2+, HSTS con preload, renovación automatizadaVerificador de Certificado SSL
3. Cabeceras HTTPInyectan scripts (XSS), enmarcan el sitio para hacer clickjacking, provocan MIME sniffing, filtran el referrerCSP, frame-ancestors, nosniff, Referrer-Policy, Permissions-PolicyVerificador de Cabeceras HTTP
4. AplicaciónCredential stuffing, inyección, control de acceso roto, CSRF, subidas de archivos insegurasArgon2id + MFA + límites de tasa, consultas parametrizadas, autorización en el servidor, cookies SameSiteRevisión de código, OWASP ZAP, Prueba de Fuerza de Contraseña
5. DependenciasPaquetes envenenados, CVE conocidos en bibliotecas, pipelines de CI comprometidosLockfiles, auditorías, versiones fijadas, SBOM, tokens de mínimo privilegionpm audit, Dependabot, Trivy
6. Servidor y operacionesPuertos abiertos, credenciales por defecto, parches pendientes, sin copias de seguridad, sin registrosFirewall, SSH solo con claves, parches, copias 3-2-1, registro centralizadoVerificador de Puertos, Verificador de Lista Negra IP, Verificador de Salud del Dominio

Consejo

Trabaja de arriba abajo. Las capas 1 a 3 son configuración que puedes terminar en una tarde y protegen todas las páginas a la vez. Las capas 4 a 6 son hábitos continuos que deben formar parte de tu revisión de código y de tu proceso de despliegue.

Advertisement

Capa 1: protege el dominio y el DNS

Todo lo demás en esta guía da por hecho que sigues controlando tu dominio. Si un atacante puede entrar en tu cuenta del registrador o cambiar tus servidores de nombres, puede dirigir tu tráfico a cualquier parte, obtener un certificado válido para tu nombre y leer todo el correo que te envíen, sin que tu código de aplicación llegue a ejecutarse nunca. Por eso la seguridad del dominio y del DNS es la primera buena práctica de seguridad web, y es casi por completo una cuestión de configuración.

Empieza con una consulta WHOIS de tu propio dominio y confirma tres cosas: que los códigos de estado incluyen clientTransferProhibited, que la fecha de caducidad está a más de un año vista y que el registrador es uno en el que realmente tienes cuenta. Es sorprendentemente habitual que el dominio de una empresa siga en la cuenta de registrador de un antiguo proveedor externo. Nuestra guía de consulta WHOIS explica cada código de estado que verás.

Registrar lock, MFA y alertas de caducidad

Activa el registrar lock (también llamado bloqueo de transferencia) para que el dominio no pueda trasladarse a otro registrador sin que lo desbloquees explícitamente, y activa la autenticación multifactor (MFA) en la propia cuenta del registrador. Las cuentas de registrador son un objetivo favorito del phishing precisamente porque un solo inicio de sesión controla todo lo que depende de ellas. Usa una llave de hardware o una app de autenticación en lugar de SMS siempre que el registrador lo permita.

Configura la renovación automática del dominio con un método de pago que no vaya a caducar y, aun así, añade una alerta en el calendario 60 días antes de la fecha de caducidad. Los drop-catchers se hacen con los dominios caducados en cuestión de horas, y el comprador hereda tu correo, tu tráfico y cualquier inicio de sesión OAuth que confíe en tu dominio.

  • El registry lock (un bloqueo manual, fuera de banda, a nivel del registro) compensa la tarifa extra en un dominio del que depende un negocio: impide que incluso una cuenta de registrador comprometida cambie los servidores de nombres.

  • Separa los roles. La persona que paga el dominio, la cuenta que lo posee y el proveedor de DNS deben estar documentados y no depender del buzón de un solo empleado.

  • Activa la privacidad WHOIS para que tus datos de contacto no sirvan de mapa para el phishing, y mantén en la cuenta una dirección de rol supervisada, como domains@.

Firma la zona con DNSSEC

DNSSEC firma tu zona DNS para que un resolver pueda detectar respuestas falsificadas. Sin él, un atacante capaz de envenenar la caché de un resolver puede enviar a tus visitantes a un servidor falso mientras su navegador sigue mostrando tu nombre de dominio. La mayoría de los proveedores de DNS gestionado (Cloudflare, Route 53, Google Cloud DNS y muchos registradores) lo activan con un solo interruptor; el único paso manual es publicar el registro DS en tu registrador. Verifícalo con dig o con la comprobación DNSSEC del Verificador de Salud del Dominio:

bash
dig +dnssec +short yourdomain.com A
# A signed zone returns the record AND an RRSIG line:
# 203.0.113.10
# A 13 2 3600 20261015000000 20260924000000 34505 yourdomain.com. Kx3f...==

dig +short yourdomain.com DS
# A DS record at the parent zone proves the chain of trust is complete
# 34505 13 2 6A1B...C9

Restringe la emisión de certificados con CAA

Un registro CAA (RFC 8659) indica a las autoridades de certificación cuáles de ellas pueden emitir certificados para tu dominio. Toda CA pública está obligada a consultarlo antes de emitir, así que un registro CAA le cierra la puerta a un atacante que haya engañado a la validación de dominio de otra CA. Tres registros cubren los casos habituales: quién puede emitir, quién puede emitir certificados wildcard y dónde notificar una solicitud rechazada:

dns
yourdomain.com.  CAA 0 issue "letsencrypt.org"
yourdomain.com.  CAA 0 issuewild ";"
yourdomain.com.  CAA 0 iodef "mailto:security@yourdomain.com"

Advertencia

Antes de añadir CAA, haz una lista de todas las CA que emiten certificados para ti actualmente, incluida la que está detrás de tu CDN o de tu panel de hosting (Cloudflare rota entre varias CA; muchos proveedores de hosting usan Sectigo o Let's Encrypt). Un registro CAA que omita tu CA real romperá sin avisar la siguiente renovación. Comprueba primero el emisor actual con el Verificador de Certificado SSL.

Audita los registros obsoletos: subdomain takeover

Un subdomain takeover (toma de control de un subdominio) ocurre cuando un registro DNS sigue apuntando a un servicio que ya no usas: un CNAME a un sitio de GitHub Pages eliminado, una app de Azure, un bucket de S3 o el hostname de un proveedor SaaS. Cualquiera puede registrar el destino abandonado y servir contenido en old-app.yourdomain.com en tu nombre, con certificado válido incluido. Es uno de los hallazgos más comunes en los programas de bug bounty, porque nadie recuerda que el registro existe.

Pasa tu dominio por el Buscador de Subdominios, que lee los registros de Certificate Transparency, para ver todos los hostnames para los que se ha emitido alguna vez un certificado. Después resuelve cada uno con una consulta DNS y elimina cualquier registro cuyo destino devuelva NXDOMAIN o la página "no such app" de un proveedor. Repítelo cada trimestre y haz que eliminar el registro DNS forme parte de la retirada de cualquier servicio.

Consejo

Certificate Transparency es también tu sistema de alerta temprana: Cert Spotter y la monitorización de CT de Cloudflare pueden enviarte un correo cada vez que cualquier CA emita un certificado para tu dominio. Un certificado inesperado suele ser la primera señal visible de que tu DNS o tu registrador están comprometidos.

Capa 2: HTTPS y TLS bien configurados

HTTPS ya no es una buena práctica: es el mínimo, y los navegadores marcan las páginas HTTP sin cifrar como "No es seguro". Lo que todavía separa un sitio seguro de uno que simplemente está cifrado son las versiones de TLS que aceptas, si queda alguna forma de llegar a ti por HTTP y si la renovación está lo bastante automatizada como para sobrevivir a los recortes de vida útil de los certificados que empezaron en marzo de 2026.

Advertisement

TLS 1.2 como mínimo, TLS 1.3 preferido

TLS 1.0 y 1.1 quedaron formalmente obsoletos con el RFC 8996 en 2021, y ningún navegador actual los negocia. Desactívalos en el servidor, da preferencia a TLS 1.3 (que elimina todos los cifrados débiles conocidos y completa el handshake en un solo viaje de ida y vuelta) y mantén TLS 1.2 solo con suites de cifrado AEAD como ECDHE-ECDSA-AES128-GCM-SHA256 o ECDHE-RSA-CHACHA20-POLY1305.

Cuando pruebas desde fuera importan dos líneas: el protocolo negociado y Verify return code: 0, que significa que la cadena de certificados completa se ha validado. La falta de un certificado intermedio es la causa más habitual de los casos de "funciona en Chrome, falla en curl y en Android"; nuestra guía sobre la cadena de certificados SSL explica cómo arreglarlo, y el Verificador de Certificado SSL señala directamente una cadena incompleta. Esta es la comprobación ejecutada contra dnsrobot.net:

bash
echo | openssl s_client -connect dnsrobot.net:443 -servername dnsrobot.net 2>/dev/null \
  | grep -E 'Protocol|Cipher|Verify return'

# Protocol  : TLSv1.3
# Cipher    : TLS_AES_256_GCM_SHA384
# Verify return code: 0 (ok)

# Confirm the old versions are refused:
openssl s_client -connect dnsrobot.net:443 -tls1_1 2>&1 | grep -iE 'alert|no protocols'

Nota

Las listas de cifrados son donde las configuraciones copiadas y pegadas se quedan anticuadas. En lugar de escribirlas a mano, genera el bloque de servidor recomendado actual para nginx, Apache, Caddy o HAProxy con el Mozilla SSL Configuration Generator y elige el perfil "Intermediate", salvo que tengas que dar soporte a clientes muy antiguos.

HSTS: que el navegador no vuelva a usar HTTP

Redirigir HTTP a HTTPS no basta por sí solo. La primera petición que hace un visitante a http://yourdomain.com sigue viajando en texto plano, y un atacante en la misma red puede responderla antes que tu redirección. HTTP Strict Transport Security (RFC 6797) lo soluciona: en cuanto un navegador ha visto la cabecera, reescribe cualquier URL http:// futura de tu dominio a https:// antes de enviar nada.

Usa un max-age de al menos un año (31536000 segundos), añade includeSubDomains cuando todos los subdominios sirvan HTTPS y, después, envía el dominio a hstspreload.org para que venga integrado de fábrica en Chrome, Firefox, Safari y Edge. El preload cierra por completo el hueco de la primera visita. Verifica la cabecera con el Verificador de Cabeceras HTTP, que evalúa HSTS como parte de su nota de seguridad de la A a la F.

http
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Advertencia

HSTS es una puerta de un solo sentido. Una vez que includeSubDomains está en la lista de preload, cualquier subdominio que no pueda servir HTTPS válido, incluidas las herramientas internas y un host dev. olvidado, se vuelve inaccesible en los navegadores. Despliégalo por fases: max-age=300 durante una semana, luego un mes, luego un año, y solo entonces añade preload.

Certificados de 47 días: automatiza ya la renovación

La votación SC-081 del CA/Browser Forum está reduciendo por fases la vida útil máxima de todos los certificados TLS públicos. El primer recorte entró en vigor el 15 de marzo de 2026, así que cualquier certificado que compres o renueves hoy ya está limitado a 200 días, y en 2029 habrá que sustituir un certificado aproximadamente cada seis semanas:

Fecha de entrada en vigorValidez máxima del certificadoReutilización de la validación de dominio
Antes del 15 de marzo de 2026398 días398 días
15 de marzo de 2026200 días200 días
15 de marzo de 2027100 días100 días
15 de marzo de 202947 días10 días

La renovación manual no sobrevive a este calendario. La buena práctica es la emisión totalmente automatizada mediante ACME: Let's Encrypt o Google Trust Services con certbot, acme.sh o Caddy, o los certificados automáticos integrados en Cloudflare, Vercel, Netlify y la mayoría de los paneles de hosting. Prueba la renovación antes de necesitarla (certbot renew --dry-run en el caso de certbot); el fallo que hay que buscar es un registro CAA o una regla de firewall añadidos desde la última renovación que ahora bloquean la validación. Uses lo que uses, vigila también la fecha de caducidad desde fuera: el Verificador de Certificado SSL muestra los días restantes, y un certificado caducado convierte cada visita en un aviso del navegador a pantalla completa.

Capa 3: cabeceras de seguridad HTTP

Las cabeceras de seguridad son instrucciones que tu servidor da al navegador sobre lo que puede y no puede hacer con tus páginas: qué scripts pueden ejecutarse, si la página puede cargarse dentro de un marco, si el navegador puede adivinar tipos de contenido y qué debe contar a otros sitios sobre la procedencia de un visitante. No cuestan nada, se aplican a todas las páginas a la vez y bloquean clases enteras de ataques. También son la capa que la mayoría de los sitios configura solo a medias, y por eso el Verificador de Cabeceras HTTP las califica. Esto es lo que envía dnsrobot.net, recortado a las cabeceras de seguridad:

bash
curl -sI https://dnsrobot.net/ | grep -iE 'strict-transport|content-security|x-frame|x-content-type|referrer-policy|permissions-policy'

strict-transport-security: max-age=31536000; includeSubDomains; preload
content-security-policy: default-src 'self'; script-src 'self' ... https://*.googletagmanager.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
x-frame-options: DENY
x-content-type-options: nosniff
referrer-policy: strict-origin-when-cross-origin
permissions-policy: camera=(self), microphone=(), geolocation=(), payment=(), usb=()

Las siete cabeceras que todo sitio debería enviar

Estos son los valores a los que aspirar en un sitio típico. Las cinco primeras son las que mueven tu nota; las dos últimas son añadidos baratos una vez que las demás están en su sitio.

CabeceraValor recomendadoQué evita
Strict-Transport-Securitymax-age=31536000; includeSubDomains; preloadDegradación de protocolo, robo de cookies a través de HTTP
Content-Security-Policyscript-src basado en nonces con 'strict-dynamic'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'Cross-site scripting (XSS), inyección de datos, clickjacking
X-Content-Type-OptionsnosniffMIME sniffing que convierte un archivo subido en un script ejecutable
Referrer-Policystrict-origin-when-cross-originFiltración de URL completas (tokens, términos de búsqueda) a terceros
Permissions-Policycamera=(), microphone=(), geolocation=(), payment=()Scripts de terceros que usan sin avisar APIs potentes del navegador
X-Frame-OptionsDENY (respaldo heredado para frame-ancestors)Clickjacking en navegadores sin CSP Level 2
Cross-Origin-Opener-Policysame-originAtaques entre ventanas a través de window.opener

Content Security Policy sin romper el sitio

Una Content Security Policy es la defensa más eficaz contra XSS, porque impide que los scripts inyectados se ejecuten incluso cuando existe un fallo de inyección. El problema es que una política estricta rompe cualquier script inline o etiqueta de terceros que se te haya olvidado. El enfoque moderno, recomendado por Google y documentado en MDN, es una política basada en nonces: el servidor genera un nonce aleatorio por respuesta, lo pone en cada etiqueta script que renderiza de forma intencionada y el navegador rechaza todo lo demás.

'strict-dynamic' es lo que hace práctica la política: un script con nonce puede cargar más scripts (analítica, gestores de etiquetas, widgets) sin que haya que añadir cada uno a una lista de permitidos, mientras que los navegadores modernos ignoran los tokens https: y 'unsafe-inline', que solo sirven de respaldo para los antiguos. Despliégala primero con Content-Security-Policy-Report-Only, revisa los informes de infracciones durante una semana y luego pasa al modo de aplicación. Frameworks como Next.js, Rails y Django tienen soporte nativo para nonces; los sitios estáticos pueden usar en su lugar un script-src basado en hashes.

http
Content-Security-Policy:
  script-src 'nonce-r4nd0m1z3dV4lu3' 'strict-dynamic' https: 'unsafe-inline';
  object-src 'none';
  base-uri 'none';
  frame-ancestors 'none';
  form-action 'self';
  report-to csp-endpoint

<!-- Only scripts carrying the nonce run; strict-dynamic lets them load their own dependencies -->
<script nonce="r4nd0m1z3dV4lu3" src="/app.js"></script>

Nota

Una política de lista de permitidos como script-src 'self' https://cdn.example.com es mejor que nada, pero cualquier endpoint JSONP o biblioteca antigua alojada en un host permitido puede usarse para saltársela. Si todavía no puedes usar nonces, define al menos object-src 'none' y base-uri 'none', que cierran de inmediato dos vías de evasión habituales.

Clickjacking: frame-ancestors y X-Frame-Options

El clickjacking carga tu sitio de forma invisible dentro de la página de un atacante y engaña al visitante para que haga clic en un botón que no ve. frame-ancestors 'none' en la CSP (o 'self' si incrustas tus propias páginas) lo impide en todos los navegadores actuales, y X-Frame-Options: DENY cubre los más antiguos. Si ofreces a propósito un widget incrustable, exime solo esa ruta y solo para los orígenes que lo necesiten; nuestra guía de X-Frame-Options repasa las reglas de servidor exactas y los errores "refused to connect" que te encontrarás al hacer pruebas.

nosniff, Referrer-Policy, Permissions-Policy y COOP

X-Content-Type-Options: nosniff impide que el navegador cuestione un Content-Type, que es lo que convierte una "imagen" subida por un usuario que contiene HTML en una página ejecutable. Referrer-Policy: strict-origin-when-cross-origin (el valor por defecto en los navegadores actuales, pero defínelo explícitamente) envía a otros sitios solo tu origen, de modo que los tokens de restablecimiento de contraseña y las búsquedas incluidas en las URL se mantienen privados. Permissions-Policy desactiva las funciones del navegador que no usas, para que un script de terceros comprometido no pueda abrir la cámara ni leer la ubicación. Cross-Origin-Opener-Policy: same-origin corta el vínculo window.opener con las páginas que abres, lo que bloquea toda una clase de ataques entre ventanas.

Las cabeceras que hay que eliminar también importan: Server y X-Powered-By anuncian versiones exactas de software a los escáneres de vulnerabilidades, y X-XSS-Protection está obsoleta y puede introducir fallos en navegadores antiguos, así que ponla a 0 o elimínala. El Detector de CMS muestra lo que un escáner averigua sobre tu stack solo a partir de las cabeceras.

Consejo

Define las cabeceras una sola vez en el borde (CDN, proxy inverso o middleware del framework) en lugar de página por página. En Next.js es el archivo proxy o middleware; en nginx, un bloque add_header en el contexto server; en Apache, Header always set. Después vuelve a pasar el Verificador de Cabeceras HTTP tras cada despliegue, porque una nueva versión del framework o un ajuste de la CDN puede eliminar alguna sin avisar.

Capa 4: una autenticación que resista el credential stuffing

Los atacantes rara vez adivinan contraseñas de una en una. Prueban miles de millones de pares de correo y contraseña filtrados de otros sitios (credential stuffing) y consiguen el resto con phishing. Por eso las buenas prácticas de autenticación tienen tres partes: almacenar las contraseñas de modo que una fuga de la base de datos no sea una fuga de contraseñas, hacer que una contraseña robada no sirva por sí sola y hacer que la fuerza bruta sea demasiado lenta para importar. OWASP sitúa los Authentication Failures (fallos de autenticación) en el puesto A07 del OWASP Top 10:2025.

Advertisement

Hash de contraseñas con Argon2id o bcrypt

Nunca almacenes una contraseña, y nunca almacenes un hash rápido de ella. MD5, SHA-1 e incluso SHA-256 están diseñados para ser rápidos, así que una tabla filtrada de estos hashes puede probarse a miles de millones de intentos por segundo con una sola GPU. Usa una función de hash de contraseñas lenta y con uso intensivo de memoria, con una sal única por contraseña. La OWASP Password Storage Cheat Sheet recomienda, por este orden:

  • Argon2id con al menos 19 MiB de memoria, 2 iteraciones y 1 grado de paralelismo (o 46 MiB con 1 iteración).

  • scrypt con N = 2^17, r = 8, p = 1 cuando Argon2 no esté disponible.

  • bcrypt con un factor de trabajo de 10 o más (ten en cuenta su límite de entrada de 72 bytes; aplicar un hash previo a las contraseñas más largas requiere cuidado).

  • PBKDF2-HMAC-SHA256 con 600.000 iteraciones, solo cuando el cumplimiento de FIPS lo exija.

javascript
// Node.js with the argon2 package
import argon2 from "argon2";

const hash = await argon2.hash(password, {
  type: argon2.argon2id,
  memoryCost: 19456, // KiB = 19 MiB
  timeCost: 2,
  parallelism: 1,
});

// Later, on login:
const ok = await argon2.verify(hash, submittedPassword);

Nota

Ajusta el coste para que un hash tarde aproximadamente entre 100 y 250 ms en tu servidor de inicio de sesión. Es imperceptible para un usuario real, pero limita a un atacante a unos pocos miles de intentos por segundo y por núcleo en lugar de miles de millones. Vuelve a calcular el hash en cada inicio de sesión correcto cuando subas los parámetros, para que los hashes antiguos se actualicen solos.

Reglas de contraseñas que sí ayudan (NIST SP 800-63B)

Las reglas de composición que la mayoría de los sitios siguen imponiendo (una mayúscula, un símbolo, cambio cada 90 días) generan contraseñas predecibles como Summer2026! y empujan a la gente a reutilizarlas. La guía actual del NIST SP 800-63B las sustituye por reglas que miden lo que importa:

  • Mínimo de 8 caracteres cuando también se exige MFA, y al menos 15 caracteres para una contraseña que se usa sola; admite como mínimo 64.

  • Sin reglas de composición y sin rotación periódica forzada; exige un cambio solo cuando haya indicios de que la cuenta está comprometida.

  • Comprueba cada contraseña nueva contra una lista de filtraciones (la API de rangos de Have I Been Pwned permite hacerlo sin enviar la contraseña) y rechaza las que ya se hayan filtrado.

  • Permite pegar y usar gestores de contraseñas, acepta espacios y Unicode, y muestra un medidor de fortaleza basado en la entropía y no en reglas.

Nuestra Prueba de Fuerza de Contraseña muestra en qué se diferencian estas medidas de las reglas antiguas: estima el tiempo que se tardaría en descifrarla a partir de la entropía y la detección de patrones, y comprueba la contraseña contra datos de filtraciones, lo que resulta mucho más útil que un mensaje en rojo de "falta un símbolo".

MFA y passkeys

La autenticación multifactor convierte una contraseña robada en un callejón sin salida. Ofrécela a todo el mundo y exígela para los roles de administración, finanzas y soporte. Ordena las opciones por su resistencia al phishing: las passkeys y las llaves de seguridad FIDO2 no pueden robarse con phishing porque la credencial está vinculada a tu origen real; las apps de autenticación (TOTP) son buenas; los códigos por SMS son mejor que nada, pero pueden interceptarse mediante SIM swapping. Las passkeys funcionan en todos los navegadores y sistemas operativos actuales y eliminan por completo la contraseña, lo que también elimina el credential stuffing como categoría.

Protege la vía de recuperación con el mismo cuidado que el inicio de sesión: códigos de recuperación almacenados con hash, restablecimientos por correo con tokens de un solo uso que caduquen en menos de 15 minutos y nada de preguntas de seguridad.

Rate limiting, bloqueo de cuentas y defensa contra bots

Aplica rate limiting (limitación de tasa) a los endpoints de inicio de sesión, registro, restablecimiento de contraseña y MFA por IP y por cuenta, y devuelve 429 Too Many Requests con una cabecera Retry-After cuando se alcance el límite (nuestra guía sobre el error HTTP 429 explica cómo deben reaccionar los clientes). Combínalo con un retardo progresivo o un bloqueo temporal tras fallos repetidos en una misma cuenta, y con un CAPTCHA o un reto de prueba de trabajo en los endpoints que reciben ataques distribuidos. Registra cada inicio de sesión fallido con la IP de origen para que el patrón de una campaña de credential stuffing sea visible en minutos y no en meses.

nginx
# nginx: 5 login attempts per minute per client IP
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

location = /api/login {
    limit_req zone=login burst=4 nodelay;
    limit_req_status 429;
    proxy_pass http://app;
}

Advertencia

Usa mensajes de error idénticos para "usuario desconocido" y "contraseña incorrecta", y haz que el tiempo de respuesta sea el mismo en ambos casos (calcula el hash de una contraseña ficticia cuando el usuario no exista). De lo contrario, el formulario de inicio de sesión funciona también como una API de enumeración de usuarios.

Sesiones, cookies y CSRF

Tras el inicio de sesión, la cookie de sesión es el usuario, así que merece la misma protección que la contraseña. Tres atributos de cookie y un prefijo de nombre hacen la mayor parte del trabajo:

  • Secure significa que la cookie nunca se envía por HTTP sin cifrar, así que no puede interceptarse en una red Wi-Fi pública.

  • HttpOnly la hace invisible para JavaScript, así que un fallo XSS no puede leerla.

  • SameSite=Lax (o Strict para los paneles de administración) evita que viaje en peticiones POST entre sitios, lo que neutraliza la mayoría de los ataques CSRF.

  • El prefijo __Host- hace que el navegador rechace la cookie salvo que sea Secure, tenga Path=/ y no lleve atributo Domain, de modo que un subdominio no puede sobrescribirla.

http
Set-Cookie: __Host-session=9f1c7e2a...; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=28800

Consejo

Las acciones que cambian el estado nunca deben ser accesibles mediante GET. Un enlace como /account/delete?id=42 puede activarse con una etiqueta <img> en cualquier página que visite el usuario, por buenos que sean los flags de tus cookies.

CSRF: una segunda línea de defensa detrás de SameSite

El cross-site request forgery (CSRF) engaña a un navegador con sesión iniciada para que envíe a tu sitio, desde otra página, una petición que cambia el estado. Las cookies SameSite detienen el caso común, pero mantén una segunda defensa en cada petición que no sea GET: un token anti-CSRF por sesión en un campo oculto o en una cabecera personalizada, o una comprobación de que la cabecera Origin (o Sec-Fetch-Site) coincide con tu propio origen. La mayoría de los frameworks (Django, Rails, Laravel, las server actions de Next.js) lo hacen por defecto; el error es desactivarlo para un endpoint de API y luego llamar a ese endpoint desde un navegador.

IDs de sesión, rotación y JWT

Genera los IDs de sesión con al menos 128 bits de aleatoriedad, rota el ID al iniciar sesión y ante cualquier cambio de privilegios para frustrar la fijación de sesión, haz caducar las sesiones tras un periodo de inactividad y ofrece a los usuarios un botón de "cerrar sesión en todos los dispositivos" que las invalide en el servidor. En el caso de los JWT, dales una vida corta (minutos, con un refresh token revocable), no los guardes nunca en localStorage, donde cualquier script puede leerlos, y trata una clave de firma filtrada como una brecha completa, porque cualquier token que haya firmado pasa a poder falsificarse.

Inyección y XSS: valida la entrada, codifica la salida

La inyección (A05:2025) y el cross-site scripting son el mismo error en lugares distintos: los datos de un usuario se entregan a un intérprete (SQL, la shell, una consulta LDAP, una página HTML) como si fueran código. La solución también es la misma en todas partes: mantener separados los datos y el código, y no construir nunca un comando concatenando cadenas.

Advertisement

Consultas parametrizadas, no cadenas concatenadas

En SQL, usa sentencias preparadas o un ORM que las genere; así la base de datos trata la entrada como un valor que nunca puede cambiar la estructura de la consulta. La misma regla se aplica a los comandos de shell (pasa un array de argumentos, nunca una cadena), a los filtros NoSQL (rechaza objetos de operador como {"$gt": ""} en la entrada del usuario) y a las rutas de archivo (resuelve la ruta y confirma que se queda dentro del directorio previsto).

javascript
// Vulnerable: the input becomes part of the query text
const rows = await db.query(`SELECT * FROM users WHERE email = '${email}'`);

// Safe: the driver sends the value separately from the query
const rows = await db.query("SELECT * FROM users WHERE email = $1", [email]);

// Python / psycopg: same idea
cur.execute("SELECT * FROM users WHERE email = %s", (email,))

La codificación de salida detiene el XSS

El cross-site scripting se produce cuando un texto controlado por el usuario se escribe en una página sin codificarlo para el contexto en el que acaba. Los motores de plantillas modernos (React y JSX, Vue, Jinja2, Blade, ERB) codifican por defecto; hoy el XSS suele venir de las vías de escape: dangerouslySetInnerHTML, v-html, |safe, innerHTML y la construcción de URL o manejadores de eventos inline a partir de datos del usuario. Codifica para el contexto exacto y sanea el HTML enriquecido con una biblioteca creada para ello, como DOMPurify, en lugar de con una expresión regular.

Dónde acaban los datosCodificar comoEjemplo
Cuerpo HTMLEntidades HTML< pasa a ser &lt;, " pasa a ser &quot;
Atributo HTMLEntidades con el atributo entre comillasPon siempre el atributo entre comillas; codifica " y '
JavaScriptNo inyectes en el texto del script; pasa los datos mediante atributos data- o un bloque JSON <script type="application/json"></script> dentro de una cadena pasa a ser \u003c/script\u003e
Parámetro de URLCodificación porcentualencodeURIComponent(value)
Valor CSSEvítalo por completo; elige nombres de clase de una lista de permitidosNunca interpoles entrada del usuario en style

SSRF, subida de archivos y deserialización

Server-side request forgery (SSRF): si tu servidor descarga una URL proporcionada por un usuario (webhooks, proxies de imágenes, vistas previas de enlaces), un atacante puede apuntarla a servicios internos o al endpoint de metadatos de la nube 169.254.169.254 y leer credenciales. Resuelve primero el hostname, rechaza los rangos privados y link-local, desactiva las redirecciones y coloca los procesos que hacen estas peticiones en un segmento de red que no pueda llegar a nada interno.

Subida de archivos: valida el tipo inspeccionando el contenido, no la extensión ni el Content-Type que envía el cliente; impón un límite de tamaño; guarda los archivos fuera de la raíz web o en almacenamiento de objetos con un nombre aleatorio generado por ti; y sírvelos desde un origen separado con nosniff y Content-Disposition: attachment siempre que sea posible. No dejes nunca que un archivo subido acabe en un lugar donde el servidor web vaya a ejecutarlo.

Deserialización y asignación masiva: no deserialices nunca datos no fiables con un formato que pueda instanciar clases arbitrarias (la serialización nativa de Java, pickle de Python, unserialize de PHP, YAML con etiquetas personalizadas); usa JSON con un esquema. Vincula los cuerpos de las peticiones a una lista explícita de campos permitidos para que un usuario no pueda enviar por POST "role": "admin" a un modelo que casualmente tenga esa columna.

Advertencia

La validación sirve para comprobar la forma (¿es un correo, un entero positivo, uno de estos cinco valores?), no para la seguridad. Las listas de bloqueo que eliminan <script> o las comillas siempre pueden eludirse. Acepta solo lo que esperas y, después, codifica en la salida y parametriza en el almacenamiento.

Broken Access Control: el riesgo número uno

Broken Access Control (control de acceso roto) ocupa el primer puesto del OWASP Top 10 desde 2021 y lo mantiene como A01:2025. No es un fallo concreto, sino un hábito: comprobar quién es alguien (autenticación) y olvidarse de comprobar qué puede tocar (autorización) en cada petición. La forma clásica es la referencia directa insegura a objetos (IDOR): GET /api/invoices/1042 funciona para el propietario de la factura, y también para cualquiera que cambie el número.

  • Deniega por defecto. Cada ruta requiere una regla explícita que conceda acceso; si falta la regla, la respuesta es 403, no 200.

  • Aplícalo en el servidor, objeto por objeto. Ocultar un botón en la interfaz no es control de acceso. Cada lectura y escritura debe confirmar que el usuario actual es el propietario del registro concreto o tiene permiso sobre él, también en los endpoints masivos, las exportaciones y las tareas en segundo plano.

  • Usa IDs imposibles de adivinar cuando ayude (UUID), pero no confíes nunca en ellos: la ocultación no es autorización.

  • Restringe CORS. Access-Control-Allow-Origin: * con credenciales, o reflejar cualquier Origin que envíe la petición, pone tu API en manos de cualquier sitio web que visite el usuario.

  • Desactiva el listado de directorios, bloquea .git, .env, las copias de seguridad y los archivos de configuración a nivel del servidor web, y mantén los paneles de administración fuera de internet o detrás de MFA y listas de IP permitidas.

  • Aplica rate limiting y registra los fallos de autorización. Una ráfaga de 403 desde una misma sesión es un ataque de enumeración en curso.

javascript
// Express: ownership check on every object access
app.get("/api/invoices/:id", requireAuth, async (req, res) => {
  const invoice = await Invoice.findById(req.params.id);
  if (!invoice || invoice.ownerId !== req.user.id) {
    return res.status(404).end(); // 404, not 403: don't confirm the record exists
  }
  res.json(invoice);
});

Nota

Prueba el control de acceso como lo haría un atacante: inicia sesión como usuario con pocos privilegios, captura todas las peticiones y repite cada una con los IDs de otro usuario y sin la cabecera Authorization. Los escáneres automáticos encuentran inyecciones; casi nunca encuentran fallos de autorización, y por eso esos fallos sobreviven durante años.

Capa 5: dependencias y cadena de suministro de software

Una aplicación web típica incluye quizá un 5 % de código escrito por ti y un 95 % de código descargado. Por eso Software Supply Chain Failures (fallos en la cadena de suministro de software) debuta en el puesto A03 del OWASP Top 10 de 2025, y por eso la explotación de vulnerabilidades superó a las credenciales robadas en el DBIR de 2026. En septiembre de 2025, un solo mantenedor víctima de phishing introdujo malware para robar criptomonedas en chalk, debug y otros 16 paquetes npm que juntos suman más de dos mil millones de descargas a la semana; todos los proyectos que instalaron una versión sin fijar durante ese periodo lo incorporaron automáticamente.

  • Haz commit de un lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, go.sum) e instala con npm ci en CI para que las compilaciones sean reproducibles y una nueva versión upstream no pueda colarse sin revisión.

  • Analiza de forma continua: npm audit, pip-audit, bundler-audit, GitHub Dependabot o Renovate para las actualizaciones, y un escáner de contenedores como Trivy o Grype para la capa del sistema operativo.

  • Retrasa unos días las actualizaciones que no sean de seguridad (minimumReleaseAge de Renovate) para que una versión envenenada suela retirarse antes de que la adoptes, pero aplica los parches de seguridad de inmediato.

  • Fija las actions y los scripts de terceros a un SHA de commit en CI, y usa Subresource Integrity (integrity="sha384-...") en cualquier script que cargues desde una CDN pública.

  • Da a CI el mínimo privilegio: tokens de solo lectura cuando sea posible, credenciales OIDC de corta duración en lugar de secretos de larga duración y permisos de publicación limitados a un job de release.

  • Genera un SBOM (CycloneDX o SPDX) en tiempo de compilación para poder responder "¿nos afecta?" en minutos cuando llegue el próximo CVE del calibre de Log4Shell.

bash
# Reproducible install + audit in CI
npm ci --ignore-scripts
npm audit --audit-level=high

# Pin a GitHub Action to a commit, not a floating tag
# uses: actions/checkout@v4                 <- can change underneath you
# uses: actions/checkout@<full-commit-sha>  # v4.2.2

# Subresource Integrity for a CDN script (hash from: openssl dgst -sha384 -binary lib.min.js | openssl base64 -A)
<script src="https://cdn.example.com/lib.min.js"
        integrity="sha384-<base64-hash>"
        crossorigin="anonymous"></script>

Consejo

npm ci --ignore-scripts bloquea los scripts de instalación que usa la mayor parte del malware de npm para ejecutarse; después, vuelve a activar los scripts solo para los pocos paquetes que de verdad necesitan un paso de compilación.

Si usas WordPress u otro CMS, las mismas reglas se aplican a los plugins y temas, que es donde empiezan la mayoría de los compromisos de un CMS. Mantén actualizados el núcleo y todos los plugins, elimina los que no uses y comprueba lo que un escáner puede averiguar sobre tus versiones con el Detector de CMS.

Capa 6: hardening del servidor (puertos, parches, secretos y copias de seguridad)

La capa de aplicación da igual si el servidor que hay debajo acepta inicios de sesión SSH con contraseña, ejecuta una base de datos en un puerto público o no se ha parcheado desde que se instaló. Las buenas prácticas de servidor son aburridas, y es justo por ahí por donde entra el ransomware.

Cierra todos los puertos que no uses

Un servidor web público necesita abiertos los puertos 80 y 443, y SSH desde tu propio rango de IP. Las bases de datos (3306, 5432, 27017), Redis (6379), Elasticsearch (9200), los paneles de administración y los endpoints de métricas deben escuchar solo en localhost o en una red privada. Compruébalo desde fuera con el Verificador de Puertos después de cada cambio, porque esa es la vista que tiene un atacante, y los grupos de seguridad en la nube son fáciles de malinterpretar.

bash
# Ubuntu: default-deny firewall, allow only web + SSH from your office range
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from 203.0.113.0/24 to any port 22 proto tcp
sudo ufw enable

# SSH: keys only, no root password login
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sudo systemctl reload ssh

Parchea con calendario y saca los secretos del código

Activa las actualizaciones de seguridad desatendidas del sistema operativo, suscríbete a las listas de seguridad de tu runtime y de tu framework, y trata un CVE crítico en cualquier cosa expuesta a internet como una tarea para el mismo día. Ejecuta los servicios con usuarios sin privilegios, en contenedores o con el sandboxing de systemd, para que un proceso comprometido no pueda leer toda la máquina.

Los secretos (contraseñas de bases de datos, claves de API, claves de firma) nunca deben estar en el repositorio, en una capa de una imagen de Docker ni en JavaScript del lado del cliente. Cárgalos desde variables de entorno inyectadas en el despliegue o desde un gestor de secretos, rótalos cuando se marche alguien con acceso y analiza el historial del repositorio con una herramienta como gitleaks, porque una clave que se ha subido una sola vez queda comprometida para siempre, aunque se elimine el commit.

Advertencia

Todo lo que lleve el prefijo NEXT_PUBLIC_, VITE_ o REACT_APP_ se empaqueta en el código del navegador y es público por definición. Coloca las claves de API de terceros detrás de una ruta de tu propio servidor. Nuestra guía para probar un endpoint de API pública muestra cómo confirmar lo que tu frontend expone realmente.

Copias de seguridad que sobrevivan al ransomware y una CDN delante

Sigue la regla 3-2-1: tres copias, en dos soportes distintos y una fuera de las instalaciones, y haz que al menos una copia sea inmutable o esté desconectada para que un ransomware que llegue al servidor no pueda cifrar también las copias. Cifra las copias de seguridad, incluye la base de datos y el directorio de subidas y, sobre todo, prueba una restauración de forma periódica. Una copia de seguridad que nadie ha restaurado nunca es una esperanza, no un plan. El tiempo de recuperación es lo que decide si un incidente es una simple caída del servicio o algo que acaba con la empresa.

Coloca una CDN o un WAF (Cloudflare, Fastly, AWS CloudFront con WAF o el equivalente de tu proveedor de hosting) delante del origen. Absorbe los DDoS volumétricos, aplica reglas gestionadas contra las cargas de inyección habituales y los bots maliciosos, oculta la IP de tu origen y te da un lugar donde aplicar límites de tasa y reglas geográficas sin tocar la aplicación. Después, restringe el firewall del origen para que solo los rangos de IP de la CDN puedan llegar directamente al puerto 443; de lo contrario, los atacantes simplemente la esquivan. El Comprobador de Hosting muestra si el origen real de un sitio queda expuesto detrás de su CDN.

Autenticación del correo: SPF, DKIM y DMARC

La seguridad web incluye el correo que transporta tus restablecimientos de contraseña, tus facturas y tus respuestas de soporte. Sin SPF, DKIM y DMARC, cualquiera puede enviar correo como billing@yourdomain.com, y desde febrero de 2024 Google y Yahoo exigen los tres a los remitentes masivos. El conjunto completo son tres registros TXT de DNS:

dns
yourdomain.com.                    TXT  "v=spf1 include:_spf.google.com -all"
google._domainkey.yourdomain.com.  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
_dmarc.yourdomain.com.             TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com; adkim=s; aspf=s"

Nota

DMARC p=reject es también un control de protección de marca: es lo único que impide que una campaña de phishing ponga exactamente tu dominio en el campo From. Los informes agregados (rua=) te muestran quién lo está intentando.

Empieza DMARC con p=none para recopilar informes y pasa a p=quarantine y luego a p=reject cuando todos los remitentes legítimos (plataforma de marketing, helpdesk, CRM) superen la alineación. Añade registros MTA-STS y TLS-RPT para forzar la entrega cifrada a tus servidores de correo, y publica un MX nulo (MX 0 .) en los dominios que nunca envían correo para que no puedan suplantarse en absoluto. Verifica cada registro con el Verificador de Registro SPF, el Verificador DKIM y el Verificador DMARC, y si baja la entregabilidad, comprueba tus IP de envío en las listas de bloqueo con el Verificador de Lista Negra IP.

Registra, monitoriza y prepárate para la brecha

Dos de las diez categorías de OWASP 2025 tratan de lo que ocurre después de un error: Security Logging and Alerting Failures (fallos de registro y alertas de seguridad, A09) y la nueva Mishandling of Exceptional Conditions (gestión incorrecta de condiciones excepcionales, A10). La brecha típica sigue pasando desapercibida durante meses porque las pruebas nunca se registraron, o se registraron y nadie las miró.

  • Registra los eventos de seguridad con contexto: cada inicio de sesión correcto y fallido, cambios de MFA, restablecimientos de contraseña, cambios de permisos, denegaciones de control de acceso, fallos de validación de entradas y acciones de administración, cada uno con marca de tiempo, ID de usuario, IP de origen y user agent.

  • No registres nunca secretos: contraseñas, tokens de sesión, números de tarjeta completos, claves de API. Enmascáralos en la capa de registro, no en cada punto de llamada.

  • Saca los registros del servidor a un almacén central (CloudWatch, Loki, Elastic, un SIEM) con una retención de al menos 90 días, para que un atacante con acceso root no pueda borrar su rastro.

  • Crea alertas sobre patrones, no sobre eventos aislados: 50 inicios de sesión fallidos en un minuto, un pico de 403 desde una sesión, un nuevo administrador creado fuera del horario laboral, un certificado emitido para tu dominio que no has solicitado.

  • Falla en cerrado: cuando una comprobación intermedia (servicio de autenticación, limitador de tasa, WAF) devuelve un error, deniega la petición. A10 existe porque muchísimos sistemas conceden el acceso cuando la comprobación que debía bloquearlo lanza una excepción.

  • Monitoriza desde fuera: disponibilidad, caducidad de certificados, cambios de DNS, inclusiones en listas de bloqueo y regresiones en las cabeceras. El Verificador de Salud del Dominio agrupa las comprobaciones de DNS, SSL, autenticación del correo y cabeceras en una sola puntuación que puedes volver a calcular tras cada despliegue.

Escribe el plan de respuesta a incidentes antes de necesitarlo

Decide de antemano quién está de guardia, cómo rotar cada credencial, cómo poner el sitio en modo de solo lectura, dónde están las copias de seguridad limpias y a qué autoridad o clientes hay que notificar y en cuántas horas (72 según el RGPD). Haz un ejercicio de simulación (tabletop) una vez al año. Los equipos con un plan ensayado se recuperan en días; los que no lo tienen improvisan durante semanas.

Consejo

Añade un archivo security.txt en /.well-known/security.txt (RFC 9116) con una dirección de contacto y una clave PGP. Los investigadores que encuentren un fallo en tu sitio lo usarán; la alternativa es que lo publiquen abiertamente.

Ponlo a prueba: escáneres, pentests y comprobaciones continuas

Todos los controles anteriores pueden verificarse, y la verificación debería automatizarse siempre que sea posible para que no se deteriore con el tiempo. Una escalera razonable, desde lo gratuito e instantáneo hasta lo periódico y de pago:

ComprobaciónHerramientaFrecuencia
Configuración TLS, cadena, caducidadVerificador de Certificado SSL, SSL Labs, testssl.shTras cada cambio de certificado o de servidor; la caducidad, a diario
Cabeceras de seguridad y CSPVerificador de Cabeceras HTTP, MDN HTTP ObservatoryTras cada despliegue (inclúyelo en CI)
Puertos abiertosVerificador de Puertos, nmapTras cada cambio de firewall o de la nube
DNS, DNSSEC, autenticación del correoVerificador de Salud del Dominio, Verificador DMARCCada mes y tras cualquier cambio de DNS
Subdominios obsoletosBuscador de SubdominiosCada trimestre y en cada retirada de un servicio
Dependencias con vulnerabilidades conocidasnpm audit, Dependabot, TrivyEn cada compilación
Fallos a nivel de código (SAST)Semgrep, CodeQLEn cada pull request
Vulnerabilidades web en tiempo de ejecución (DAST)OWASP ZAP, NucleiCada semana, contra el entorno de staging
Autorización y lógica de negocioPentest manual o programa de bug bountyUna vez al año y tras cada funcionalidad importante

Los escáneres son buenos detectando inyecciones, cabeceras y componentes desactualizados, y malos con la autorización y la lógica de negocio, así que reserva presupuesto para al menos una prueba humana al año en cualquier cosa que maneje dinero o datos personales. Corrige según la exposición: lo que un usuario no autenticado pueda explotar desde internet va primero.

Checklist de seguridad web

Copia esto en el README de tu proyecto o en tu gestor de tickets. Cada línea es una de las prácticas anteriores, redactada para que pueda marcarse como hecha o pendiente; la última columna es la prueba.

CapaPrácticaHecho cuando
DominioRegistrar lock y MFA en la cuenta del registrador; renovación automática activadaWHOIS muestra clientTransferProhibited; caducidad a más de 12 meses vista
DNSZona firmada con DNSSEC; registro CAA que solo incluye tus CAdig +dnssec devuelve RRSIG; registro DS presente en la zona padre
DNSNingún registro CNAME ni A huérfanoCada hostname del Buscador de Subdominios resuelve a algo que controlas
TLSSolo TLS 1.2+, TLS 1.3 preferido, cadena completa servidaVerificador de Certificado SSL: cadena completa, TLS 1.0/1.1 rechazados
TLSHSTS con max-age de un año, includeSubDomains y preloadIncluido en hstspreload.org
TLSRenovación automatizada mediante ACME; caducidad monitorizadacertbot renew --dry-run se ejecuta sin errores; alerta configurada a 14 días
CabecerasCSP (basada en nonces), frame-ancestors, nosniff, Referrer-Policy, Permissions-PolicyNota A en el Verificador de Cabeceras HTTP
AutenticaciónHash con Argon2id o bcrypt; reglas de contraseñas del NIST; comprobación contra listas de filtracionesUn hash tarda de 100 a 250 ms; sin reglas de composición
AutenticaciónMFA ofrecida a todos y obligatoria para administradores; passkeys admitidasImposible iniciar sesión como administrador sin un segundo factor
AutenticaciónEndpoints de inicio de sesión, restablecimiento y MFA con rate limiting por IP y por cuentaEl sexto intento en un minuto devuelve 429
SesionesCookie __Host- con Secure, HttpOnly y SameSite; ID rotado al iniciar sesiónAtributos de la cookie visibles en DevTools; la sesión antigua deja de ser válida tras el inicio de sesión
EntradasConsultas parametrizadas en todas partes; salida codificada según el contexto; archivos subidos validados por su contenidoNinguna consulta construida con cadenas en una búsqueda por el código; los payloads XSS se muestran como texto
Control de accesoEnrutamiento con denegación por defecto; comprobaciones de propiedad por objeto; CORS estrictoRepetir peticiones con los IDs de otro usuario devuelve 404 o 403
DependenciasLockfile en el repositorio; npm ci; auditoría en CI; actions fijadas a un SHA; SRI en los scripts de CDNLa compilación falla ante un CVE de gravedad alta
ServidorSolo 80 y 443 públicos; SSH solo con claves; actualizaciones de seguridad desatendidas; secretos en variables de entorno o en un vaultEl Verificador de Puertos muestra 22, 3306 y 6379 cerrados desde internet
Copias de seguridad3-2-1 con una copia inmutable; restauración probadaÚltima prueba de restauración correcta realizada hace menos de 90 días
CorreoSPF -all, DKIM, DMARC p=reject, MTA-STSEl Verificador DMARC no muestra errores; llegan los informes agregados
MonitorizaciónEventos de autenticación y autorización registrados de forma centralizada; alertas sobre patrones; monitorización externa de disponibilidad, certificados y DNSAlerta de prueba enviada y recibida
RespuestaPlan de incidentes por escrito; security.txt publicado; ejercicio de simulación realizadoPlan revisado en los últimos 12 meses

Cómo encaja con el OWASP Top 10:2025

El OWASP Top 10 es la lista de riesgos de aplicaciones web más citada, y su edición de 2025 reordenó los puestos e introdujo dos categorías nuevas. Si un cliente, un auditor o un marco de cumplimiento te pregunta cómo lo abordas, esta es la correspondencia con las prácticas de esta guía:

OWASP Top 10:2025Prácticas de esta guía
A01 Broken Access Control (control de acceso roto)Denegación por defecto, comprobaciones por objeto, CORS estricto, paneles de administración blindados
A02 Security Misconfiguration (configuración de seguridad incorrecta)Cabeceras de seguridad, HSTS, puertos cerrados, cabeceras de versión eliminadas, listado de directorios desactivado
A03 Software Supply Chain Failures (fallos en la cadena de suministro de software; nueva)Lockfiles, auditorías, actions fijadas, SRI, SBOM, CI con mínimo privilegio
A04 Cryptographic Failures (fallos criptográficos)TLS 1.2+ y 1.3, HSTS, Argon2id, gestión de secretos, copias de seguridad cifradas
A05 Injection (inyección)Consultas parametrizadas, codificación de salida, CSP, validación de archivos subidos
A06 Insecure Design (diseño inseguro)Modelo de amenazas por capa, valores por defecto que fallan en cerrado, rate limiting desde el diseño
A07 Authentication Failures (fallos de autenticación)Reglas de contraseñas del NIST, comprobación de filtraciones, MFA y passkeys, rotación de sesiones
A08 Software or Data Integrity Failures (fallos de integridad del software o de los datos)SRI, dependencias firmadas y fijadas, deserialización segura
A09 Security Logging and Alerting Failures (fallos de registro y alertas de seguridad)Registro centralizado, alertas por patrones, monitorización externa
A10 Mishandling of Exceptional Conditions (gestión incorrecta de condiciones excepcionales; nueva)Fallar en cerrado, respuestas de error uniformes, ninguna traza de pila visible para los usuarios

Nota

El ASVS de OWASP (Application Security Verification Standard) convierte el mismo material en un checklist numerado para auditorías. El nivel 1 es un objetivo realista para cualquier sitio público; el nivel 2, para cualquier cosa que maneje datos personales o financieros.

Comprueba las cabeceras de seguridad de tu sitio en segundos

El Verificador de Cabeceras HTTP gratuito de DNS Robot analiza cualquier URL y califica sus cabeceras de seguridad de la A a la F: HSTS, Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy y Permissions-Policy, con el valor exacto que encontró y lo que falta. Sin registro.

Probar el Verificador de Cabeceras HTTP

Advertisement

Preguntas frecuentes sobre seguridad web

Fuerza HTTPS con TLS moderno y HSTS, envía cabeceras de seguridad estrictas (sobre todo una Content Security Policy), aplica hash a las contraseñas con Argon2id respaldado por MFA y rate limiting, usa consultas parametrizadas y codificación de salida, aplica el control de acceso en el servidor para cada objeto, mantén las dependencias parcheadas y fijadas, cierra los puertos que no uses y registra los eventos de seguridad de forma centralizada. Protege primero el dominio y el DNS, porque todo lo demás depende de que sigas controlando tu nombre.

Herramientas relacionadas

HTTP Headers CheckSSL Certificate CheckPort CheckerDomain Health CheckerDMARC CheckerSubdomain FinderPassword Strength Tester

Artículos relacionados

¿Qué es una cadena de certificados SSL? Cómo funcionaX-Frame-Options Explained: Fix “Refused to Connect” in an iframeError 429 Too Many Requests: Causas y cómo solucionarloWHOIS de dominio: cómo consultar quién es el dueño y leer el registro

Tabla de contenidos

  • Qué significan de verdad las buenas prácticas de seguridad web
  • La pila de seguridad web: seis capas que proteger
  • Capa 1: protege el dominio y el DNS
  • Capa 2: HTTPS y TLS bien configurados
  • Capa 3: cabeceras de seguridad HTTP
  • Capa 4: una autenticación que resista el credential stuffing
  • Sesiones, cookies y CSRF
  • Inyección y XSS: valida la entrada, codifica la salida
  • Broken Access Control: el riesgo número uno
  • Capa 5: dependencias y cadena de suministro de software
  • Capa 6: hardening del servidor (puertos, parches, secretos y copias de seguridad)
  • Autenticación del correo: SPF, DKIM y DMARC
  • Registra, monitoriza y prepárate para la brecha
  • Ponlo a prueba: escáneres, pentests y comprobaciones continuas
  • Checklist de seguridad web
  • Cómo encaja con el OWASP Top 10:2025
  • Preguntas frecuentes