# Análisis de seguridad del sitio web

URL: https://discuvr.org/security-scan/?hl=es
Last updated: 2026-11-07
MCP tool: `security_scan`

Escanea un dominio: cabeceras de seguridad ausentes, problemas de TLS y archivos expuestos. Cada hallazgo trae la evidencia y el comando exacto para reproducirlo.

Muchos escáneres te dan una nota con letra y una lista de palabras alarmantes. Este también da una nota, pero cada punto que resta está ligado a un hallazgo que muestra la respuesta que obtuvo de verdad y el comando de una línea que te devuelve esa misma respuesta, así que un hallazgo es algo que puedes comprobar, no algo que tengas que creer.

## Qué hace

- Revisa DNS y CAA, SPF y DMARC, el certificado TLS y TLS 1.0/1.1, la redirección a HTTPS, las cabeceras de seguridad, los atributos de las cookies, CORS, los banners de versión, los métodos HTTP, el contenido mixto, 23 rutas sensibles, los listados de directorios, robots.txt, security.txt y 12 puertos de servicio.
- Cada hallazgo incluye la observación sin procesar y un comando de shell para reproducirlo.
- Las comprobaciones que no pudieron ejecutarse se informan como "no comprobado", nunca silenciosamente como aprobadas.
- Los informes se descargan en Markdown o JSON.

## Cómo funciona

1. Introduce un dominio del que seas responsable.
2. El escaneo ejecuta sondeos pasivos: solicitudes ordinarias, sin explotación.
3. Lee los hallazgos, cada uno con su evidencia, y verifica los que importan.

## Ningún hallazgo está inventado

El escáner no contiene ningún modelo de lenguaje. La gravedad, el impacto y la corrección son fijos para cada comprobación, y cada hallazgo se genera a partir de una observación real. El informe en pantalla y las descargas en Markdown y JSON se construyen con los mismos hallazgos, sin ningún modelo de por medio.

## Cómo se calcula la nota

La puntuación parte de 100 y pierde 34 puntos por hallazgo crítico, 13 por alto, 5 por medio y 1,5 por bajo, con un tope por gravedad (alto 45, medio 22, bajo 9). Los resultados informativos y los aprobados no restan. 90 o más es una A, 75 una B, 60 una C, 40 una D y menos, una F. Un solo archivo .env expuesto o un puerto de base de datos accesible lleva un sitio limpio de 100 a 66, una C; dos hallazgos así dan 32, una F.

## Cómo evita las falsas alarmas

Antes de probar rutas como /.git/HEAD o /backup.sql, el escáner pide una dirección aleatoria que no puede existir y anota cómo responde el sitio. Una ruta solo se marca como expuesta si devuelve HTTP 200, difiere de esa respuesta de referencia y coincide con la firma propia del archivo, así que un sitio que responde a cualquier URL con su página de inicio no se llena de hallazgos críticos.

## Un informe limpio no es un certificado

Estas son comprobaciones pasivas contra un sitio en funcionamiento. No cubren la lógica de la aplicación, la autenticación, el control de acceso ni nada que esté detrás de un inicio de sesión, que es por donde suelen empezar las brechas reales. Las comprobaciones que no pudieron completarse se listan como no comprobadas exactamente por esta razón: una aprobación derivada de una conexión fallida es una falsa tranquilidad, y un escaneo sin hallazgos significa que no se encontró nada, no que no haya nada.

## Escanea solo lo que es tuyo

Escanea dominios que poseas o para los que tengas permiso por escrito para probar. La herramienta rechaza hosts que resuelven a direcciones privadas o internas, y está limitada por IP, pero la autorización sigue siendo tu responsabilidad.

## Preguntas

**¿Es esto un ataque activo?**

No. Hace peticiones GET, HEAD y OPTIONS normales, negociaciones TLS (incluidos intentos con TLS 1.0 y 1.1), consultas DNS mediante DNS sobre HTTPS de Cloudflare y conexiones TCP simples a 12 puertos. No se explota nada, no se envía ningún formulario y no se modifica nada.

**¿Puedo escanear cualquier sitio web?**

Solo los que posees o para los que estás autorizado a probar. Escanear infraestructura de terceros sin permiso puede ser ilegal donde te encuentres.

