Linux sans magie #14 — Linux capabilities : donner un privilège précis sans passer par SUID root
Comprendre les Linux capabilities, leur différence avec SUID root, les commandes getcap/setcap et les risques de sécurité associés.
Sous Unix traditionnel, le modèle de privilèges semble simple : soit un processus est privilégié — historiquement root — soit il ne l’est pas.
Mais donner tous les privilèges de root à un programme qui n’a besoin que d’une opération particulière est excessif.
Linux dispose pour cela des capabilities : les privilèges traditionnellement associés à root sont découpés en unités indépendantes qui peuvent être accordées séparément.
L’objectif est le principe du moindre privilège : donner uniquement le privilège nécessaire.
root
│
├── CAP_NET_ADMIN
├── CAP_NET_BIND_SERVICE
├── CAP_NET_RAW
├── CAP_CHOWN
├── CAP_SETUID
└── ...
SUID root vs capability
Avec un exécutable SUID appartenant à root, le processus peut obtenir un UID effectif privilégié.
Une file capability permet au contraire d’associer à l’exécutable un ensemble beaucoup plus ciblé de privilèges lors de son exécution.
Ce n’est cependant pas une « version sans risque de SUID » : une capability puissante accordée à un programme vulnérable reste un vecteur d’élévation de privilèges.
Voir les capabilities d’un fichier
L’outil principal est :
getcap /chemin/vers/programme
Pour rechercher récursivement :
getcap -r /usr 2>/dev/null
C’est un bon réflexe d’audit : un binaire sans bit SUID peut malgré tout disposer de privilèges supplémentaires.
Exemple : CAP_NET_BIND_SERVICE
Une capability couramment rencontrée est :
CAP_NET_BIND_SERVICE
Elle autorise notamment la liaison à des ports Internet privilégiés, historiquement inférieurs à 1024.
Plutôt que d’accorder des privilèges beaucoup plus larges à un serveur qui n’a besoin que de cette opération, on peut donc lui attribuer ce privilège précis.
La syntaxe typique est :
sudo setcap 'cap_net_bind_service=+ep' ./programme
Puis :
getcap ./programme
On peut obtenir :
./programme cap_net_bind_service=ep
Ici, p correspond au jeu Permitted et e au bit Effective associé aux file capabilities.
Linux manipule plusieurs ensembles de capabilities — notamment permitted, effective, inheritable, bounding et ambient — mais leur fonctionnement détaillé dépasse le périmètre de cet article.
Retirer une file capability
Avant toute expérimentation, il faut savoir revenir en arrière :
sudo setcap -r ./programme
Puis vérifier :
getcap ./programme
Si aucune capability n’est affichée, l’attribut a bien été retiré.
Attention à CAP_SYS_ADMIN
Toutes les capabilities ne se valent pas.
CAP_SYS_ADMIN autorise un très grand nombre d’opérations d’administration système. Elle est tellement large qu’elle est souvent considérée comme une capability à éviter lorsqu’une capability plus précise suffit.
Attribuer :
CAP_SYS_ADMIN
à un programme simplement pour « le faire fonctionner » est généralement contraire au principe recherché.
Il faut identifier la capability réellement nécessaire.
Où Linux stocke-t-il ces informations ?
Contrairement aux permissions classiques affichées par :
ls -l
les file capabilities sont stockées dans un attribut étendu nommé :
security.capability
Elles ne sont donc pas directement visibles dans la représentation rwx.
C’est le même piège conceptuel que pour les ACL : ls -l ne raconte pas toujours toute l’histoire de la sécurité d’un fichier.
Capabilities ≠ absence de risque
Le principe du moindre privilège réduit la surface d’exposition, mais une capability reste un privilège.
Avant d’en attribuer une à un exécutable, il faut notamment vérifier :
ls -l ./programme
getcap ./programme
et se demander :
Qui peut modifier ou remplacer ce fichier ?
Accorder une capability sensible à un exécutable modifiable par un utilisateur non fiable peut créer une voie d’élévation de privilèges.
Les capabilities doivent donc être auditées au même titre que SUID et SGID.
Mini-lab sécurisé
L’objectif est uniquement d’observer le mécanisme sur une copie locale d’un binaire non critique.
mkdir -p ~/linux-sans-magie-capabilities
cp /bin/true ~/linux-sans-magie-capabilities/true-test
cd ~/linux-sans-magie-capabilities
Vérifier l’état initial :
getcap ./true-test
Attribuer une capability à cette copie :
sudo setcap 'cap_net_bind_service=+ep' ./true-test
Vérifier :
getcap ./true-test
Puis retirer la capability :
sudo setcap -r ./true-test
getcap ./true-test
Enfin, supprimer le répertoire de test :
cd
rm -rf ~/linux-sans-magie-capabilities
Le lab n’altère aucun binaire système.
À retenir
Le modèle classique :
utilisateur normal ←────────→ root
peut être affiné avec les capabilities :
processus
│
└── seulement les privilèges nécessaires
Les commandes essentielles sont :
getcap fichier
sudo setcap 'capability=+ep' fichier
sudo setcap -r fichier
Linux ne supprime pas ici les privilèges historiquement associés à root : il permet de les découper et de les attribuer plus finement.
C’est une application directe du principe du moindre privilège.
