AppArmor est un système de contrôle d'accès obligatoire (Mandatory Access Control) qui s'appuie sur l'interface Linux Security Modules fournie par le noyau Linux. Concrètement, le noyau interroge AppArmor avant chaque appel système pour savoir si le processus est autorisé à effectuer l'opération concernée. Ce mécanisme permet à AppArmor de confiner des programmes à un ensemble restreint de ressources.
AppArmor applique un ensemble de règles (un «profil») à chaque programme. Le profil appliqué par le noyau dépend du chemin d'installation du programme à exécuter. Contrairement à SELinux (décrit dans Section14.5, «Introduction à SELinux»), les règles appliquées ne dépendent pas de l'utilisateur: tous les utilisateurs sont concernés par le même jeu de règles lorsqu'ils exécutent le même programme (mais les permissions habituelles des utilisateurs jouent toujours, ce qui peut donner un comportement différent).
Les profils AppArmor sont stockés dans /etc/apparmor.d/
; ils consistent en une liste de règles de contrôle d'accès sur les ressources que peut utiliser chaque programme. Les profils sont compilés et chargés dans le noyau par le biais de la commande apparmor_parser
. Chaque profil peut être chargé soit en mode strict (enforcing) soit en mode relâché (complaining). Le mode strict applique les règles et rapporte les tentatives de violation, alors que le mode relâché se contente d'enregistrer dans les journaux système les appels système qui auraient été bloqués, sans les bloquer réellement.
Le support d'AppArmor est intégré aux noyaux standards fournis par Debian. Pour activer AppArmor, il suffira donc d'installer quelques paquets et d'ajouter quelques paramètres à la ligne de commande du noyau:
#
apt install apparmor apparmor-profiles apparmor-utils
[...]#
perl -pi -e 's,GRUB_CMDLINE_LINUX="(.*)"$,GRUB_CMDLINE_LINUX="$1 apparmor=1 security=apparmor",' /etc/default/grub
#
update-grub
Après un redémarrage, AppArmor sera opérationnel, ce que confirmera aa-status
:
#
aa-status
apparmor module is loaded.44 profiles are loaded.9 profiles are in enforce mode. /usr/bin/lxc-start /usr/lib/chromium-browser/chromium-browser//browser_java[...]35 profiles are in complain mode. /sbin/klogd[...]3 processes have profiles defined.1 processes are in enforce mode. /usr/sbin/libvirtd (1295) 2 processes are in complain mode. /usr/sbin/avahi-daemon (941) /usr/sbin/avahi-daemon (1000) 0 processes are unconfined but have a profile defined.
NOTE Autres profils AppArmor
Le paquet apparmor-profiles contient des profils développés par la communauté amont d'AppArmor. Pour en obtenir d'autres encore, il est possible d'installer apparmor-profiles-extra, qui contient des profils développés par Ubuntu et Debian.
Le statut de chaque profil peut être basculé entre les modes strict et relâché, avec les commandes aa-enforce
et aa-complain
, en leur passant en paramètre soit le chemin de l'exécutable concerné, soit le chemin du fichier de profil. Il est également possible de désactiver complètement un profil avec aa-disable
, ou de le basculer en mode audit (de sorte qu'il enregistre dans les journaux même les appels système acceptés) avec aa-audit
.
#
aa-enforce /usr/sbin/avahi-daemon
Setting /usr/sbin/avahi-daemon to enforce mode.
#
aa-complain /etc/apparmor.d/usr.bin.lxc-start
Setting /etc/apparmor.d/usr.bin.lxc-start to complain mode.
Bien qu'il soit assez simple de créer un profil AppArmor, peu de programmes en fournissent un. Cette section montre comment créer un nouveau profil depuis zéro, simplement en utilisant le programme visé et en indiquant à AppArmor de surveiller les appels système qu'il passe et les ressources qu'il utilise.
Les programmes qui devront être confinés en priorité sont ceux qui font face au réseau, car ce sont eux qui seront les cibles les plus alléchantes pour des attaquants distants. C'est précisément dans ce but qu'AppArmor fournit une commande aa-unconfined
, qui liste les programmes qui, sans avoir de profil associé, exposent quand même un port de communication. L'option --paranoid
liste même tous les processus non confinés qui ont au moins une connexion réseau ouverte.
#
aa-unconfined
801 /sbin/dhclient not confined890 /sbin/rpcbind not confined899 /sbin/rpc.statd not confined929 /usr/sbin/sshd not confined941 /usr/sbin/avahi-daemon confined by '/usr/sbin/avahi-daemon (complain)'988 /usr/sbin/minissdpd not confined1276 /usr/sbin/exim4 not confined1485 /usr/lib/erlang/erts-6.2/bin/epmd not confined1751 /usr/lib/erlang/erts-6.2/bin/beam.smp not confined19592 /usr/lib/dleyna-renderer/dleyna-renderer-service not confined
Dans l'exemple suivant, nous allons nous atteler à créer un profil pour /sbin/dhclient
. Nous allons pour cela utiliser la commande aa-genprof dhclient
, qui nous invite à utiliser l'application (dans une autre fenêtre) et à revenir à aa-genprof
une fois que c'est fait, pour scruter les journaux à la recherche d'événements AppArmor et convertir ces journaux en règles de contrôle d'accès. Pour chaque événement enregistré, une ou plusieurs suggestions de règles seront proposées, et il sera possible de les approuver telles quelles ou de les modifier de diverses manières:
#
aa-genprof dhclient
Writing updated profile for /sbin/dhclient.Setting /sbin/dhclient to complain mode.Before you begin, you may wish to check if aprofile already exists for the application youwish to confine. See the following wiki page formore information:http://wiki.apparmor.net/index.php/ProfilesPlease start the application to be profiled inanother window and exercise its functionality now.Once completed, select the "Scan" option below in order to scan the system logs for AppArmor events. For each AppArmor event, you will be given the opportunity to choose whether the access should be allowed or denied.Profiling: /sbin/dhclient[(S)can system log for AppArmor events] / (F)inishReading log entries from /var/log/audit/audit.log.Profile: /sbin/dhclient Execute: /usr/lib/NetworkManager/nm-dhcp-helperSeverity: unknown(I)nherit / (C)hild / (P)rofile / (N)amed / (U)nconfined / (X) ix On / (D)eny / Abo(r)t / (F)inish
P
Should AppArmor sanitise the environment whenswitching profiles?Sanitising environment is more secure,but some applications depend on the presenceof LD_PRELOAD or LD_LIBRARY_PATH.(Y)es / [(N)o]Y
Writing updated profile for /usr/lib/NetworkManager/nm-dhcp-helper.Complain-mode changes:WARN: unknown capability: CAP_net_rawProfile: /sbin/dhclient Capability: net_rawSeverity: unknown[(A)llow] / (D)eny / (I)gnore / Audi(t) / Abo(r)t / (F)inishA
Adding capability net_raw to profile.Profile: /sbin/dhclient Path: /etc/nsswitch.confMode: rSeverity: unknown 1 - #include <abstractions/apache2-common> 2 - #include <abstractions/libvirt-qemu> 3 - #include <abstractions/nameservice> 4 - #include <abstractions/totem> [5 - /etc/nsswitch.conf][(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)ore3
Profile: /sbin/dhclientPath: /etc/nsswitch.confMode: rSeverity: unknown 1 - #include <abstractions/apache2-common> 2 - #include <abstractions/libvirt-qemu> [3 - #include <abstractions/nameservice>] 4 - #include <abstractions/totem> 5 - /etc/nsswitch.conf [(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)oreA
Adding #include <abstractions/nameservice> to profile.Profile: /sbin/dhclientPath: /proc/7252/net/devMode: rSeverity: 6 1 - /proc/7252/net/dev [2 - /proc/*/net/dev][(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)oreA
Adding /proc/*/net/dev r to profile[...]Profile: /sbin/dhclient Path: /run/dhclient-eth0.pidMode: wSeverity: unknown [1 - /run/dhclient-eth0.pid][(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)oreN
Enter new path: /run/dhclient*.pidProfile: /sbin/dhclientPath: /run/dhclient-eth0.pidMode: wSeverity: unknown 1 - /run/dhclient-eth0.pid [2 - /run/dhclient*.pid][(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)oreA
Adding /run/dhclient*.pid w to profile[...]Profile: /usr/lib/NetworkManager/nm-dhcp-helper Path: /proc/filesystemsMode: rSeverity: 6 [1 - /proc/filesystems][(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)oreA
Adding /proc/filesystems r to profile= Changed Local Profiles =The following local profiles were changed. Would you like to save them? [1 - /sbin/dhclient] 2 - /usr/lib/NetworkManager/nm-dhcp-helper (S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)tS
Writing updated profile for /sbin/dhclient.Writing updated profile for /usr/lib/NetworkManager/nm-dhcp-helper.Profiling: /sbin/dhclient[(S)can system log for AppArmor events] / (F)inishF
Setting /sbin/dhclient to enforce mode.Setting /usr/lib/NetworkManager/nm-dhcp-helper to enforce mode.Reloaded AppArmor profiles in enforce mode.Please consider contributing your new profile!See the following wiki page for more information:http://wiki.apparmor.net/index.php/ProfilesFinished generating profile for /sbin/dhclient.
Il faut noter que le programme n'affiche pas les caractères de contrôle tapés ; nous les avons inclus dans la transcription ci-dessus pour clarifier les choses.
| Le premier événement détecté est l'exécution d'un autre programme. Dans ce cas, plusieurs choix s'offrent à nous: on peut soit lancer le programme avec le profil du programme parent (Inherit), soit le lancer avec un profil dédié (Profile et Name, qui ne diffèrent que par la possibilité de choisir un nom de profil arbitraire), soit le lancer avec un sous-profil du processus parent (Child), soit le lancer sans aucun profil (Unconfined), soit ne pas le lancer du tout (Deny). À noter que lorsque l'on choisit de lancer le processus fils selon un profil dédié mais qui n'existe pas encore, l'outil va créer le profil manquant, et proposer des suggestions de règles par la même occasion. |
| Au niveau du noyau, les pouvoirs spéciaux de l'utilisateur root ont été séparés en «capacités». Lorsqu'un appel système a besoin d'une capacité spécifique, AppArmor va vérifier que le profil permet au programme d'utiliser cette capacité. |
| Ici, le programme requiert les permissions de lecture sur |
| Le programme essaie de créer le fichier |
| Notons que cette tentative d'accès ne fait pas partie du profil dhclient, mais du nouveau profil que nous avons créé lorsque nous avons autorisé Une fois que tous les événements enregistrés ont été examinés, le programme propose de sauver tous les profils qui ont été créés pendant l'exécution. Dans notre cas, nous avons deux profils que nous enregistrons d'un coup avec «Save» (mais nous aurions aussi pu les enregistrer un par un) avant de quitter le programme avec «Finish». |
aa-genprof
n'est en fait qu'un petit script intelligent qui utilise aa-logprof
: il crée un profil vide, le charge en mode relâché, puis lance aa-logprof
. Ce dernier est un outil qui met à jour un profil en fonction des violations qui ont été enregistrées. On peut donc relancer cet outil plus tard, de manière à améliorer le profil nouvellement créé.
Pour que le profil généré soit complet, il faut utiliser le programme de toutes les manières légitimement possibles. Dans le cas de dhclient, cela implique de le lancer via Network Manager, mais aussi via ifupdown, à la main, etc. À la fin, on obtient un /etc/apparmor.d/sbin.dhclient
qui ressemble à ceci:
# Last Modified: Tue Sep 8 21:40:02 2015#include <tunables/global>/sbin/dhclient { #include <abstractions/base> #include <abstractions/nameservice> capability net_bind_service, capability net_raw, /bin/dash r, /etc/dhcp/* r, /etc/dhcp/dhclient-enter-hooks.d/* r, /etc/dhcp/dhclient-exit-hooks.d/* r, /etc/resolv.conf.* w, /etc/samba/dhcp.conf.* w, /proc/*/net/dev r, /proc/filesystems r, /run/dhclient*.pid w, /sbin/dhclient mr, /sbin/dhclient-script rCx, /usr/lib/NetworkManager/nm-dhcp-helper Px, /var/lib/NetworkManager/* r, /var/lib/NetworkManager/*.lease rw, /var/lib/dhcp/*.leases rw, profile /sbin/dhclient-script flags=(complain) { #include <abstractions/base> #include <abstractions/bash> /bin/dash rix, /etc/dhcp/dhclient-enter-hooks.d/* r, /etc/dhcp/dhclient-exit-hooks.d/* r, /sbin/dhclient-script r, }}