Si te dedicas a lanzar escaneos automatizados y a pelearte por las mismas vulnerabilidades de siempre, te estás perdiendo lo realmente valioso. Está ahí, en texto plano.
Archivos JavaScript.
La mayoría de los investigadores se los saltan. Lanzan su escáner, recogen las victorias fáciles y pasan al siguiente objetivo. Mientras tanto, la aplicación está literalmente regalando sus secretos en archivos que cualquiera puede leer.
Esto es lo que he encontrado simplemente leyendo archivos JavaScript a lo largo de los años:
- Claves de API hardcodeadas con permisos de administrador
- Endpoints internos que no deberían haber sido públicos
- Mapas completos de rutas API, incluidas las de funcionalidades "ocultas"
- Lógica de autorización que revelaba exactamente cómo saltársela
- Comentarios de desarrolladores describiendo problemas conocidos que nunca arreglaron
Esto último siempre me llama la atención. Desarrolladores dejando TODOs y FIXMEs sobre problemas de seguridad que conocen pero que no han tenido tiempo de arreglar. Es como dejar una nota en la puerta diciendo "la cerradura está rota."
No necesitas herramientas sofisticadas para esto. Abre DevTools. Lee el código. Busca palabras clave como api, token, secret, admin, internal, /v1/, TODO, FIXME. Sigue el flujo de datos. Mira dónde se guardan los tokens. Mira a dónde van las peticiones. Mira lo que el frontend sabe y que el backend asumía que nadie vería.
// Ejemplo de lo que aparece al leer el bundle de verdad
const ADMIN_API = "https://api-internal.example.com/v2";
const DEBUG_TOKEN = "eyJhbGciOiJIUzI1NiJ9..."; // TODO: quitar antes de prod
function getProvisioningKey() {
return fetch(ADMIN_API + "/_debug/bootstrap").then(r => r.json());
}Los desarrolladores escriben código para que funcione. Los atacantes lo leen buscando oportunidades.
La mayoría de las aplicaciones empaquetan su código frontend en unos pocos archivos JavaScript. A veces minificados, a veces no. En cualquier caso, la lógica está ahí. Los endpoints están ahí. Las reglas de negocio están ahí. Y si alguien fue perezoso con las variables de entorno o hardcodeó algo que no debía, eso también está ahí.
Quiero compartir un hallazgo que reporté en HackerOne y que empezó exactamente así.
El flujo fue el siguiente:
Lancé mi automatización de reconocimiento contra el objetivo. Reconocimiento profundo, no un simple escaneo de subdominios. El tipo de reconocimiento que lleva tiempo pero que saca a la luz cosas que un escaneo superficial no detecta.
Los resultados revelaron algunos subdominios interesantes. Paneles de desarrollo y administración que no deberían haber estado expuestos. Los patrones de nombres los hacían fáciles de identificar una vez que sabías qué buscar.
Empecé a revisar los archivos JavaScript de esos subdominios. No escanearlos. Leerlos. Mirar el código, entender qué hacía la aplicación, mapear los endpoints a los que llamaba.
Encontré varios endpoints de API referenciados en el código del frontend. La mayoría se comportaban como era de esperar. Autenticación requerida, controles de acceso adecuados, nada inusual.
Uno de ellos no.
Este endpoint se podía llamar sin ningún tipo de autenticación. Sin token, sin sesión, sin credenciales de ningún tipo. Simplemente lo llamabas y respondía. Pero no solo respondía con datos. Respondía con un JWT válido.
$ curl https://dev-admin.target.example.com/api/v1/session/init
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"role": "admin",
"expires_in": 86400
}Un JWT válido con acceso de administrador.
A partir de ahí, acceso completo al panel de administración. Gestión de usuarios, descuentos, catálogo de productos, todo. Crear usuarios, eliminar usuarios, modificar precios, añadir o quitar productos. Control administrativo total sobre la plataforma.
La parte interesante es que se trataba de una versión de desarrollo del panel de administración. Pero no funcionaba con datos de prueba. Contenía una copia completa de la base de datos de producción. Datos reales de clientes. Cuentas de usuario reales. Todo real.
La cadena fue sencilla:
- Reconocimiento profundo saca a la luz subdominios de desarrollo expuestos
- Los archivos JavaScript de esos subdominios revelan endpoints de API
- Un endpoint devuelve un JWT de administrador válido sin autenticación
- El JWT da acceso completo al panel de administración con datos de producción
Cada paso de esa cadena empezó leyendo código que era accesible públicamente. Nada de explotación de corrupción de memoria. Nada de cadenas de ataque complejas. Solo leer lo que ya estaba ahí y probar lo que hacía.
Por eso sigo diciendo que saltarse los archivos JavaScript es un error. La aplicación te lo está contando todo. Los endpoints con los que habla. Los parámetros que envía. Los tokens que almacena. Las funcionalidades que oculta detrás de flags. Las rutas de administración que conoce pero que no muestra en la navegación.
Todo está en el código. Solo tienes que leerlo.
La severidad de ese reporte fue clasificada como High. Te dejo sacar tus propias conclusiones.
Si aún no has hecho del análisis de JavaScript una parte fundamental de tu metodología, empieza ya. Antes de tu próximo escaneo, antes de tu próxima ejecución automatizada, abre los archivos JS y léelos. Puede que te sorprenda lo que encuentres.