**¿Por qué una comprobación dice "no comprobado"?**

Porque no pudo completarse, normalmente porque nada respondió en ese origen. Se informa honestamente en lugar de registrarse como una aprobación.

**¿Puedo exportar el informe?**

Sí, en Markdown o JSON, durante una hora: el informe se guarda en la caché del servidor ese tiempo para que funcionen las descargas y luego caduca. Ninguna exportación usa un modelo. El registro de uso guarda el número de hallazgos y la nota, no el dominio.

**¿Qué archivos y puertos comprueba?**

Archivos: 23 rutas fijas, entre ellas /.git/HEAD, /.git/config, /.env, /.env.local, /.env.production, /.aws/credentials, /id_rsa, /backup.zip, /backup.sql, /dump.sql, /wp-config.php.bak, /phpinfo.php, /server-status, /actuator/env, y cada una se marca solo si la respuesta coincide con la firma propia de ese archivo; /.well-known/security.txt suma a tu favor si está publicado. Puertos: una conexión TCP simple, nunca un intento de inicio de sesión, a 21 FTP, 23 Telnet, 25 SMTP, 3306 MySQL, 5432 PostgreSQL, 6379 Redis, 27017 MongoDB, 9200 Elasticsearch, 3389 RDP, 5900 VNC, 11211 Memcached, 8080. Un puerto de base de datos accesible (MySQL, PostgreSQL, Redis, MongoDB, Elasticsearch) o Telnet se califica como crítico.

**¿Qué marcan las comprobaciones de SPF y DMARC?**

Ambos registros se leen del DNS público, incluso si el sitio no envía correo, porque sin ellos cualquiera puede enviar correo que dice venir de tu dominio. No tener registro SPF es gravedad media; un SPF que contiene +all, que autoriza a cualquier servidor de internet, es alta. No tener registro DMARC en _dmarc es media; p=none (o sin etiqueta p=) solo monitoriza y es baja; p=quarantine o p=reject se aprueba. Un dominio que no envía ningún correo puede publicar v=spf1 -all.

**¿Qué cabeceras de seguridad revisa y qué valor se aprueba?**

Seis cabeceras en la respuesta de tu página de inicio. Si faltan, HSTS y Content-Security-Policy son gravedad alta, X-Content-Type-Options y X-Frame-Options media, Referrer-Policy y Permissions-Policy baja. Strict-Transport-Security necesita un max-age de al menos 15552000 (180 días): uno menor es baja y max-age=0 es media. Content-Security-Policy se marca como debilitada (media) si script-src permite 'unsafe-inline', la política permite 'unsafe-eval' o default-src o script-src tienen un comodín * suelto. X-Content-Type-Options debe ser exactamente nosniff. X-Frame-Options debe ser DENY o SAMEORIGIN, y no hace falta si la CSP define frame-ancestors. Referrer-Policy solo se marca con unsafe-url o no-referrer-when-downgrade. Permissions-Policy solo tiene que estar presente. Cada cabecera ausente o débil incluye un comando curl -sI para que lo compruebes tú mismo.

**¿Cómo comprueba los atributos de las cookies (Secure, HttpOnly, SameSite)?**

Lee cada cabecera Set-Cookie de la respuesta de tu página de inicio (hasta 12 cookies) y comprueba en cada una Secure, HttpOnly y SameSite. Si falta Secure o HttpOnly la gravedad es media; si solo falta SameSite es baja, y SameSite=None sin Secure se señala porque los navegadores rechazan esa cookie. Una cookie con los tres atributos se aprueba. La corrección habitual es Secure; HttpOnly; SameSite=Lax (en Django: SESSION_COOKIE_SECURE, SESSION_COOKIE_HTTPONLY y SESSION_COOKIE_SAMESITE). El análisis no inicia sesión, así que no ve las cookies que se crean solo después del login. Compruébalo tú mismo con curl -sI https://your-site/ | grep -i set-cookie

**¿Cómo funciona la comprobación de CORS y cuándo es crítica?**

