2016-10-05 09:13:56 +00:00
|
|
|
\newpage
|
|
|
|
|
|
|
|
Les capabilities
|
|
|
|
================
|
|
|
|
|
|
|
|
## Présentation
|
|
|
|
|
2016-10-05 20:49:08 +00:00
|
|
|
Historiquement, dans la tradition UNIX, on distingue deux catégories de
|
|
|
|
processus :
|
2016-10-05 09:13:56 +00:00
|
|
|
|
2016-10-05 20:49:08 +00:00
|
|
|
* les processus *privilégiés* : dont l'identifiant de son utilisateur est 0 ;
|
|
|
|
* les processus *non-privilégiés* : dont l'identifiant de son utilisateur n'est
|
|
|
|
pas 0.
|
|
|
|
|
|
|
|
Lors des différents tests de permission fait par le noyau, les processus
|
|
|
|
privilégiés outrepassaient ces tests, tandis que les autres devaient passer les
|
|
|
|
tests de l'effective UID, effective GID, et autres groupes supplémentaires...
|
|
|
|
|
|
|
|
Depuis Linux 2.2 (en 1998), les processus privilégiés peuvent activer ou
|
|
|
|
désactiver des *capabilities*, chacune donnant accès à un groupe d'actions
|
|
|
|
privilégiées au sein du noyau.
|
|
|
|
|
|
|
|
On trouve par exemple :
|
|
|
|
|
|
|
|
* `CAP_CHOWN` : permet de modifier le propriétaire d'un fichier de manière
|
|
|
|
arbitraire ;
|
|
|
|
* `CAP_KILL` : permet de tuer n'importe quel processus ;
|
|
|
|
* `CAP_SYS_BOOT` : permet d'arrêter ou de redémarrer la machine ;
|
|
|
|
* `CAP_SYS_MODULE` : permet de charger et décharger des modules ;
|
|
|
|
* et beaucoup d'autres, il y en a environ 39 en tout !
|
|
|
|
|
|
|
|
|
|
|
|
### `ping`
|
|
|
|
|
|
|
|
Pour émettre un ping, il est nécessaire d'envoyer des paquets ICMP. À la
|
|
|
|
différence des datagrammes UDP ou des segments TCP, il n'existe pas d'interface
|
|
|
|
exposée par le noyau aux utilisateurs pour envoyer des paquets ICMP. Pour le
|
|
|
|
faire, il est nécessaire de pouvoir écrire directement sur l'interface ; ça,
|
|
|
|
seul le super-utilisateur peut le faire.
|
|
|
|
|
|
|
|
Pour permettre à tous les utilisateurs de pouvoir envoyer des ping, le
|
|
|
|
programme est donc généralement Setuid root. Cela permet à n'importe quel
|
|
|
|
utilisateur de prendre les droits du super-utilisateur, le temps de l'exécution
|
|
|
|
du programme.
|
|
|
|
|
|
|
|
Les problèmes surviennent lorsque l'on découvre des vulnérabilités dans les
|
|
|
|
programmes Setuid root. En effet, s'il devient possible à un utilisateur
|
|
|
|
d'exécuter du code arbitraire, ce code sera exécuté avec les privilèges de
|
|
|
|
l'utilisateur root ! Dans le cas de ping, on se retrouverait alors à pouvoir
|
|
|
|
lire l'intégralité de la mémoire, alors que l'on avait juste besoin d'écrire
|
|
|
|
sur une interface réseau.
|
|
|
|
|
|
|
|
C'est donc à ce moment que les *capabilities* entrent en jeu : un processus (ou
|
|
|
|
même un thread) privilégié peut décider, à son lancement, de réduire ses
|
|
|
|
*capabilities*, pour ne garder que celles dont il a réellement besoin. Ainsi,
|
|
|
|
`ping` pourrait se contenter de `CAP_NET_RAW`.
|
|
|
|
|
|
|
|
|
|
|
|
## Les attributs de fichier étendus
|
|
|
|
|
|
|
|
Une grosse majorité des systèmes de fichiers (ext[234], XFS, btrfs, ...)
|
|
|
|
permettent d'enregistrer, pour chaque fichier, des attributs (dits attributs
|
|
|
|
*étendus*, par opposition aux attributs *réguliers* qui sont réservés à l'usage
|
|
|
|
du système de fichiers).
|
|
|
|
|
|
|
|
Sous Linux, les attributs sont regroupés dans des espaces de noms :
|
|
|
|
|
|
|
|
* *security* : espace utilisé par les modules de sécurité du noyau, tel que
|
|
|
|
SELinux, ... ;
|
|
|
|
* *system* : espace utilisé par le noyau pour stocker des objets système, tels
|
|
|
|
que les ACL POSIX ;
|
|
|
|
* *trusted*: espace dont la lecture et l'écriture est limité au
|
|
|
|
super-utilisateur ;
|
|
|
|
* *user* : modifiable sans restriction, à partir du moment où l'on est le
|
|
|
|
propriétaire du fichier.
|
|
|
|
|
|
|
|
Par exemple, on peut définir un attribut sur un fichier comme cela :
|
|
|
|
|
|
|
|
```shell
|
|
|
|
42sh$ echo 'Hello World!' > toto
|
|
|
|
42sh$ setfattr -n user.foo -v bar toto
|
|
|
|
42sh$ getfattr -d toto
|
|
|
|
# file: toto
|
|
|
|
user.foo="bar"
|
|
|
|
```
|
|
|
|
|
|
|
|
Encore plus fort, vous pouvez utiliser les ACL POSIX :
|
|
|
|
|
|
|
|
```shell
|
|
|
|
42sh$ sudo chown root:root toto && sudo chmod o-r toto
|
|
|
|
42sh$ cat toto
|
|
|
|
cat: toto: Permission denied
|
|
|
|
42sh$ sudo setfattr -m u:$USER:r toto
|
|
|
|
42sh$ cat toto
|
|
|
|
Hello World!
|
|
|
|
```
|
|
|
|
|
|
|
|
Bien que les droits UNIX traditionnels ne vous donne pas accès au fichier, les
|
|
|
|
ACL POSIX vous autorisent à lire le contenu du fichier.
|
|
|
|
|
|
|
|
Vous pouvez voir ces attributs avec la commande :
|
|
|
|
|
|
|
|
```shell
|
|
|
|
42sh$ getfattr -d -m "^system" toto
|
|
|
|
# file: toto
|
|
|
|
system.posix_acl_access=0sgAAEAD/////AgAEOgDAEAA/////xAABAD////8=
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### `ping`
|
|
|
|
|
|
|
|
De la même manière que l'on peut définir de manière plus fine les droits
|
|
|
|
d'accès par utilisateur, un attribut de l'espace de nom *security* peut être
|
|
|
|
définit pour accroître les *capabilities* d'un processus lorsqu'il est lancé
|
|
|
|
par un utilisateur non-privilégié. On peut alors voir le Setuid root comme
|
|
|
|
l'utilisation de cet attribut auquel on accroîtrait l'ensemble des
|
|
|
|
*capabilities*.
|
|
|
|
|
|
|
|
Si votre distribution profite de ces attributs étendus, vous devriez obtenir :
|
|
|
|
|
|
|
|
```shell
|
|
|
|
42sh$ getfattr -d -m "^security" $(which ping)
|
|
|
|
# file: bin/ping
|
|
|
|
security.capability=0sAQAAAgAgAAAAAAAAAAAAAAAAAAA=
|
|
|
|
```
|
|
|
|
|
|
|
|
Ou, dans sa version plus lisible :
|
|
|
|
|
|
|
|
```shell
|
|
|
|
42sh$ getcap $(which ping)
|
|
|
|
/bin/ping = cap_net_raw+ep
|
|
|
|
```
|
2016-10-05 09:13:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
## Exercice : visualisateur de capabilities d'un processus
|
|
|
|
|
2016-10-05 20:49:08 +00:00
|
|
|
Écrivons maintenant un script permettant de voir les *capabilities* d'un
|
|
|
|
processus :
|
|
|
|
|
2016-10-05 09:13:56 +00:00
|
|
|
```shell
|
|
|
|
```
|
2016-10-05 20:49:08 +00:00
|
|
|
|
|
|
|
## Rendu
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## Aller plus loin
|
|
|
|
|
|
|
|
Je vous recommande la lecture des *man* suivants :
|
|
|
|
|
|
|
|
* `capabilities(7)` : énumérant tous les capabilities, leur utilisation, etc. ;
|
|
|
|
* `xattrs(7)` : à propos des attributs étendus.
|
|
|
|
|
|
|
|
Et de ces quelques articles :
|
|
|
|
|
|
|
|
* [https://www.freedesktop.org/wiki/CommonExtendedAttributes/](Guidelines for
|
|
|
|
extended attributes)
|
|
|
|
* [https://lwn.net/Articles/211883/](File-based capabilities)
|
|
|
|
* [http://lwn.net/Articles/199004/](A bid to resurrect Linux capabilities)
|