Introduction aux fonctionnalités de Linux
Sur Linux, traditionnellement, un processus pouvait soit s’exécuter en tant que root, et donc avoir un accès illimité au système, soit en tant qu’utilisateur non root, soumis à un ensemble de restrictions. Depuis la version 2.2 du noyau, des fonctionnalités ont été introduites comme moyen d’accorder des autorisations de manière plus granulaire.
Dans ce tutoriel, nous apprenons quels sont les trois principaux ensembles de fonctionnalités qui peuvent être associés aux exécutables sous Linux, et comment lister, ajouter et supprimer des capacités à l’aide des utilitaires getpcap et setcap.
Dans ce tutoriel, vous allez apprendre :
- Quels sont les ensembles de fonctionnalités qui peuvent être associés aux fichiers ?
- Comment lister les fonctionnalités attribuées à un exécutable ou à un processus
- Comment définir et supprimer des fonctionnalités d’un exécutable
Introduction
Des capacités ont été introduites sur Linux pour permettre d’attribuer des privilèges aux processus de manière granulaire, en surmontant la distinction binaire traditionnelle racine/non-racine. Tout comme en utilisant sudo, nous pouvons exécuter des commandes spécifiques en tant qu’un autre utilisateur (même root), sans devenir définitivement cet utilisateur, en utilisant des capacités, nous pouvons accorder à un processus uniquement certains privilèges sans avoir à l’exécuter en tant que root.
Nous avons vu un exemple concret de ce à quoi les capacités peuvent être utilisées dans un tutoriel récent sur l’autorisation des conteneurs docker sans racine à se lier à des ports système privilégiés : l’une des solutions proposées dans l’article consistait à attribuer la capacité CAP_NET_BIND_SERVICE au binaire rootlesskit. CAP_NET_BIND_SERVICE’est là l’une des fonctionnalités qui peuvent être utilisées sous Linux : la liste complète se trouve dans la page de manuel dédiée.
Ensembles de capacités : autorisés, efficaces et héritables
Sur Linux, il existe cinq ensembles de fonctionnalités : Autorisé, Héritable, Effectif, Limité et Ambiant. Cependant, parmi ceux-ci, seuls les trois premiers peuvent être affectés à des fichiers exécutables. L’ensemble de fonctionnalités autorisées comprend les capacités attribuées à un certain exécutable ; l’ensemble effectif est un sous-ensemble de l’ensemble autorisé et comprend les capacités qui sont effectivement utilisées. Enfin, l’ensemble Héritable comprend des capacités qui peuvent être héritées par les processus fils.
Vérification des capacités d’un exécutable ou d’un processus
Pour vérifier les capacités attribuées à un exécutable, nous utilisons getcap, qui est installé par défaut dans toutes les principales distributions Linux. Cet utilitaire, ainsi que son compagnon setcap, font partie du paquet « libcap2-bin » sur les distributions basées sur Debian, et du paquet « libcap-2 » sur les systèmes basés sur Fedora.
Voyons un exemple de vérification des capacités attribuées à un exécutable. Clockdiff est un programme utilisé pour mesurer les différences d’horloge entre les hôtes. Pour lister les fonctionnalités qui lui sont attribuées, nous exécutons :
getcap /usr/bin/clockdiffSur la dernière version de Fedora, la commande ci-dessus renvoie :
/usr/bin/clockdiff cap_net_raw=pLes ensembles de fonctionnalités Autorisé, Effectif et Héritable sont référencés par les indicateurs « p », « e » et « i », respectivement. Comme nous pouvons le voir ci-dessus, l’exécutable /usr/bin/clockdiff a la capacité CAP_NET_RAW dans l’ensemble autorisé.
Si nous ne savons pas quels exécutables ont des capacités spéciales attribuées, nous pouvons invoquer l’utilitaire getcap avec l’option -r, qui permet une recherche récursive sur le chemin passé en argument. La commande ci-dessous vérifie l’ensemble du système :
sudo getcap -r /Pour lister les fonctionnalités attribuées à un processus en cours d’exécution, nous utilisons un autre utilitaire : getpcaps. Nous passons simplement les PID des processus que nous voulons examiner comme argument :
getpcaps 44448Attribution de capacités
Pour attribuer des capacités à un exécutable, nous utilisons l’utilitaire setcap. Nous fournissons la liste des capacités que nous voulons attribuer, séparées par des virgules, et nous les associons aux drapeaux qui font référence aux ensembles de capacités, via l’un des opérateurs disponibles : =, + ou -.
Voyons un exemple. Supposons que nous voulions ajouter la capacité CAP_NET_BIND_SERVICE au binaire /usr/bin/rootlesskit, à la fois dans l’ensemble autorisé et effectif. Nous gérons :
sudo setcap cap_net_bind_service=pe /usr/bin/rootlesskitDans l’exemple ci-dessus, nous avons attribué la capacité CAP_NET_BIND_SERVICE aux ensembles Autorisé (p) et Effectif (e), à l’aide de l’opérateur =. Cet opérateur supprime d’abord les fonctionnalités répertoriées de tous les ensembles de fonctionnalités, puis les ajoute à celles que nous spécifions dans la commande.
Plusieurs « clauses » séparées par des espaces peuvent être spécifiées dans une seule commande, pour ajouter différentes capacités dans différents ensembles. À titre d’exemple, pour spécifier que nous voulons ajouter la capacité CAP_NET_BIND_SERVICE aux ensembles autorisés, effectifs et héritables, et la capacité CAP_NET_RAW uniquement aux ensembles autorisés et effectifs du binaire rootlesskit, nous exécuterions :
sudo setcap "cap_net_bind_service=pei cap_net_raw=ep" /usr/bin/rootlesskitSi nous utilisons l’opérateur = mais que nous ne spécifions explicitement aucune capacité, la commande les affecte toutes. Ainsi, pour ajouter toutes les fonctionnalités aux ensembles Autorisé et Effectif d’un exécutable, nous exécuterions :
sudo setcap =pe /path/to/executableSelon la même logique, pour vider tous les ensembles de fonctionnalités d’un exécutable, on exécuterait :
sudo setcap = /path/to/executableContrairement à =, les opérateurs + et - exigent explicitement qu’une liste de capacités et un ou plusieurs indicateurs d’ensembles de capacités soient fournis. Le premier est utilisé pour inclure les capacités spécifiées dans les ensembles de fonctionnalités fournis, le second est utilisé pour les supprimer. Dans l’exemple ci-dessous, nous ajoutons la capacité CAP_NET_BIND_SERVICE aux ensembles autorisés et effectifs d’un exécutable, et nous nous assurons explicitement qu’elle n’est pas présente dans l’ensemble Héritable :
sudo setcap cap_net_bind_service+ep-i /path/to/executableVoici un autre exemple. Cette fois, nous ajoutons toutes les fonctionnalités dans les ensembles Autorisé et Effectif d’un exécutable, à l’exception de la capacité CAP_CHOWN :
sudo setcap "all+pe cap_chown-pe" /path/to/executablePour supprimer toutes les fonctionnalités attribuées à un exécutable, nous lançons setcap avec l’option -r, et passons le chemin du fichier en argument :
sudo setcap -r /path/to/executableChaque fois que nous utilisons l’utilitaire setcap sur un exécutable, ses capacités actuelles sont « détruites » et le nouveau traité, donc nous ne pouvons pas, par exemple, simplement ajouter certaines capacités en plus de celles actuellement définies. Nous devons toujours spécifier la liste complète des capacités de l’exécutable chaque fois que nous invoquons l’utilitaire.
Conclusions
Dans ce tutoriel, nous avons parlé des capacités de Linux, qui peuvent être utilisées pour accorder des autorisations précises aux processus Linux. Nous avons vu quels sont les trois principaux ensembles auxquels une capacité peut être attribuée et comment répertorier et modifier les capacités attribuées à un exécutable. Pour en savoir plus sur les capacités, vous pouvez jeter un coup d’œil à la page de manuel capabilities(7).
