Encuentra los endpoints del servidor que tu escáner no puede alcanzar
Los crawlers dinámicos solo encuentran los endpoints que pueden activar desde la interfaz. El código muerto y los bundles protegidos por autenticación esconden endpoints reales del servidor en el JavaScript del cliente — el análisis estático de SolidPoint los encuentra.
Lo que el rastreo dinámico pasa por alto
Los crawlers dinámicos descubren endpoints simulando la interacción del usuario: clics, envíos de formularios, navegación. Tres categorías de endpoints del servidor suelen escapar a este enfoque:
Código muerto — funciones que existen en el bundle de JavaScript pero nunca se invocan desde la interfaz. Ninguna interacción puede activarlas.
Módulos sin instanciar — clases de clientes de API y helpers de solicitudes que se incluyen en el bundle pero no se utilizan en la página actual.
Bundles protegidos por autenticación — JavaScript para paneles de administración, funciones autenticadas e interfaces de depuración que se envían a todos los usuarios, incluidos los anónimos. La interfaz oculta estas funciones, pero el código — y los endpoints del servidor que referencia — está a la vista.
1 const api = "/application/iuT6ei/";
2 const remove = async (params) => {
3 if (prompt("Enter 'yes' to remove") !== "yes") return;
4 await fetch(api + "interface/remove/handle", {
5 method: "POST", body: JSON.stringify(params)
6 });
7 };
8 const removeByID = (id) => remove({ ident: id }); Estas funciones nunca se llaman en ningún lugar de la página. Ningún botón las activa. Ningún enlace las referencia. Un crawler dinámico que simule clics de usuario nunca ejecutará este código. Pero la llamada a fetch en la línea 4 referencia un endpoint activo del servidor que un escáner debería probar. En nuestra investigación encontramos este patrón exacto en un plugin de WordPress con más de 70.000 instalaciones activas.
1 class ApiClient {
2 baseURL = '/api/v2/';
3
4 async sendData(payload) {
5 await fetch(this.baseURL + 'data/ingest', {
6 method: 'POST', body: JSON.stringify(payload)
7 });
8 }
9 } Si esta clase no se instancia en la página, la llamada a fetch de la línea 5 es invisible para los crawlers. La coincidencia de URLs por regex tampoco la encontrará — la URL está dividida entre un campo de clase y un método, y requiere resolver this.baseURL. Los escáneres de la industria probados en nuestra investigación — incluidos Acunetix, Burp Scanner, HCL AppScan, Detectify y PT BlackBox Scanner — no encontraron ningún endpoint oculto en código como este.
Estos no son casos excepcionales. En nuestras pruebas sobre cinco aplicaciones de referencia, encontramos bundles de JavaScript del lado del cliente que contenían endpoints para paneles de administración, funciones autenticadas, funciones deshabilitadas e interfaces de depuración. El código del lado del servidor detrás de estos endpoints estaba activo y era potencialmente explotable.
Cómo funciona el análisis estático de SolidPoint
Todos los escáneres rastrean HTML y simulan clics. SolidPoint añade una tercera capa:
Rastreo estático
Enlaces HTML, formularios y marcado estándar. La base que hace cualquier escáner.
Rastreo dinámico
Interacción con navegador headless — simulando clics, envíos de formularios y navegación.
Análisis estático de JavaScript
Análisis a nivel de AST de todo el JavaScript de la página, incluyendo código muerto y bundles protegidos por autenticación. Este es el diferenciador de SolidPoint.
Dentro del motor de análisis estático
Análisis multi-pasada
Cuatro pasadas sobre el AST de JavaScript acumulan conocimiento sobre los valores de las variables, los argumentos de las funciones y los valores de retorno, construyendo una imagen progresivamente más completa del flujo de datos del programa.
Recorrido de cadenas de llamadas
Rastrea el flujo de datos a través de hasta 5 niveles de llamadas a funciones anidadas — resolviendo argumentos, valores de retorno y variables globales compartidas entre invocadores.
Análisis de código muerto
Visita todos los nodos del AST sin importar si son alcanzables — incluyendo funciones nunca invocadas y ramas muertas. Código que el análisis dinámico omite por completo.
Descubrimiento tras autenticación
Los bundles de JS del cliente suelen enviar código para paneles de administración y funciones autenticadas a todos los usuarios. El analizador encuentra esos endpoints sin credenciales.
OOP y resolución de clases
Resuelve this en clases ES6 y en patrones basados en prototipos. Rastrea baseURL desde la asignación en el constructor hasta su uso en métodos.
Reconocimiento de sinks AJAX
Identifica patrones de envío de solicitudes en fetch, $.ajax/$.post de jQuery, axios, $http de AngularJS y asignaciones a window.location.
Resolución de módulos consciente del bundler
Reconoce estructuras de bundle de Webpack y Browserify, extrae los módulos individuales y resuelve llamadas a require() y exports a través de límites entre módulos.
Análisis de página completa
Analiza todos los scripts de la página como una unidad única — resolviendo globales definidos en etiquetas de script inline y usados en archivos JavaScript externos.
Revisado por pares y publicado en una revista
Sigalov, D., Gamayunov, D. "Finding Server-Side Endpoints with Static Analysis of Client-Side JavaScript." ESORICS 2023 Workshops, LNCS vol. 14399, pp. 442–458. Springer, 2024.
Primer método que aplica análisis estático no trivial del JavaScript del cliente para descubrir endpoints de servidor en escaneos de seguridad de caja negra. Publicado en el European Symposium on Research in Computer Security y ampliado en un artículo de revista completo en el Journal of Information Security and Applications de Elsevier. Investigación de Daniil Sigalov y Dennis Gamayunov (Universidad Estatal de Moscú Lomonosov / SolidSoft LLC).
View on Springer →Evaluation results
En OWASP Juice Shop — una aplicación de página única que envía todo el código cliente de la API a usuarios no autenticados — nuestro análisis encontró 36 endpoints de servidor. El mejor crawler dinámico encontró 13.
En MyBB encontramos 77 endpoints. El siguiente mejor resultado fue 68 (Arachni).
Probamos cinco escáneres de la industria — Acunetix, Burp Scanner, HCL AppScan, Detectify y PT BlackBox Scanner — contra un benchmark con 17 endpoints (14 ocultos). Ninguno encontró endpoints ocultos. Nuestro prototipo encontró los 17.
Los resultados varían según la complejidad de la aplicación. En WebGoat, cuyo JS del cliente usa herencia de clases y bundlers AMD más allá de nuestro soporte actual, el mejor crawler dinámico (Arachni) encontró 78 endpoints frente a 12 del análisis estático. Por eso usamos ambos métodos juntos.
El análisis se completó en menos de 30 segundos por página en todos los benchmarks. El análisis de la aplicación completa de MyBB (la ejecución más larga) tomó 5 minutos.
Los componentes open source y los datos completos del experimento están disponibles públicamente para su verificación.
Por qué importan los endpoints ocultos
Cada endpoint que tu escáner pasa por alto es un endpoint que no recibe ninguna prueba de vulnerabilidades. Se queda en producción, sin probar, hasta que alguien lo encuentra.
Endpoints faltantes a menudo significan controles de acceso faltantes
Los paneles de administración, las funciones autenticadas y las interfaces de depuración accedidas a través de endpoints ocultos con frecuencia carecen de verificaciones de autorización en el servidor — la interfaz era la única barrera. Cuando un escáner encuentra y prueba estos endpoints, aparecen vulnerabilidades de Broken Access Control. Cuando no los encuentra, no aparecen. Broken Access Control ha sido la categoría nº1 del OWASP Top 10 desde 2021.
Un descubrimiento incompleto significa cobertura incompleta
En nuestras pruebas de referencia, el mejor crawler dinámico encontró 13 endpoints en una aplicación de página única donde había 36. Esos 23 endpoints no probados incluían rutas de API para carga de archivos, administración de usuarios y exportación de datos — funcionalidad activa en el servidor que aceptaba solicitudes sin autenticar.
Tu alcance de cumplimiento tiene un punto ciego
PCI DSS 4.0.1, SOC 2 e ISO 27001 exigen pruebas de seguridad de aplicaciones web. Estos marcos asumen que tu escáner está probando toda la aplicación. Si el descubrimiento de endpoints es incompleto, tu alcance de pruebas también lo es — y ninguna auditoría detectará la brecha, porque los endpoints faltantes no aparecen en ningún informe.
Qué encuentra cada método de descubrimiento
| Capacidad de descubrimiento | Rastreo dinámico | Coincidencia de URLs por regex | Análisis estático de SolidPoint |
|---|---|---|---|
| Enlaces HTML y formularios | Yes | N/A | Yes |
| Solicitudes JS activables desde la UI | Yes | Partial | Yes |
| Código muerto (funciones nunca invocadas) | No | Partial | Yes |
| Endpoints tras autenticación (paneles de administración) | With credentials * | Partial | Yes |
| URLs construidas desde variables en código muerto | No | No | Yes |
| Métodos de clases sin instanciar | No | No | Yes |
| Cadenas de llamadas en código no activable (3–5 niveles) | No | No | Yes |
* Solo con credenciales válidas para ese rol. Sin autenticación, los crawlers dinámicos pasan estos completamente por alto.
Lo que aún no cubrimos
El análisis estático de JavaScript complementa el rastreo dinámico — no lo reemplaza. Nuestro analizador trabaja junto con el rastreo con navegador headless y el rastreo estático tradicional. Juntas, las tres capas producen el mapa de superficie de ataque más completo.
Algunos patrones de JavaScript siguen siendo desafiantes para el análisis estático: sistemas de eventos específicos de frameworks complejos, jerarquías de herencia de clases y endpoints construidos enteramente a partir de datos del DOM en tiempo de ejecución. Estamos ampliando activamente la cobertura en estas áreas.