1. Construye una ficha de señales, no una lista de productos
Al terminar tendrás una ficha por servicio con URL, dirección resuelta, redirecciones, cabeceras, métodos declarados, recursos públicos, tecnologías probables, nombres asociados y datos del certificado. Cada fila separará observación, inferencia y verificación pendiente.
Observado
Dato reproducible: código 301, cabecera Server, comentario HTML, SAN o respuesta distinta para un nombre.
Inferido
Hipótesis apoyada por varias señales: proxy probable, framework posible o aplicación alojada por nombre.
Confirmado
Dato contrastado con una segunda fuente, configuración del propietario o comportamiento específico y estable.
Usa una solicitud inexistente autorizada como línea base negativa. Ayuda a reconocer páginas de error uniformes, redirecciones globales y contenido por defecto. No conviertas una versión anunciada en prueba de vulnerabilidad: los banners pueden ocultarse, alterarse o pertenecer a un intermediario.
mkdir -p "$HOME/cubix-web-enum"curl --version | head -n 1curl -sS --max-time 10 -D "$HOME/cubix-web-enum/base-404.headers" -o "$HOME/cubix-web-enum/base-404.html" https://web.lab.example/cubix-no-existe-7f31$Out = Join-Path $HOME 'cubix-web-enum'New-Item -ItemType Directory -Force $Out | Out-Nullcurl.exe --version | Select-Object -First 1curl.exe -sS --max-time 10 -D (Join-Path $Out 'base-404.headers') -o (Join-Path $Out 'base-404.html') https://web.lab.example/cubix-no-existe-7f312. Recorre HTTP sin perder la respuesta original
Empieza por HEAD para obtener metadatos y repite con GET si el servidor trata ambos de forma distinta. No sigas redirecciones en la primera pasada: el código y Location explican cómo se alcanza el destino canónico. Después usa una segunda ejecución con -L y guarda la cadena completa.
curl -sS --max-time 10 -I https://web.lab.example/curl -sS --max-time 10 -D "$HOME/cubix-web-enum/root.headers" -o "$HOME/cubix-web-enum/root.html" https://web.lab.example/curl -sS --max-time 10 -L -D "$HOME/cubix-web-enum/redirect-chain.headers" -o /dev/null https://web.lab.example/curl.exe -sS --max-time 10 -I https://web.lab.example/curl.exe -sS --max-time 10 -D (Join-Path $Out 'root.headers') -o (Join-Path $Out 'root.html') https://web.lab.example/curl.exe -sS --max-time 10 -X OPTIONS -D - -o NUL https://web.lab.example/Registra Server y X-Powered-By como pistas, no como identidad confirmada. Añade Content-Type, Content-Length, Location, Set-Cookie, caché y cabeceras de seguridad. La ausencia de una cabecera solo es relevante tras conocer el contexto, la ruta y el navegador al que protege.
Entrega y plataforma
Server, Via, X-Powered-By, X-Generator y cabeceras del proveedor pueden señalar varias capas distintas.
Sesión y caché
Set-Cookie, Cache-Control, Vary, ETag y Age explican estado, intermediarios y variaciones de contenido.
Política del navegador
CSP, HSTS, X-Content-Type-Options, Referrer-Policy y Permissions-Policy deben leerse con su valor completo.
OPTIONS solicita opciones de comunicación y puede devolver Allow, pero una respuesta vacía no demuestra que no existan otros métodos. Limita esta etapa a métodos seguros. No envíes PUT, DELETE, PATCH o TRACE para «comprobar» el anuncio.
curl -sS --max-time 10 -X OPTIONS -D - -o /dev/null https://web.lab.example/curl -sS --max-time 10 -I https://web.lab.example/3. Revisa lo que el servidor publica voluntariamente
La raíz, robots.txt y sitemap.xml pueden aportar rutas, idiomas y secciones. Según RFC 9309, robots.txt orienta a rastreadores; no protege contenido. Un Disallow no confirma que una ruta exista, sea sensible ni esté dentro del alcance: anótala y pide autorización antes de ampliarlo.
curl -sS --max-time 10 -D "$HOME/cubix-web-enum/robots.headers" -o "$HOME/cubix-web-enum/robots.txt" https://web.lab.example/robots.txtcurl -sS --max-time 10 -D "$HOME/cubix-web-enum/sitemap.headers" -o "$HOME/cubix-web-enum/sitemap.xml" https://web.lab.example/sitemap.xmlInspecciona la página raíz en el navegador y usa «Ver código fuente». Busca el título, etiquetas meta, comentarios, nombres de recursos, rutas de API y atributos de formularios. El HTML y JavaScript entregados son código del cliente; no son el código fuente privado del servidor. Si aparece una credencial o token, no lo uses: registra ubicación, exposición y contexto mínimo y notifícalo.
rg -n -i '<title|generator|script|stylesheet|form|action=|api/|sourceMappingURL' "$HOME/cubix-web-enum/root.html"rg -n -i '<!--|todo|debug|staging|internal' "$HOME/cubix-web-enum/root.html"$Pattern = '<title|generator|script|stylesheet|form|action=|api/|sourceMappingURL|<!--|todo|debug|staging|internal'Select-String -Path (Join-Path $Out 'root.html') -Pattern $Pattern -AllMatchesUna página de bienvenida de nginx, Apache, IIS, un proxy o una plataforma es una señal de despliegue por defecto. Captura título, hash o fragmento no sensible y fecha. No presupongas que representa el origen: puede proceder de un balanceador, CDN, virtual host por defecto o aplicación de mantenimiento.
4. Correlaciona tecnologías con al menos dos señales
OWASP recomienda combinar cabeceras, cookies, HTML, extensiones, archivos característicos y mensajes. Una firma aislada puede estar personalizada o desactualizada. Asigna un nivel de confianza y conserva la evidencia exacta que lo justifica.
Confianza baja
Una sola señal genérica, como Server: nginx o una extensión .php en una URL histórica.
Confianza media
Dos señales coherentes, como meta generator y rutas de recursos propias del mismo CMS.
Confianza alta
Varias firmas estables y confirmación del propietario o una respuesta inequívoca del producto.
Cookies con nombres conocidos, cabeceras del framework, comentarios de compilación y rutas de assets pueden apuntar a una tecnología. Documenta también contradicciones: Server puede describir el proxy mientras una cookie describe la aplicación. Evita buscar CVE hasta confirmar producto, versión y componente expuesto.
5. Relaciona nombres, virtual hosts y certificado sin alterar DNS
Una IP puede servir varios sitios. Recoge únicamente nombres que ya estén autorizados o aparezcan en fuentes del propio servicio: redirecciones, enlaces, DNS entregado por el propietario y SAN del certificado. Valida cada candidato con --resolve: curl conecta a la IP indicada conservando nombre HTTP, SNI y validación TLS.
curl -sS --max-time 10 --resolve web.lab.example:443:192.0.2.20 -D - -o /dev/null https://web.lab.example/curl -sS --max-time 10 --resolve portal.lab.example:443:192.0.2.20 -D - -o /dev/null https://portal.lab.example/Compara código, Location, longitud, título y hash del cuerpo con el virtual host conocido y con un nombre inexistente autorizado. Una diferencia confirma comportamiento por nombre; no confirma por sí sola que la aplicación sea sensible o vulnerable. Para descubrimiento mediante diccionario, continúa con la guía específica de Gobuster y sus límites de ritmo.
openssl s_client -connect 192.0.2.20:443 -servername web.lab.example -verify_hostname web.lab.example -verify_return_error -showcerts </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName$Tcp = [Net.Sockets.TcpClient]::new('web.lab.example', 443)$Tls = [Net.Security.SslStream]::new($Tcp.GetStream(), $false)$Tls.AuthenticateAsClient('web.lab.example')$Cert = [Security.Cryptography.X509Certificates.X509Certificate2]::new($Tls.RemoteCertificate)$Cert | Select-Object Subject, Issuer, NotBefore, NotAfter, Thumbprint$Cert.Extensions | Where-Object Oid -eq '2.5.29.17' | ForEach-Object { $_.Format($true) }$Tls.Dispose(); $Tcp.Dispose()Registra sujeto, emisor, vigencia, SAN y resultado de validación. Los SAN amplían el inventario de nombres, no el permiso de prueba. -showcerts muestra la cadena enviada, pero la documentación de OpenSSL advierte que esa lista no equivale a una cadena ya verificada; por eso el ejemplo también exige validación y nombre esperado.
6. Distingue dato, configuración y riesgo contextual
OPTIONS sin Allow
Observa una respuesta incompleta o una política del intermediario; no concluyas que solo existen GET y HEAD.
Server con versión
Confirma exposición de un banner. La vulnerabilidad exige validar producto real, versión efectiva y configuración.
robots con /admin
Confirma una directiva para rastreadores. No demuestra existencia, acceso público ni autorización para probar la ruta.
CSP ausente
Es una observación de política en esa respuesta; el riesgo depende del contenido, las rutas y otros controles.
SAN con otro nombre
Vincula una identidad al certificado. Puede ser histórico, compartido o fuera del alcance acordado.
Página por defecto
Indica despliegue genérico o ruta de fallback. Identifica la capa que responde antes de atribuirla al origen.
Repite una observación relevante en dos momentos o con dos métodos seguros. Si CDN, WAF o caché cambian la respuesta, conserva ambos resultados y la hora. No intentes eludirlos: la arquitectura observada forma parte de la superficie que debe entenderse.
7. Entrega una ficha que permita decidir el siguiente paso
Crea una fila por URL o nombre con: fecha UTC, IP resuelta, protocolo, código inicial, cadena de redirección, cabeceras relevantes, métodos declarados, metaficheros, título, tecnologías probables y confianza, SAN, vigencia TLS, observación, inferencia y verificación pendiente. Sanea cookies, tokens, datos personales y cuerpos antes de adjuntar evidencia.
- La URL, los nombres, la dirección y el horario constan en el alcance autorizado
- La raíz y una ruta inexistente forman la línea base antes de interpretar diferencias
- La primera respuesta conserva código y Location sin seguir redirecciones
- HEAD, GET y OPTIONS se usan como observación segura; no se envían métodos mutadores
- Server, cookies, HTML y rutas se tratan como señales y se correlacionan
- robots.txt se interpreta como directiva de rastreo, nunca como control de acceso
- El código visible del cliente no se confunde con código fuente del servidor
- Cada virtual host se compara con una respuesta negativa sin desactivar TLS
- El certificado registra SAN, emisor, vigencia y resultado de validación
- La ficha separa observado, inferido, confirmado y pendiente, y elimina datos sensibles
El siguiente paso no es lanzar un escáner indiscriminado. Prioriza componentes confirmados, superficies públicas distintas de la línea base, métodos inesperados verificados por el propietario y configuraciones TLS o de cabeceras con impacto contextual. Para defender, reduce banners innecesarios, retira páginas y comentarios por defecto, protege cada ruta con autorización real, revisa virtual hosts publicados y automatiza inventario y renovación de certificados.
Glosario
Fingerprinting
Identificación probable de una tecnología mediante varias señales observables, sin asumir que una sola firma es concluyente.
Cabecera HTTP
Campo de metadatos de una solicitud o respuesta, como Server, Location, Allow o Content-Security-Policy.
Método seguro
Método HTTP cuya semántica es esencialmente de solo lectura, como GET, HEAD u OPTIONS.
Página por defecto
Contenido genérico instalado por un servidor, proxy, plataforma o producto antes de publicar la aplicación definitiva.
Robots Exclusion Protocol
Convención estandarizada en robots.txt para indicar a rastreadores qué rutas deben o no deben recorrer; no aplica control de acceso.
Código fuente del cliente
HTML, CSS y JavaScript entregados al navegador; es distinto del código que permanece y se ejecuta en el servidor.
Virtual host
Sitio seleccionado por nombre que puede compartir dirección IP y puerto con otros sitios.
Host
Cabecera HTTP que identifica el nombre de destino y permite al servidor seleccionar un virtual host.
SNI
Extensión de TLS con la que el cliente comunica el nombre esperado durante el establecimiento de la conexión.
SAN
Extensión subjectAltName de un certificado que vincula una o más identidades, normalmente nombres DNS, a la clave certificada.
Línea base
Respuesta conocida con la que se comparan otras observaciones para distinguir diferencias reales de comportamiento genérico.
Inferencia
Conclusión provisional apoyada por indicios y pendiente de confirmación independiente.