Son las siete de la mañana en la Academia Faro. Esta vez no estás en el SOC: estás en su cuarto de servidores, junto al aula, delante de srv-aulas. De madrugada, el vigilante de integridad del SOC (un programa que compara cada noche los archivos sensibles con los del día anterior) avisó: alguien cambió cosas que no se cambian solas. Las clases empiezan a las ocho y media.
Nadie sigue dentro. Lo que hay son rastros: lo que se queda para poder volver. Una cuenta nueva, permiso para hacer de root, una tarea que se lanza sola, una clave más en un authorized_keys, un programa que da permisos de root a quien lo ejecute. Tu trabajo es encontrarlo y quitarlo sin quitar lo que es de la academia, que también hay cosas que parecen raras.
Para eso está la hoja de la academia, la que dejó el técnico de antes:
tecnico@srv-aulas:~$ cat ~/hoja-academia.txt Hoja de la Academia Faro (srv-aulas): lo que es nuestro Cuentas de personas: profesor (Rubén Ortega, informática) y marta (Marta Gil, secretaría). La del técnico: tecnico. La cuenta del proyector: proyector (de sistema, sin shell). Su crontab lo enciende a las 8:25 con /usr/local/bin/encender-proyector. Las copias: /etc/cron.d/copias-academia, cada noche a las 2:15 (/usr/local/sbin/copia-academia). Sudo: Rubén solo puede reiniciar el proyector (/etc/sudoers.d/profesor). Nadie más, salvo tecnico. Las claves de Rubén: la de su portátil del aula (SHA256:FVcxGYtv45bt7yW/8qCyDn+mrWyiyVPmXyHOyNUiFaQ) y la de casa (SHA256:wgXEzso68tG35DYtzUsT7LCywLEFsVa7JwsutBjvbIs). Programas propios: /usr/local/bin/encender-proyector y /usr/local/sbin/copia-academia, sin setuid.
Qué cambió anoche
Lo primero, saber dónde mirar. find con -mtime -1 busca lo modificado en el último día; con
-ls, además, cuándo y de quién:
tecnico@srv-aulas:~$ sudo find /etc /usr/local /var/tmp /home -xdev -mtime -1 -type f -ls 178 4 -rw-r--r-- 1 root root 1721 Oct 14 03:10 /etc/passwd 179 4 -rw-r--r-- 1 root root 777 Oct 14 03:10 /etc/group 180 4 -rw-r----- 1 root shadow 962 Oct 14 03:10 /etc/shadow 278 4 -rw-r--r-- 1 root root 52 Oct 14 03:15 /etc/cron.d/actualizar-cache 275 4 -r--r----- 1 root root 32 Oct 14 03:12 /etc/sudoers.d/90-sistemas 279 28 -rwsr-xr-x 1 root root 26936 Oct 14 03:19 /usr/local/bin/diagnostico 277 16 -rwxr-xr-x 1 root root 14632 Oct 14 03:14 /var/tmp/.sys/run 269 4 -rw------- 1 profesor profesor 287 Oct 14 03:17 /home/profesor/.ssh/authorized_keys 272 4 -rw-r--r-- 1 sistemas sistemas 3771 Oct 14 03:10 /home/sistemas/.bashrc 273 4 -rw-r--r-- 1 sistemas sistemas 807 Oct 14 03:10 /home/sistemas/.profile 274 4 -rw-r--r-- 1 sistemas sistemas 220 Oct 14 03:10 /home/sistemas/.bash_logout
Todo entre las 3:10 y las 3:19, y cada línea es un sitio de los de este tema. Pero ojo: -mtime dice
qué archivo cambió, no qué línea. En /etc/passwd está la cuenta nueva, pero también la del
proyector; en el authorized_keys del profesor, la clave nueva y las suyas. Hay que mirar dentro.
Una cuenta de más
Las cuentas de personas tienen uid de 1000 para arriba; las de sistema (como la del proyector), por
debajo. awk las separa:
tecnico@srv-aulas:~$ awk -F: '$3 >= 1000 && $3 < 60000' /etc/passwd tecnico:x:1000:1000:tecnico:/home/tecnico:/bin/bash profesor:x:1001:1001:Ruben Ortega,,,:/home/profesor:/bin/bash marta:x:1002:1002:Marta Gil,,,:/home/marta:/bin/bash sistemas:x:1003:1003:sistemas,,,:/home/sistemas:/bin/bash
sistemas no está en la hoja. Su nombre suena a algo de la casa (es lo que se busca), pero
lastlog dice cuándo entró cada cuenta por última vez, y desde dónde:
tecnico@srv-aulas:~$ sudo lastlog -u sistemas Username Port From Latest sistemas pts/1 203.0.113.34 Wed Oct 14 03:22:12 +0000 2026
Desde fuera, de madrugada. Y en auth.log, cuándo se creó (useradd deja dos líneas):
tecnico@srv-aulas:~$ sudo grep -E "useradd|Accepted" /var/log/auth.log Oct 14 03:10:46 srv-aulas useradd[4147]: new group: name=sistemas, GID=1003 Oct 14 03:10:46 srv-aulas useradd[4147]: new user: name=sistemas, UID=1003, GID=1003, home=/home/sistemas, shell=/bin/bash, from=/dev/pts/1 Oct 14 03:22:12 srv-aulas sshd[4148]: Accepted password for sistemas from 203.0.113.34 port 40065 ssh2
Para quitarla, userdel -r borra la cuenta, su grupo y su casa. Si prefieres guardarla para
investigar, bloquéala: sudo usermod -L -s /usr/sbin/nologin sistemas (sin contraseña y sin shell).
tecnico@srv-aulas:~$ sudo userdel -r sistemas userdel: sistemas mail spool (/var/mail/sistemas) not found
Ese aviso es normal: no tenía buzón. Lo que no borra userdel es su crontab, si lo tuviera: queda
en /var/spool/cron/crontabs con el número de la cuenta en vez de su nombre. cron ya no lo lanza (la
cuenta no existe), pero sudo find / -xdev -nouser lo encuentra, por si acaso.
Ejercicio
Una cuenta de más: /etc/passwd, lastlog y userdel
En srv-aulas hay una cuenta de persona que no está en la hoja de la academia (~/hoja-academia.txt). Encuéntrala y que no pueda entrar, sin tocar las de verdad ni la del proyector.
Preparando la máquina…
Quién puede ser root
sudo no solo mira el grupo sudo: lee /etc/sudoers y, por su última línea
(@includedir /etc/sudoers.d), los archivos de /etc/sudoers.d. Ahí es fácil dejar una línea:
tecnico@srv-aulas:~$ ls -l /etc/sudoers.d total 12 -r--r----- 1 root root 32 Oct 14 03:12 90-sistemas -r--r----- 1 root root 1096 Sep 7 09:30 README -r--r----- 1 root root 67 Sep 7 09:30 profesor
Sin abrirlos, sudo -l -U dice qué deja sudo a cada cuenta:
tecnico@srv-aulas:~$ sudo -l -U profesor Matching Defaults entries for profesor on srv-aulas: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty User profesor may run the following commands on srv-aulas: (root) NOPASSWD: /usr/bin/systemctl restart proyector
Eso es lo de la hoja: Rubén puede reiniciar el proyector como root, sin contraseña, y nada más.
(ALL) NOPASSWD: ALL sería otra cosa: todo, como root, sin preguntar. Esa es la de 90-sistemas.
tecnico@srv-aulas:~$ sudo rm /etc/sudoers.d/90-sistemas
tecnico@srv-aulas:~$ sudo visudo -c /etc/sudoers: parsed OK /etc/sudoers.d/README: parsed OK /etc/sudoers.d/profesor: parsed OK
visudo -c comprueba todo lo que lee sudo. Si un archivo tiene un error, sudo avisa cada vez que se
usa y se salta esa línea (no se rompe entero); si cualquiera puede escribirlo, lo ignora; y uno con un
punto en el nombre (ana.conf) ni se lee. Por eso la regla de serie es: archivos sin punto, de
root, con permisos 0440, y visudo -c después de tocar.
Ejercicio
Sudo de más: sudo -l -U, sudoers.d y visudo -c
Alguien puede hacer de root sin contraseña y no es el técnico. Encuentra la regla en /etc/sudoers.d y quítala, sin tocar la del profesor (solo reinicia el proyector).
Preparando la máquina…
Lo que se lanza solo
cron lanza lo de tres sitios: /etc/crontab, los archivos de /etc/cron.d (con una columna más: el usuario) y el crontab de cada cuenta. Los de /etc/cron.d se pueden leer sin sudo:
tecnico@srv-aulas:~$ cat /etc/cron.d/* */10 * * * * root /var/tmp/.sys/run >/dev/null 2>&1 SHELL=/bin/sh # Las copias de la academia, cada noche (al NAS del despacho). 15 2 * * * root /usr/local/sbin/copia-academia 30 3 * * 0 root test -e /run/systemd/system || SERVICE_MODE=1 /usr/lib/x86_64-linux-gnu/e2fsprogs/e2scrub_all_cron 10 3 * * * root test -e /run/systemd/system || SERVICE_MODE=1 /sbin/e2scrub_all -A -r
La primera: cada diez minutos, como root, algo en /var/tmp (una carpeta que cualquiera puede
escribir) dentro de una carpeta con punto (escondida para ls), y sin dejar rastro de su salida. La de
las copias está en la hoja; la de e2scrub_all es de Ubuntu. Los crontab de cada cuenta están en el
spool, que solo lee root:
tecnico@srv-aulas:~$ sudo crontab -l -u proyector 25 8 * * 1-5 /usr/local/bin/encender-proyector
Para quitar la tarea, su archivo; y lo que lanzaba, también:
tecnico@srv-aulas:~$ sudo rm /etc/cron.d/actualizar-cache
tecnico@srv-aulas:~$ sudo rm -r /var/tmp/.sys
Aunque ya no esté, cron apunta en el diario cada vez que lanza algo: journalctl -u cron | grep CMD
dice qué lanzó y cuándo (y con grep -o "CMD (.*" | sort | uniq -c, cuántas veces cada cosa).
Lo que tiene que lanzarse como otra cuenta va en su crontab: sudo crontab -u marta -e (o
echo "<la línea>" | sudo crontab -u marta -, que lo sustituye entero), sin columna de usuario. Así
corre como ella y no como root, que es lo que se busca: con lo justo.
Ejercicio
Una tarea de más: /etc/cron.d y crontab -l -u
Algo se lanza cada diez minutos que no es de la academia. Encuentra la tarea y quítala, y también lo que lanza; la de las copias y la del proyector, que sigan.
Preparando la máquina…
Una clave de más
Una clave en un authorized_keys deja entrar sin contraseña, y no hace falta crear ninguna cuenta: basta con añadirla a la de alguien. Las huellas se comparan con las de la hoja:
tecnico@srv-aulas:~$ sudo ssh-keygen -lf /home/profesor/.ssh/authorized_keys 256 SHA256:FVcxGYtv45bt7yW/8qCyDn+mrWyiyVPmXyHOyNUiFaQ ruben@portatil-aula (ED25519) 256 SHA256:wgXEzso68tG35DYtzUsT7LCywLEFsVa7JwsutBjvbIs ruben@casa (ED25519) 256 SHA256:LJcmfzPZQnqEHWPAE17ExoFd/0/sH+XKhM5Jy74uCr4 soporte@faro (ED25519)
La tercera no está en la hoja. El comentario (soporte@faro) lo escribe quien hace la clave: no
prueba nada; la huella sí. Se quita esa línea, solo esa (borrar el archivo entero dejaría a Rubén
sin entrar):
tecnico@srv-aulas:~$ sudo sed -i "/soporte@faro$/d" /home/profesor/.ssh/authorized_keys
Al revés, una clave nueva de alguien de la casa (la de un portátil nuevo) se comprueba igual, por su
huella, y se añade como una línea más, sin tocar las otras: cat nueva.pub | sudo tee -a y el
authorized_keys. Y la de un equipo que deja de usarse se quita como esta: no se queda con su llave.
Ejercicio
Una clave de más: ssh-keygen -lf y la hoja
En el authorized_keys del profesor hay una clave que no es suya. Compara las huellas con las de la hoja de la academia y quita la que sobra, solo esa.
Preparando la máquina…
Programas con setuid
Un programa con setuid se ejecuta con los permisos de su dueño, no con los de quien lo lanza. Así
funciona passwd: es de root y por eso puede escribir en /etc/shadow cuando cambias tu contraseña.
En ls -l se ve como una s en lugar de la x del dueño (-rwsr-xr-x). Un programa de root con
setuid que haga lo que le pidan es una puerta para volver a ser root.
tecnico@srv-aulas:~$ find / -xdev -perm -4000 -type f 2>/dev/null /usr/bin/sudo /usr/bin/su /usr/bin/gpasswd /usr/bin/passwd /usr/bin/newgrp /usr/bin/mount /usr/bin/umount /usr/bin/chfn /usr/bin/chsh /usr/bin/fusermount3 /usr/bin/pkexec /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/lib/openssh/ssh-keysign /usr/local/bin/diagnostico /usr/libexec/polkit-agent-helper-1
Esos catorce son los de cualquier Ubuntu Server; diagnostico no. Lo que pone apt viene de un
paquete, y dpkg -S dice de cuál; lo copiado a mano, de ninguno:
tecnico@srv-aulas:~$ dpkg -S /usr/bin/passwd /usr/local/bin/diagnostico passwd: /usr/bin/passwd dpkg-query: no path found matching pattern /usr/local/bin/diagnostico
Se le quita el setuid (o se borra, si no es de nada), sin tocar los de verdad: a passwd sin setuid
nadie podría cambiarse la contraseña.
tecnico@srv-aulas:~$ sudo chmod u-s /usr/local/bin/diagnostico
Ejercicio
Un programa con setuid: find -perm y dpkg -S
Hay un programa con setuid de root que no trae Ubuntu. Encuéntralo entre los de verdad (passwd, sudo, su…) y quítale el setuid, sin tocar los demás.
Preparando la máquina…
En la sala: lo que se quedó dentro
En la sala estás en el cuarto de servidores de la academia, con el aula al lado. En el panel del vigilante de integridad sale lo que sigue distinto de ayer, archivo por archivo, y sus avisos, que suben de tono cada vez que vuelve a mirar. El vigilante no sabe qué es de la academia: la hoja, en tu mesa, sí (y ayer por la tarde la academia cambió dos cosas suyas). Hasta las ocho y media: a las 8:25 el servidor enciende el proyector y a esa hora Rubén entra en el aula. Quita lo que sobra; si quitas algo de la academia, se nota en clase (y en la nota). Y si te quedas sin sudo o sin SSH, la consola del servidor arranca en modo de recuperación, pero cuesta veinte minutos.