En Linux, el usuario root tiene permiso para realizar prácticamente cualquier operación dentro del sistema. Puede modificar archivos protegidos, cambiar configuraciones de red, gestionar procesos, montar sistemas de archivos o cargar módulos en el kernel.
Sin embargo, muchas aplicaciones solamente necesitan realizar una de estas operaciones. Concederles todos los permisos de root sería innecesario y aumentaría considerablemente el impacto de una posible vulnerabilidad.
Las Linux capabilities solucionan este problema dividiendo los privilegios tradicionales de root en permisos independientes. De esta forma, un proceso puede recibir únicamente la capacidad concreta que necesita para funcionar.
👉 Y recuerda, si quieres aprender más de Linux, pincha en este curso de Linux gratis
🐳 Si quieres aprender más de Docker, pincha en este curso de Docker gratis
Qué son las Linux capabilities
Tradicionalmente, los sistemas Unix diferenciaban entre dos tipos de procesos:
- Procesos privilegiados ejecutados por root.
- Procesos sin privilegios ejecutados por el resto de los usuarios.
El usuario root podía superar la mayoría de las comprobaciones de permisos realizadas por el kernel. Los demás usuarios quedaban limitados por su UID, sus grupos y los permisos configurados sobre archivos y recursos.
Desde Linux 2.2, estos privilegios se dividen en unidades independientes llamadas capabilities. Técnicamente, las capabilities son atributos asociados a los hilos de ejecución, aunque normalmente se habla de las capacidades de un proceso.
Por ejemplo, una aplicación puede recibir permiso para:
- Escuchar en un puerto privilegiado.
- Cambiar el propietario de un archivo.
- Configurar una interfaz de red.
- Ajustar la hora del sistema.
- Crear determinados tipos de sockets.
- Enviar señales a otros procesos.
La aplicación obtiene únicamente el permiso necesario, sin recibir acceso completo como root.
Qué problema resuelven las Linux capabilities
Imagina un servidor web que necesita escuchar en el puerto 80.
Tradicionalmente, los puertos privilegiados requerían permisos de root. Una solución sencilla consistía en ejecutar todo el servidor web como administrador, aunque la única operación privilegiada que necesitaba era abrir ese puerto.
Con las Linux capabilities es posible concederle únicamente CAP_NET_BIND_SERVICE, que permite enlazar el proceso a puertos privilegiados.
El servidor puede continuar ejecutándose con un usuario normal y no obtiene permisos para modificar discos, administrar interfaces de red o cambiar la configuración del kernel.
Este mecanismo aplica el principio de mínimo privilegio: cada proceso debe disponer exclusivamente de los permisos imprescindibles para realizar su función.
Capabilities más utilizadas en Linux
Linux dispone de diferentes capabilities para separar las operaciones administrativas. Estas son algunas de las más habituales:
| Capability | Función |
|---|---|
CAP_CHOWN | Permite cambiar el propietario y el grupo de archivos |
CAP_DAC_OVERRIDE | Permite ignorar determinadas comprobaciones de permisos sobre archivos |
CAP_KILL | Permite enviar señales a procesos que pertenecen a otros usuarios |
CAP_NET_BIND_SERVICE | Permite escuchar en puertos privilegiados |
CAP_NET_RAW | Permite utilizar sockets RAW y PACKET |
CAP_NET_ADMIN | Permite realizar operaciones avanzadas de administración de red |
CAP_SYS_TIME | Permite modificar el reloj del sistema |
CAP_SYS_BOOT | Permite reiniciar el sistema |
CAP_SYS_MODULE | Permite cargar o eliminar módulos del kernel |
CAP_SYS_ADMIN | Permite realizar una gran cantidad de operaciones administrativas |
La capability CAP_SYS_ADMIN merece especial atención. Agrupa muchas operaciones diferentes y, en algunos escenarios, puede proporcionar un nivel de acceso muy elevado. Por este motivo, debe evitarse siempre que exista una capability más específica para la operación requerida.
Cómo funcionan las Linux capabilities
Las capabilities no se almacenan en una única lista. Linux utiliza diferentes conjuntos para determinar qué privilegios puede emplear, conservar o heredar un proceso.
Permitted
El conjunto Permitted contiene las capabilities que un proceso tiene permitido utilizar.
Funciona como un límite para el conjunto Effective. Una capability que no se encuentre en Permitted normalmente no puede activarse como efectiva.
Effective
El conjunto Effective contiene las capabilities que el kernel utiliza en ese momento para comprobar si una operación está permitida.
Que una capability esté en Permitted no significa necesariamente que se esté utilizando. Para que el proceso pueda ejercerla debe encontrarse también en el conjunto Effective.
Inheritable
El conjunto Inheritable determina qué capabilities podrían conservarse cuando el proceso ejecuta otro programa mediante execve().
Su funcionamiento depende también de las capabilities configuradas en el archivo ejecutable.
Bounding
El conjunto Bounding establece el límite máximo de capabilities que un proceso puede obtener durante la ejecución de nuevos programas.
Eliminar una capability de este conjunto evita que pueda recuperarse posteriormente mediante la ejecución de un archivo con capabilities.
Ambient
El conjunto Ambient permite conservar determinadas capabilities al ejecutar programas que no tienen privilegios especiales configurados.
Las ambient capabilities aparecieron en Linux 4.3 y resultan especialmente útiles cuando una aplicación ejecuta otros binarios y necesita mantener ciertos permisos durante la cadena de ejecución.
Cómo consultar las capabilities de un archivo
Las herramientas principales para trabajar con capabilities forman parte del proyecto libcap.
En Debian y Ubuntu pueden instalarse habitualmente con:
sudo apt update
sudo apt install libcap2-binEn Fedora, Rocky Linux, AlmaLinux y Red Hat Enterprise Linux:
sudo dnf install libcapEl comando getcap muestra las capabilities asignadas a un archivo:
getcap /ruta/al/ejecutableun Por ejemplo:
getcap /usr/bin/pingDependiendo de la distribución y de su configuración, el resultado podría ser similar a este:
/usr/bin/ping cap_net_raw=epTambién puedes buscar archivos con capabilities dentro de varios directorios:
sudo getcap -r /usr/bin /usr/sbin 2>/dev/nullLa opción -r realiza una búsqueda recursiva y muestra los archivos que tienen capabilities configuradas.
Cómo consultar las capabilities de un proceso
Para revisar las capabilities del proceso actual puede utilizarse:
capsh --printcapsh muestra información sobre los conjuntos Effective, Permitted, Bounding y Ambient, entre otros datos relacionados con el contexto de seguridad.
También puedes consultar un proceso concreto mediante su PID:
getpcaps PIDPor ejemplo, para consultar las capabilities de la shell actual:
getpcaps $$El comando getpcaps recibe uno o varios identificadores de proceso y muestra sus capabilities en formato legible.
El kernel también expone esta información en /proc:
grep '^Cap' /proc/$$/statusEl resultado tendrá un formato parecido al siguiente:
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000Los valores se muestran como máscaras hexadecimales, por lo que herramientas como capsh suelen resultar más cómodas para interpretarlos.
Cómo asignar una capability a un archivo
El comando setcap permite asociar capabilities a un archivo ejecutable.
La sintaxis general es:
sudo setcap capability=conjuntos /ruta/al/ejecutablePor ejemplo, para permitir que una aplicación escuche en puertos privilegiados:
sudo setcap cap_net_bind_service=+ep /usr/local/bin/mi-aplicacionEn esta expresión:
eañade la capability al conjunto Effective.pla añade al conjunto Permitted.+incorpora la capability a los conjuntos indicados.
Puedes comprobar la configuración con:
getcap /usr/local/bin/mi-aplicacionEl resultado será similar a:
/usr/local/bin/mi-aplicacion cap_net_bind_service=epDesde Linux 2.6.24, las capabilities pueden asociarse directamente a ejecutables. Esta configuración se almacena como un atributo extendido denominado security.capability.
Cómo eliminar las capabilities de un archivo
Para eliminar todas las capabilities asociadas a un ejecutable se utiliza la opción -r de setcap:
sudo setcap -r /usr/local/bin/mi-aplicacionDespués puedes verificar que se han eliminado:
getcap /usr/local/bin/mi-aplicacionSi el comando no devuelve ningún resultado, el archivo ya no tiene capabilities asignadas.
Linux capabilities en Docker
Las capabilities son especialmente importantes en los contenedores.
Aunque un proceso se ejecute como root dentro de un contenedor Docker, normalmente no recibe todos los privilegios disponibles para el usuario root del sistema anfitrión. Docker utiliza un conjunto reducido de capabilities para limitar lo que pueden hacer los procesos del contenedor.
La opción –cap-add permite añadir una capability:
docker run --cap-add=NET_ADMIN imagenLa opción –cap-drop permite eliminarla:
docker run --cap-drop=NET_RAW imagenUna práctica más restrictiva consiste en eliminar todas las capabilities y añadir únicamente las necesarias:
docker run \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
imagenEn Docker Compose puede configurarse de esta forma:
services:
aplicacion:
image: mi-aplicacion:latest
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICESiempre que sea posible, este enfoque es preferible a ejecutar el contenedor con:
docker run --privileged imagenEl modo privilegiado elimina gran parte del aislamiento de seguridad y concede al contenedor un nivel de acceso mucho mayor sobre el sistema anfitrión.
Linux capabilities en Kubernetes y OpenShift
Kubernetes permite añadir o eliminar capabilities mediante el securityContext del contenedor.
Un ejemplo seguro sería:
apiVersion: v1
kind: Pod
metadata:
name: aplicacion
spec:
containers:
- name: aplicacion
image: mi-aplicacion:latest
securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICEEn los manifiestos de Kubernetes se omite el prefijo CAP_. Por ejemplo, CAP_NET_BIND_SERVICE se escribe como NET_BIND_SERVICE.
La recomendación general consiste en:
- Eliminar todas las capabilities con drop: ALL.
- Añadir exclusivamente las que necesita la aplicación.
- Ejecutar el contenedor como usuario no root.
- Desactivar la escalada de privilegios.
- Utilizar un perfil seccomp apropiado.
El estándar de seguridad Restricted de Kubernetes exige eliminar todas las capabilities y solamente permite volver a añadir NET_BIND_SERVICE.
En OpenShift también intervienen las Security Context Constraints o SCC. Una aplicación no podrá solicitar una capability si la SCC aplicada a su cuenta de servicio no la permite. Las SCC controlan, entre otros elementos, los contenedores privilegiados, la escalada de privilegios y las capabilities que puede solicitar cada pod.
Riesgos de utilizar capabilities
Las Linux capabilities son más seguras que entregar acceso completo como root, pero no son inofensivas.
Una capability mal asignada puede permitir que un atacante amplíe el impacto de una vulnerabilidad. Algunas, como CAP_SYS_ADMIN, CAP_SYS_MODULE, CAP_DAC_OVERRIDE o CAP_NET_ADMIN, pueden proporcionar acceso a operaciones especialmente sensibles.
También debe evitarse asignar capabilities a intérpretes genéricos como Python, Bash, Perl o PHP. Si un intérprete tiene una capability, cualquier código ejecutado mediante ese intérprete podría aprovecharla.
Por ejemplo, no sería recomendable hacer esto en un sistema real:
sudo setcap cap_net_bind_service=+ep /usr/bin/python3En su lugar, la capability debería asignarse a un binario específico, diseñado para realizar únicamente la operación necesaria.
Buenas prácticas con Linux capabilities
Antes de asignar una capability, comprueba qué operación necesita realmente la aplicación.
Evita conceder CAP_SYS_ADMIN como solución genérica. Si existe una capability más específica, utiliza siempre la opción más limitada.
En contenedores, elimina todas las capabilities y añade solo las imprescindibles:
capabilities:
drop:
- ALLRevisa periódicamente los ejecutables con capabilities:
sudo getcap -r /usr/bin /usr/sbin /usr/local/bin 2>/dev/nullCombina las capabilities con otras medidas de seguridad como usuarios no root, permisos Unix, SELinux, AppArmor, seccomp, namespaces y sistemas de archivos de solo lectura.
Por último, documenta por qué se ha concedido cada capability. De esta forma será más sencillo revisarla o eliminarla cuando la aplicación deje de necesitarla.
Conclusión
Las Linux capabilities permiten dividir los privilegios tradicionales del usuario root en permisos mucho más específicos. Gracias a este mecanismo, una aplicación puede realizar una operación privilegiada sin obtener control completo sobre el sistema.
Comandos como getcap, setcap, getpcaps y capsh permiten consultar y administrar estos permisos directamente en Linux. Docker, Kubernetes y OpenShift también utilizan capabilities para reducir los privilegios disponibles dentro de los contenedores.
Aplicadas correctamente, las Linux capabilities ayudan a seguir el principio de mínimo privilegio y reducen considerablemente el impacto de una aplicación comprometida.
