New tuto 3 done
This commit is contained in:
parent
5f4880dc50
commit
ba77aca73b
57 changed files with 1026 additions and 137 deletions
|
|
@ -1,202 +0,0 @@
|
|||
\newpage
|
||||
|
||||
Les *capabilities*
|
||||
==================
|
||||
|
||||
## Présentation
|
||||
|
||||
Historiquement, dans la tradition UNIX, on distinguait deux catégories de
|
||||
processus :
|
||||
|
||||
* les processus *privilégiés* : dont l'identifiant numérique de son utilisateur
|
||||
est 0 ;
|
||||
* les processus *non-privilégiés* : dont l'identifiant numérique 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 (ça dépend de la
|
||||
version du noyau) !
|
||||
|
||||
|
||||
### `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 pour 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, généralement à 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, ...)
|
||||
permet 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 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
42sh$ echo 'Hello World!' > toto
|
||||
42sh$ setfattr -n user.foo -v bar toto
|
||||
42sh$ getfattr -d toto
|
||||
# file: toto
|
||||
user.foo="bar"
|
||||
```
|
||||
</div>
|
||||
|
||||
Encore plus fort, vous pouvez utiliser les ACL POSIX :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
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!
|
||||
```
|
||||
</div>
|
||||
|
||||
Bien que les droits UNIX traditionnels ne vous donnent pas accès au fichier,
|
||||
les ACL POSIX vous autorisent à le lire.
|
||||
|
||||
Vous pouvez voir ces attributs avec la commande :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
42sh$ getfattr -d -m "^system" toto
|
||||
# file: toto
|
||||
system.posix_acl_access=0sgAAEAD/////AgAEOgDAEAA/////xAABAD////8=
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
### `ping`
|
||||
|
||||
De la même manière que l'on peut définir de façon plus fine les droits d'accès
|
||||
par utilisateur, un attribut de l'espace de nom *security* peut être défini
|
||||
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 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
42sh$ getfattr -d -m "^security" $(which ping)
|
||||
# file: bin/ping
|
||||
security.capability=0sAQAAAgAgAAAAAAAAAAAAAAAAAAA=
|
||||
```
|
||||
</div>
|
||||
|
||||
Ou, dans sa version plus lisible :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
42sh$ getcap $(which ping)
|
||||
/bin/ping = cap_net_raw+ep
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## Exercice : visualisateur de capabilities d'un processus {-}
|
||||
|
||||
Écrivons maintenant un programme permettant de voir les *capabilities*
|
||||
d'un processus :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh$ ./view_caps 1
|
||||
cap_user_header_t
|
||||
-----------------
|
||||
Version: 20080522
|
||||
PID: 1
|
||||
|
||||
cap_user_data_t
|
||||
---------------
|
||||
effective: 0x3fffffffff
|
||||
CAP_AUDIT_CONTROL
|
||||
CAP_AUDIT_READ
|
||||
[...]
|
||||
CAP_SYS_TIME
|
||||
CAP_SYS_TTY_CONFIG
|
||||
CAP_SYSLOG
|
||||
CAP_WAKE_ALARM
|
||||
permitted: 0x3fffffffff
|
||||
CAP_AUDIT_CONTROL
|
||||
CAP_AUDIT_READ
|
||||
[...]
|
||||
CAP_SYS_TIME
|
||||
CAP_SYS_TTY_CONFIG
|
||||
CAP_SYSLOG
|
||||
CAP_WAKE_ALARM
|
||||
inheritable: 0x0
|
||||
```
|
||||
</div>
|
||||
|
||||
Astuces : `capget(2)`, X-macros, ...
|
||||
|
||||
|
||||
## Pour 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 :
|
||||
|
||||
* [Secure Your Containers with this One Weird Trick](https://www.redhat.com/en/blog/secure-your-containers-one-weird-trick)
|
||||
* [Guidelines for extended attributes](https://www.freedesktop.org/wiki/CommonExtendedAttributes/)
|
||||
* [File-based capabilities](https://lwn.net/Articles/211883/)
|
||||
* [A bid to resurrect Linux capabilities](https://lwn.net/Articles/199004/)
|
||||
* [False Boundaries and Arbitrary Code Execution](https://forums.grsecurity.net/viewtopic.php?f=7&t=2522&sid=c6fbcf62fd5d3472562540a7e608ce4e#p10271)
|
||||
|
||||
Pour revenir à Docker, par défaut, un certain nombre de *capabilities* sont
|
||||
désactivées par défaut ; vous pouvez en ajouter et en retirer via les arguments
|
||||
`--cap-add` et `--cap-drop` du `docker container run`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue