vendredi 6 septembre 2019

DAC_READ_SEARCH / DAC_OVERRIDE


J'ai repris un post de l'excellent Dan Walsh afin de bien comprendre la subtilité des "capabilities" et sur les logs AVC DAC_READ_SEARCH et DAC_OVERRIDE que je rencontre.


Commençons par un mythe bien connu : ROOT a tous les droits.

L'idée que ROOT possède tous les droits est une erreur. Cela fait quelques années que le noyau Linux a essayé de décomposer les privilèges de root en plusieurs fonctionnalités, les "capabilities".

A l'origine, ils étaient de 32 et sont passés récemment à 64.
Les capabilities donnent la possibilité au programmeur de coder des applications de manière a ce que la commande ping par exemple puisse ouvrir une socket ou httpd puisse ouvrir un port inférieur à 1024, sans utiliser les autres capabilities de root.

SELinux contrôle également l'accès à toutes les fonctionnalités d'un processus.

Un bugzilla courant concerne un processus nécessitant la fonctionnalité DAC_READ_SEARCH ou DAC_OVERRIDE.

DAC (Discretionnary Access Control) signifie un contrôle d'accès discrétionnaire. Cela indique que les droits sur un fichier sont laissés à  la discrétion du propriétaire du fichier. En tant que propriétaire du fichier, vous pouvez modifier n'importe quels droits dessus. Dans ce modèle, l'état est non déterminable par l'administrateur. Et root outrepasse tout le contrôle d'accès. C'est le mode par défaut des systèmes Linux/ Unix avec les read-write-execute et users et groups.

Regardons maintenant la puissance des capabilities:
more /usr/include/linux/capability.h
...
/* Override all DAC access, including ACL execute access if
   [_POSIX_ACL] is defined. Excluding DAC access covered by
   CAP_LINUX_IMMUTABLE. */

#define CAP_DAC_OVERRIDE     1

/* Overrides all DAC restrictions regarding read and search on files
   and directories, including ACL restrictions if [_POSIX_ACL] is
   defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */

#define CAP_DAC_READ_SEARCH  2
En lisant la description dans le code, cela signifie d’un processus s'exécutant avec l'UID=0 peut lire tous les fichiers du système, même si les flags de permissions n'autorisent pas root de lire le fichier.

De façon similaire, DAC_OVERRIDE signifie qu'un processus peut ignorer les droits de  permissions et propriétaires de tous les fichiers d'un système.

Si on voit un message AVC qui requière cet accès, il faut regarder l'UID du processus et bien souvent, ce processus s'exécute avec l'uid=0.

Le réflexe dans la plupart du temps est d'ajouter des autorisations, ce qui est bien souvent une erreur.

Ces AVC indique que vous avez des droits d'accès positionnés pour restreindre l'accès à ces fichiers. Il s'agit souvent de fichiers de configurations.

Prenons l'exemple du processus https ayant besoin de lire le contenu de /var/lib/myweb/content avec comme propriétaire l'utilisateur httpd et les permissions 600.
ls -l /var/lib/myweb/content
-rw-------. 1 apache apache 0 May 12 13:50 /var/lib/myweb/content
Si pour différente raison, le processus a besoin de lire ce fichier et qu'il tourne avec l'UID=0, alors le système va refuser l'accès et générer un DAC_* AVC.

Un simple fix serait de changer les permissions du fichier à 644.
# chmod 640 /var/lib/myweb/content
# chgrp root /var/lib/myweb/content
# ls -l /var/lib/myweb/content
-rw-r-----. 1 apache root 0 May 12 13:50 /var/lib/myweb/content
Cela va permettre à un processus root de lire le fichier en utilisant les droits "other".

Une autre solution serait de changer le groupe du fichier à root et de changer les permissions du fichier à 640.

A présent, root peut lire le fichier en fonction des autorisations du groupe, mais other ne pourra pas le lire.

Il est possible aussi d'utiliser les ACL pour gérer les access.
Au final, il ne s'agit pas d'un problème lié à SELinux, ni d'un problème imposant d'assouplir la sécurité SELinux

Le problème avec SELinux est que le message AVC n'indique pas quel objet du système de fichiers a bloqué l'accès par défaut. La raison est celle de la performance.

Il faut donc activer l'audit complet et régénérer l'AVC afin d'obtenir le chemin de l'objet avec les mauvais contrôles DAC.
# echo "-w /etc/shadow -p wr" >> /etc/audit/audit.rules
# service auditd restart
Ou de façon non permanente:
# auditctl -w /etc/shadow -p w