Aprende › Escalada de privilegios en Linux

Contraseñas en archivos: cómo se filtran credenciales en servidores y cómo encontrarlas

· 10 min de lectura

Aprende dónde suelen esconderse contraseñas en los sistemas (archivos .env, scripts, configuraciones, historiales, copias de seguridad), cómo se buscan de forma metódica en un laboratorio, por qué la reutilización las convierte en un desastre y cómo gestionar secretos sin dejarlos en texto plano.

En las películas los atacantes crackean contraseñas tecleando a toda velocidad; en la vida real, muchas veces simplemente las leen de un archivo. Variables de entorno de aplicaciones, scripts con curl -u usuario:clave, copias de seguridad con wp-config.php dentro, historiales de shell con un comando mal escrito. Un servidor lleva semanas publicando esos secretos sin que nadie se dé cuenta hasta que alguien los busca.

En los laboratorios de whoami-labs, el patrón «encuentra una shell como un usuario poco privilegiado → busca contraseñas en archivos → reutilízalas para pasar a otro usuario o a otra máquina» aparece en casi todos los retos. Y en situaciones reales, la reutilización de contraseñas entre un .env y la base de datos de producción es responsable de buena parte de las filtraciones masivas de los últimos años.

En esta lección vas a ver dónde suelen esconderse las credenciales en un sistema, cómo buscarlas de forma metódica, cómo aprovecharlas en movimiento lateral y cómo gestionar los secretos para que una filtración de un archivo no se convierta en el fin del mundo.

Practica solo en sistemas propios o en entornos autorizados, como los laboratorios de whoami-labs. Usar credenciales ajenas sin permiso es un delito, aunque las encuentres a la vista.

Dónde suelen esconderse#