Envía una petición GET a tu página de inicio con Origin: https://scanner-probe.example y lee Access-Control-Allow-Origin y Access-Control-Allow-Credentials en la respuesta. Sin cabecera Access-Control-Allow-Origin, o con un origen fijo que no repite el de la prueba, se aprueba. Devolver el origen de la prueba junto con Access-Control-Allow-Credentials: true es crítico, porque cualquier sitio que visite un usuario con sesión iniciada podría leer sus respuestas. Devolver el origen sin credenciales es medio. Un comodín * es bajo, o medio si además se permiten credenciales (los navegadores rechazan esa combinación). Solo se prueba la página de inicio y no se envía la petición previa OPTIONS, así que revisa las rutas de tu API por separado con curl -sI -H "Origin: https://scanner-probe.example" https://your-site/api/ | grep -i access-control

**¿Qué comprueba el análisis TLS (caducidad del certificado, TLS 1.0 y 1.1)?**

Se conecta al puerto 443 y valida la cadena del certificado y el nombre de host. Un certificado que no valida es de gravedad alta, uno caducado se marca además como crítico y uno al que le quedan menos de 15 días es de gravedad media; si no, se muestran el sujeto, el emisor, la fecha de caducidad y los nombres SAN como aprobado. El protocolo negociado debe ser TLS 1.2 o TLS 1.3; cualquier versión anterior es alta. Después intenta por separado un handshake TLS 1.0 y otro TLS 1.1: si el servidor acepta alguno, el hallazgo es medio, porque ambos están obsoletos según el RFC 8996. Si el propio OpenSSL del escáner no puede ofrecer la versión antigua, no informa nada en lugar de adivinar. La corrección en nginx es ssl_protocols TLSv1.2 TLSv1.3; Comprueba las fechas tú mismo con echo | openssl s_client -connect your-site:443 -servername your-site 2>/dev/null | openssl x509 -noout -dates

**¿Comprueba que HTTP redirige a HTTPS?**

Sí. Solicita http://your-site/ sin seguir redirecciones. Un 301 o 308 a una dirección https:// se aprueba. Un 302, 303 o 307 a HTTPS es bajo, porque los navegadores no recuerdan una redirección temporal y cada visita nueva empieza con una petición sin cifrar. Una página servida por HTTP sin cifrar (respuesta 2xx) es alta. Si el puerto 80 no responde, es informativo, no un fallo. La corrección en nginx es server { listen 80; return 301 https://$host$request_uri; }, y después añade Strict-Transport-Security. Compruébalo tú mismo con curl -I http://your-site/

**¿Qué métodos HTTP señala (TRACE, PUT, DELETE)?**

Envía una sola petición OPTIONS a tu página de inicio y lee la cabecera Allow, o Access-Control-Allow-Methods si falta Allow. Si se anuncia TRACE, TRACK, PUT o DELETE, la gravedad es media; PATCH o CONNECT por sí solos son de gravedad baja; si solo hay métodos estándar de lectura, se aprueba. Si el servidor no envía ninguna de las dos cabeceras, no se informa nada. Anunciar un método no demuestra que funcione, así que confírmalo antes de cambiar nada. TRACE puede devolver al cliente las cabeceras de la petición, cookies incluidas (Cross-Site Tracing). nginx rechaza TRACE por defecto; en Apache configura TraceEnable Off. Limita PUT y DELETE a las rutas de API que los necesitan, con autenticación. Compruébalo tú mismo con curl -X OPTIONS -i https://your-site/

**¿Cómo detecta el listado de directorios ("Index of /")?**

Solicita 7 rutas: /, /static/, /assets/, /uploads/, /images/, /files/ y /backup/. Una ruta que responde HTTP 200 con una página cuyo título o encabezado principal empieza por "Index of /" se marca con gravedad media (CWE-548), porque el listado muestra archivos que no están enlazados en ningún sitio, como copias de seguridad, exportaciones y versiones antiguas. Si ninguna lo hace, la comprobación se aprueba; si no se puede acceder al sitio, se indica como no realizada. La corrección en nginx es autoindex off; (el valor por defecto, así que busca un autoindex on explícito), en Apache Options -Indexes, y después saca todo lo sensible de la raíz web. Compruébalo tú mismo con curl -s https://your-site/uploads/ | head -20

**¿Detecta contenido mixto y formularios que envían por HTTP?**

