Un fichero SQL alcanzable desde internet, y dentro un token de administrador en texto plano que abría una puerta en otra entidad del mismo grupo.
Del barrido de directorios al acceso total sin credenciales
El trabajo empezó por mapear la aplicación con ffuf, una herramienta que recorre un sitio probando nombres de una lista para descubrir páginas y carpetas que no están enlazadas desde ninguna parte. Entre lo que devolvió había un directorio que no tenía por qué estar ahí: http://client.example.com/database.
Una carpeta llamada "database" accesible públicamente ya es una señal de alarma por sí sola, y dentro había otra: /database/migrations/. Las carpetas de migraciones guardan los ficheros que crean o actualizan el esquema de una base de datos, es decir, maquinaria interna del proyecto. Encontrarlas servidas por el servidor web significa que algo que solo debía existir del lado de los desarrolladores había acabado publicado en internet.
El paso siguiente fue buscar ficheros sensibles dentro de esa carpeta con un barrido dirigido por extensiones, usando un diccionario propio y probando .sql, .txt y .zip. La respuesta útil fue initsql.sql. Un fichero SQL de inicialización sirve para crear y poblar una base de datos, así que es de los que con más frecuencia llevan datos de arranque, cuentas de servicio o claves.
Dentro de initsql.sql había un token de seguridad escrito en texto plano. Lo que convirtió el hallazgo en grave no fue solo que estuviera ahí, sino de quién era: no pertenecía a la aplicación que se estaba auditando, sino a otra entidad del mismo grupo empresarial. Un secreto guardado en claro dentro de un fichero de la aplicación es CWE-798, "Use of Hard-coded Credentials"; ese fichero servido a internet es CWE-552, "Files or Directories Accessible to External Parties"; y la carpeta publicada por descuido es lo que el OWASP Top 10:2025 llama A02, "Security Misconfiguration", que enumera entre sus condiciones tener habilitado o instalado lo que no hace falta: puertos, servicios, páginas, cuentas, frameworks de pruebas o privilegios que sobran.
El equipo identificó a qué API pertenecía ese token y lo probó contra ella. Seguía siendo válido y correspondía a una cuenta de administrador, o sea, acceso total: no a la aplicación auditada, sino a un sistema de otra entidad del grupo que ni siquiera formaba parte del alcance del trabajo.
RECONSTRUCCIÓN · SIN DATOS DE CLIENTE
Cómo un nombre de un diccionario llegó a una cuenta de administrador de otra empresa
- CWE-552
- CWE-798
-
El barrido de directorios
DICCIONARIO · ffuf
- admin
- assets
- backup
- config
- database
ENCONTRADO
GET /database HTTP/1.1 Host: client.example.comUna herramienta que prueba nombres en orden para encontrar lo que no está enlazado desde ninguna parte.
-
Lo que había dentro
RAÍZ PÚBLICA DEL SERVIDOR WEB
client.example.com/ └── database/ └── migrations/SOLO DEL LADO DE DESARROLLO (CWE-552)
Las carpetas de migraciones construyen el esquema de la base de datos. Son maquinaria interna del proyecto, publicada por descuido.
-
El barrido por extensiones
DICCIONARIO PROPIO
- .sql
- .txt
- .zip
/database/migrations/initsql.sqlUn fichero SQL de inicialización sirve para crear y poblar una base de datos, así que es de los que con más frecuencia llevan datos de arranque, cuentas de servicio o claves.
-
El secreto, y de quién era
TEXTO PLANO (CWE-798)
initsql.sql ... 'EXAMPLE-TOKEN-Z9Y8X7W6' ...Aplicación auditada
Otra entidad, mismo grupo
ALCANCE DEL TRABAJOEl caso publica que el token estaba en texto plano dentro del fichero. No publica el esquema de la base de datos, así que la figura no lo dibuja.
Seguía siendo válido. Administrador. En un sistema fuera del alcance.
Clasificado como crítico. El mismo barrido automatizado que lo encontró aquí lo encontraría para cualquiera.
Lo que se recomendó
/var/www/html/database/migrations/initsql.sql
/srv/app/db/migrations/initsql.sql
fuera de la raíz pública
'EXAMPLE-TOKEN-Z9Y8X7W6'
${API_TOKEN}
gestor de secretos o entorno
Un secreto no va ni en el código fuente ni en ficheros de base de datos. Cualquier token que haya llegado a estar publicado se trata como comprometido y se invalida.
El impacto se clasificó como crítico. Cualquiera que diera con ese fichero SQL expuesto, y para dar con él bastaba el mismo barrido automatizado que lo encontró aquí, podía entrar sin credenciales y con privilegios de administrador: para ver, modificar o borrar datos sensibles; añadir o quitar cuentas de usuario; acceder a la analítica y a los registros privados; y causar un daño serio a la operación.
La causa raíz es dejar ficheros sensibles en un directorio alcanzable desde internet. Esos ficheros no deberían ser accesibles nunca desde fuera, y un token no debe guardarse en texto plano ni dentro del código fuente ni dentro de ficheros de base de datos. Lo que se recomendó fue sacar el directorio de migraciones de la raíz pública del servidor web, mover los secretos a un gestor de secretos o a variables de entorno que no viajen con el despliegue, y tratar como comprometido e invalidar cualquier token que haya llegado a estar publicado.