Los sitios más comunes donde aparecen contraseñas en un servidor: variables de entorno, configuraciones, scripts, historiales y copias
Los sitios más comunes donde aparecen contraseñas en un servidor: variables de entorno, configuraciones, scripts, historiales y copias
UbicaciónQué suele contener
Archivos .env y de configuración de frameworksCredenciales de base de datos, claves de API, secretos de JWT
wp-config.php, settings.py, config.yamlConfiguración principal con credenciales de BD y servicios
Scripts de despliegue y de respaldossh, scp, mysql -u ... -p... con las credenciales incrustadas
Historiales de shell (.bash_history, .zsh_history)Comandos con contraseñas tecleadas por error
Variables de entorno de procesos (/proc/*/environ)Las aplicaciones a menudo reciben secretos ahí
Copias de seguridad (.bak, .old, .tar.gz)Versiones antiguas de los archivos de configuración
Logs de aplicacionesContraseñas que se registraron por error al depurar
Archivos de credenciales de servicios (.my.cnf, .pgpass)Acceso directo a bases de datos sin pedir contraseña
Repositorios Git localesCommits pasados con credenciales que se «borraron» (pero siguen en el historial)
Archivos de CI/CD (.gitlab-ci.yml, Jenkinsfile)Secretos en texto plano o referencias a variables secretas
HTML comentado y JavaScriptA veces incluyen credenciales de pruebas que quedan en producción
Ticketing, wikis y documentación internaCredenciales «temporales» que nadie cambió

Por qué funciona tan bien el movimiento lateral#

Las personas y las aplicaciones reutilizan contraseñas. Encuentras la credencial de MySQL en un .env y resulta ser la misma que la del usuario admin del WordPress; o encuentras la clave que un script usa para conectar por SSH a otro servidor, y la misma clave abre el panel de administración; o en un .bash_history ves sudo con la contraseña escrita por error, y es la que usa el administrador en todos los servidores.

Por eso, cada contraseña encontrada se prueba contra todo lo que haya: otros usuarios locales, otros servicios de la misma máquina, otras máquinas de la red interna, otros servicios expuestos a internet. En un laboratorio, el impulso es seguir buscando después del primer hallazgo; en una auditoría real, documentar cada reutilización es una parte muy valiosa del informe.

Cómo buscarlas de forma metódica en un laboratorio#

Tras entrar como un usuario normal, estas búsquedas son el estándar. Los errores a /dev/null sirven para no inundar la pantalla con los directorios que no puedes leer.

Por nombre de archivo#

# Archivos de configuración típicos
find / -name "*.env*" 2>/dev/null
find / -name "wp-config.php" 2>/dev/null
find / -name "config.php" -o -name "settings.py" -o -name "config.yaml" 2>/dev/null
find / -name ".git-credentials" -o -name ".netrc" -o -name ".pgpass" 2>/dev/null

# Copias de seguridad y archivos antiguos
find / -type f \( -name "*.bak" -o -name "*.old" -o -name "*.save" -o -name "*.orig" \) 2>/dev/null
find / -type f \( -name "*.tar.gz" -o -name "*.zip" -o -name "*.sql" \) 2>/dev/null

Por contenido#

Dentro de un alcance razonable (no en todo el disco), busca palabras típicas:

# Palabras clave en archivos de configuración del usuario web
grep -irE "password|passwd|pwd|secret|token|api_key|apikey" /var/www /opt 2>/dev/null \
  | grep -v "example\|template"

# Patrones típicos de URL con credenciales
grep -rE "mysql://|postgres://|mongodb://|https?://[^ ]*:[^ @]*@" /var/www /opt 2>/dev/null

En historiales y entornos#

# Tu historial y el de otros usuarios (lo que puedas leer)
cat ~/.bash_history
cat /home/*/.bash_history 2>/dev/null
cat /root/.bash_history 2>/dev/null

# Variables de entorno de los procesos en ejecución
for pid in $(ls /proc | grep -E "^[0-9]+$"); do
  cat /proc/$pid/environ 2>/dev/null | tr '\0' '\n' | grep -iE "pass|secret|token|key"
done

En repositorios Git#

# Revisar el historial de Git local
find / -name ".git" -type d 2>/dev/null

# Dentro de un repo encontrado
cd /ruta/al/repo
git log -p --all | grep -iE "password|secret|api_key" | head -30

Herramientas automatizadas como linPEAS incluyen búsquedas muy similares a estas y resaltan los hallazgos. Saber hacerlo a mano permite entender qué buscan y adaptar las consultas a cada escenario.

Un caso completo en un laboratorio#

En un laboratorio autorizado consigues una shell como www-data. Tras unas búsquedas:

cat /var/www/html/.env

Muestra, entre otras cosas:

DB_HOST=127.0.0.1
DB_USER=appuser
DB_PASS=Verano2026!
MAIL_PASSWORD=Verano2026!

Paso 1: usar la credencial de base de datos#

mysql -u appuser -pVerano2026!

Dentro, revisas las tablas: hay una columna users con hashes, otra con tokens. Nada da acceso directo todavía, pero anotas.

Paso 2: probarla contra los usuarios locales#

su maria
# escribes Verano2026!

Si funciona, ya eres maria. Es más habitual de lo que parece: aunque la contraseña fuera «para la base de datos», la persona la reutilizó para su cuenta.

Paso 3: probarla contra servicios expuestos#

Con maria, enumeras lo que hay en la red:

ss -tulpn

Si descubres que maria tiene SSH hacia otra máquina (el known_hosts lo sugiere), o un panel de administración cercano, pruebas allí también con la misma contraseña.

Paso 4: escalar con lo que encontraste#

Si maria puede usar sudo (con esa misma contraseña), revisas sus reglas con sudo -l y aplicas lo que aprendiste en la lección de sudo mal configurado. Si no, buscas por otro lado: capabilities, tareas cron, SUID…

Más allá de las contraseñas: claves de API y tokens#

No todo lo que un auditor busca son contraseñas tradicionales. En los sistemas modernos, los tokens y las claves de API son igual de poderosos y a menudo mucho más fáciles de encontrar.

Tipo de secretoDónde suele vivirQué permite
Token de GitHub (ghp_…, gho_…).env, scripts de CI, .netrcClonar repos privados, subir código, borrar ramas
Clave de AWS (AKIA…)~/.aws/credentials, variables de entornoCrear máquinas, leer buckets, modificar la infraestructura
Token de Slack (xox…)Scripts de notificaciones, variables de entornoLeer mensajes, publicar, exfiltrar conversaciones
Clave de Stripe, Twilio, SendGridConfiguraciones de aplicaciones de negocioMovimientos de dinero, envío de SMS, correos masivos
Token de Docker Registry~/.docker/config.jsonPublicar imágenes maliciosas en registros privados

Muchos de estos tokens tienen patrones reconocibles (los prefijos ghp_, AKIA, xox), por eso las herramientas de escaneo los detectan muy bien y los atacantes también. Cualquier token encontrado en un servidor comprometido suele probarse de inmediato contra el servicio correspondiente.

Qué puede lograr un atacante#

ImpactoEjemplo real
Movimiento lateralReutilizar una credencial para pasar entre servidores
Acceso a datos sensiblesEntrar a la base de datos y leer usuarios, correos, pagos
Toma de cuentasUsar la credencial del correo para resetear contraseñas de otros servicios
PersistenciaGuardar las credenciales como respaldo del acceso
Compromiso en cadenaUna clave de API con amplios permisos permite controlar servicios externos

Cómo gestionar los secretos#

Buenas prácticas con secretos: fuera del código, gestor de secretos, permisos estrictos, escaneo automático, rotación y no reutilizar
Buenas prácticas con secretos: fuera del código, gestor de secretos, permisos estrictos, escaneo automático, rotación y no reutilizar

No en el código, no en el repositorio#

Los secretos nunca deben vivir en el código fuente. Usa archivos de configuración fuera del repositorio o, mejor, un sistema de gestión de secretos: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, Doppler, 1Password Secrets Automation. Las aplicaciones los leen al arrancar; nunca tocan disco en texto plano.

Permisos restrictivos#

Los archivos de configuración con secretos deben ser propiedad del usuario del servicio y legibles solo por él:

sudo chown www-data:www-data .env
sudo chmod 600 .env

Variables de entorno con cuidado#

Son mejores que ponerlos en el código, pero no son invisibles: cualquier otro usuario con acceso a /proc/*/environ del proceso puede leerlas. Protege ese acceso y, para servicios en systemd, usa LoadCredential para pasar secretos sin exponerlos.

Rotar en cuanto algo se filtre#

Si un secreto se publicó por error (en un commit, en un log, en un paste), cámbialo inmediatamente. Que un commit se borre no significa que no quede en el historial o en caches de GitHub.

Escaneo de secretos#

Antes de publicar código, pásale un escáner de secretos como gitleaks, trufflehog o detect-secrets, idealmente en un gancho de pre-commit y en el pipeline de CI. Detectan la mayoría de credenciales accidentales antes de que salgan a un repositorio público.

Historiales y /proc#

Para que las contraseñas no acaben en .bash_history, usa read -s en scripts (no eco de lo que escribes), antepone un espacio a los comandos sensibles (si HISTCONTROL lo permite) o usa unset HISTFILE en sesiones donde sea necesario.

Errores comunes#

  • Reutilizar la misma contraseña en todo. Un .env filtrado se convierte en el acceso completo.
  • Dejar .env en el repositorio. Es el error clásico; cualquier commit que lo incluyera la expone para siempre en el historial.
  • Confiar en «solo nosotros vemos este servidor». Una vulnerabilidad web o una copia de seguridad expuesta lo cambia todo.
  • Olvidar las copias de seguridad. Un backup.tar.gz con las configuraciones es una filtración ambulante.
  • Guardar contraseñas en logs. Los logs se envían a sistemas centrales, se analizan, se exportan. Allí aparece la contraseña.

Preguntas frecuentes#

¿Qué es un archivo .env?#

Un archivo de texto con variables en formato CLAVE=VALOR que muchos frameworks (Laravel, Node.js, Django, Flask) leen al arrancar. Suele contener credenciales de base de datos, claves de API y secretos.

¿Por qué .bash_history es peligroso?#

Porque guarda cada comando que escribiste, incluidos los que llevan contraseñas en la línea (como mysql -u root -pMiClaveSecreta). Cualquiera que pueda leerlo las verá.

¿Un gestor de secretos es imprescindible para empezar?#

No para un proyecto personal, donde basta con .env fuera del repositorio y con permisos restrictivos. Para una empresa o para varios servidores sí: deja de depender de que nadie se equivoque.

¿Qué pasa si se me cuela una clave en un commit?#

Cámbiala inmediatamente en todos los servicios. Reescribir el historial de Git no basta: GitHub conserva las caches y los forks las conservan también.

¿Dónde practico?#

En los laboratorios de whoami-labs enlazados al final de esta lección, donde buscar credenciales en archivos es parte habitual del recorrido.

Resumen#

  • Las contraseñas aparecen en archivos de configuración, scripts, historiales, procesos, copias y repositorios Git.
  • Se buscan con find por nombre, grep -r por contenido, los historiales de shell y /proc/*/environ.
  • La reutilización las convierte en vía de movimiento lateral: la misma clave suele servir en más de un sitio.
  • Se gestionan con secretos fuera del código, permisos restrictivos, gestores de secretos, escaneo automático y rotación inmediata al menor indicio de filtración.

Fuentes y lecturas recomendadas#

Practícalo en estos laboratorios

Ver todos los laboratorios de esta categoría