Sí, en la página de inicio. Lee el HTML tal como se sirve (no ejecuta JavaScript) y enumera cada etiqueta script, link, iframe o img cuyo src o href empieza por http://. Si alguna es un archivo .js o .css, el hallazgo es medio, porque un script o una hoja de estilos sustituidos en tránsito se ejecutan dentro de tu página HTTPS; si solo hay imágenes y marcos, es bajo; si no hay ninguna, se aprueba (CWE-311). Un formulario cuyo action empieza por http:// se marca como alto (CWE-319), porque todo lo que se escribe en él, contraseñas incluidas, viaja sin cifrar. La solución es cambiar esas URL a https:// o hacerlas relativas, y añadir la cabecera Content-Security-Policy: upgrade-insecure-requests como red de seguridad. Compruébalo tú mismo con curl -s https://your-site/ | grep -Eo "(src|href|action)=.http://[^ >]*"

**¿Qué revisa en robots.txt y security.txt?**

robots.txt: descarga /robots.txt y, si responde HTTP 200 como archivo de texto, lee las líneas Disallow de sus primeros 8000 caracteres. Una ruta Disallow que contiene admin, internal, private, backup, config, staging, test, api, secret, dev se marca como baja (CWE-200): robots.txt es público y solo pide a los rastreadores respetuosos que no entren, así que listar esas rutas las anuncia. Protégelas con inicio de sesión y usa noindex para dejar páginas fuera del buscador. security.txt: solicita /.well-known/security.txt, la ubicación que fija el RFC 9116, y lo cuenta a tu favor cuando el archivo tiene una línea Contact:. No tenerlo no resta puntos. El RFC 9116 exige además un campo Expires:, que el escaneo no comprueba, así que publica ambos, por ejemplo Contact: mailto:security@your-site, Expires: 2027-06-30T23:00:00Z. Compruébalo tú mismo con curl -s https://your-site/.well-known/security.txt

**¿Qué busca la comprobación de CAA y cómo añado un registro CAA?**

Consulta los registros CAA (RFC 8659) del nombre de host que escribiste, mediante DNS sobre HTTPS de Cloudflare. Si encuentra alguno, la comprobación se aprueba y la evidencia muestra hasta 5; si no encuentra ninguno, indica "No CAA record" con gravedad baja, porque entonces cualquier autoridad de certificación pública puede emitir un certificado para ese nombre. Un registro CAA enumera las CA que realmente usas, por ejemplo your-site. IN CAA 0 issue "letsencrypt.org", más 0 iodef "mailto:security@your-site" para recibir avisos. Añade una línea issue por cada CA que uses, y una línea issuewild si los certificados comodín deben venir de otra CA. Compruébalo tú mismo con dig CAA your-site

**¿Por qué al analizar www o un subdominio indica que no hay CAA, SPF o DMARC?**

Cada comprobación de DNS se hace sobre el nombre exacto que escribiste, así que www.example.com se consulta como www.example.com, no como example.com, y los tres registros se heredan de forma distinta. CAA: una autoridad de certificación que no encuentra registro CAA en www.example.com sube a example.com y usa ese (RFC 8659, sección 3), así que "No CAA record" en un subdominio puede ser una falsa alarma. DMARC: los receptores recurren a la política del dominio organizativo, que puede fijar una política aparte para subdominios con sp= (RFC 9989, que deja obsoleto el RFC 7489), así que la falta de registro en _dmarc.www.example.com suele quedar cubierta por _dmarc.example.com. SPF: no hay herencia (RFC 7208), así que "No SPF record" es correcto para ese nombre; un nombre de host que no envía correo puede publicar v=spf1 -all. Una consulta DNS que falla también aparece como registro ausente. Analiza también el dominio sin www, o confírmalo con dig CAA example.com y dig TXT _dmarc.example.com

## Más en Privacidad y seguridad

- [Depuración de imágenes](https://discuvr.org/image-scrub/?hl=es)

## Se usa a menudo con

- [Cuál es mi IP](https://discuvr.org/what-is-my-ip/?hl=es)
- [Generador de Contraseñas](https://discuvr.org/password-generator/?hl=es)

---

Part of Discuvr (https://discuvr.org/): Discuvr is a collection of free, focused tools for day-to-day professional work - office and data utilities, legal and compliance helpers, privacy and security checks, and developer formatters. Every tool has its own page, and most can also be called from ChatGPT or Claude over MCP.
