Menu Fermer

Comment créer un profile AppArmor

AppArmor est une solution de sécurité qui vise à confiner les processus Linux pour s’assurer qu’ils n’accèdent pas à des ressources du système non nécessaires.
Pour cela, AppArmor fonctionne avec des profiles qui établissent la politique d’accès d’un processus.
Par défaut, AppArmor est fourni avec de nombreux profile mais il peut arriver qu’un profile ne soit pas disponible.
Dans ce cas là, il faut créer un nouveau profile.

Dans ce tutoriel, je vous montre deux méthodes pour créer un profile dans AppArmor.
La première méthode avec aa-genprof est la génération automatique, la seconde avec la création manuelle d’un profile AppArmor.

Comment créer un profile AppArmor

Comment créer un profile AppArmor automatiquement avec aa-genprof

aa-genprof est un utilitaire qui permet de générer automatiquement un profile AppArmor.
Pour cela, il analyse les activités du processus, détecte les appels systèmes, les fichiers lus ou écrit, etc.
Ensuite, vous devez autoriser ou non ces accès.
Au bout du coup, il écrit automatiquement le profile AppArmor.

  • Le paquet apparmor-utils et le service audits sont nécessaire :
apt install apparmor-utils auditd
  • Puis on utilise aa-genprof avec la syntaxe suivante :
sudo aa-genprof /chemin/binaire
  • Par exemple pour établir un profile sur pihole-FTL :
sudo aa-genprof /usr/bin/pihole-FTL
  • aa-genprof se met en mode Scan pour analyser l’activité de l’application. Utilisez celle-ci puis appuyez sur la touche S, cela va créer les logs d’audit
  • Répétez l’opération en utilisant à nouveau le programme
aa-genprof /usr/bin/pihole-FTL

Before you begin, you may wish to check if a
profile already exists for the application you
wish to confine. See the following wiki page for
more information:
https://gitlab.com/apparmor/apparmor/wikis/Profiles

Profiling: /usr/bin/pihole-FTL

Please start the application to be profiled in
another 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.

(S)can system log for AppArmor events] / (F)inish
  • A partir de là, on autorise les accès au système. Par exemple ci-dessous, doit-on autoriser pihole-FTL à exécuter un processus enfant /sur/bin/dash et de quelle manière (hérité, enfant, etc).
Profile:  /usr/bin/pihole-FTL
Execute:  /usr/bin/dash
Severity: unknown

(I)nherit / (C)hild / (N)amed / (U)nconfined / (X) ix On / (D)eny / Abo(r)t / (F)inish
Comment créer un profil AppArmor automatiquement avec aa-genprof
Comment créer un profil AppArmor automatiquement avec aa-genprof
  • Vient ensuite les autorisations de fichiers:
Comment créer un profil AppArmor automatiquement avec aa-genprof
  • Une fois toutes les autorisations établies, on vous demande d’enregistrer le profile avec S
  • Puis appuyez sur F pour terminer le scan
The following local profiles were changed. Would you like to save them?

 [1 - /usr/bin/pihole-FTL]
  2 - netstat
(S)ave Changes / Save Selec(t)ed Profile / [(V)iew Changes] / View Changes b/w (C)lean profiles / Abo(r)t
Writing updated profile for /usr/bin/pihole-FTL.
Writing updated profile for netstat.
  • Assurez vous de passer le binaire en mode complain pour n’effectuer aucun blocage :
aa-complain /chemin/binaire
  • Vérifiez les journaux /var/log/syslog et corrigez le profile au besoin en répétant l’opération aa-genprof pour mettre à jour le profile à tout moment.

Le profile créé se trouve dans /etc/apparmor.d/, il est tout à fait possible de le modifier manuellement par la suite.

Comment créer un profile AppArmor manuellement

Dans cette seconde méthode, on créé le profile AppArmor de zéro.

Dans cet exemple, nous allons créer un profile AppArmor pour le service rsync.
Le principe est de créer le profile puis de le passer en complain mode afin de vérifier dans les logs, les accès nécessaire à l’application.
Puis on corrige petit à petit le profile afin de donner les accès adéquate.
Avec l’habitude, une grande partie des accès peut être anticipée pour écrire une grande partie du profile.

Tout d’abord, on commence par créer le fichier :

vim /etc/apparmor.d/usr.bin.rsync

Puis on peut créer ce profile simple qui donne accès au binaire de rsync.

#include <tunables/global>

/usr/bin/rsync flags=(complain) {

#include <abstractions/base>

/usr/bin/rsync mr,

}

Les abstractions sont des fichiers de politiques de bases, présents dans /etc/apparmor.d/abstractions/, que l’on peut appeler depuis un profile. Cela évite de devoir recréer des règles sur des librairies communes à différents types de profiles.
On en trouve différents selon les besoins :

  • #include <abstractions/base> charge un fichier de base qui donne accès aux librairies Linux. En général, elles sont nécessaires pour le fonctionnent d’un binaire. Ici nous allons donc l’utiliser
  • #include <abstractions/nameservice> : donne accès aux librairies et certaines protocoles comme DNS, LDAP, etc, fichier /etc/resolv.conf, utile pour les binaires réseaux
  • #include <abstractions/ssl_certs> : permet l’accès aux fichiers de certificats du système dont notamment /etc/ssl/
Vérifiez bien le contenu avant d’inclure un fichier d’abstraction, par exemple nameservice et authentication donnent accès à /etc/passwd et /etc/group ce que l’on ne veut certainement pas dans le cas d’un serveur WEB.

On en trouve ensuite des spécifiques comme abstractions/openssl, abstractions/php ou abstractions/apache_2.
Là pas de magie, il faut vérifier avant et avec l’habitude, on saura lesquels sont nécessaire selon le type de binaires.

Ensuite on passe le profile en mode complain :

aa-complain /usr/bin/rsync

Surveillez les logs /var/log/syslog pour vérifier les accès et corrigez le profile en fonction.
Par exemple ci-dessous, ce dernier nécessite certains privilèges :

Jul 13 18:05:27 ns3140199 kernel: [12337303.504464] audit: type=1400 audit(1657735527.558:43): apparmor="ALLOWED" operation="capable" profile="/usr/bin/rsync" pid=23890 comm="rsync" capability=10  capname="net_bind_service"
Jul 14 01:40:53 ns3140199 kernel: [12364629.671772] audit: type=1400 audit(1657762853.583:1346): apparmor="ALLOWED" operation="capable" profile="/usr/bin/rsync" pid=20429 comm="rsync" capability=2  capname="dac_read_search"
Jul 14 01:40:53 ns3140199 kernel: [12364629.671778] audit: type=1400 audit(1657762853.583:1347): apparmor="ALLOWED" operation="capable" profile="/usr/bin/rsync" pid=20429 comm="rsync" capability=18  capname="sys_chroot"
Jul 14 01:40:53 ns3140199 kernel: [12364629.671781] audit: type=1400 audit(1657762853.583:1348): apparmor="ALLOWED" operation="capable" profile="/usr/bin/rsync" pid=20429 comm="rsync" capability=6  capname="setgid"
Jul 14 01:40:53 ns3140199 kernel: [12364629.671785] audit: type=1400 audit(1657762853.583:1349): apparmor="ALLOWED" operation="capable" profile="/usr/bin/rsync" pid=20429 comm="rsync" capability=7  capname="setuid"

On les ajoute grâce à capability.
J’ajoute aussi network inet tcp car rsynd écoute en TCP IPv4 et IPv6. Il est possible de limiter sur énormément de protocoles : AppArmor Network Access Control et AppArmor_Core_Policy_Reference.
Reportez vous aussi au man capabilities.

   # Privleges
   capability net_bind_service,
   capability sys_chroot,
   capability dac_read_search,
   capability setgid,
   capability setuid,
   network inet tcp,

Puis sans surprise, AppArmor rapporte des accès aux fichiers de configuration de /etc utiles pour initialiser l’application.

Jul 14 02:10:02 ns3140199 kernel: [12366378.128748] audit: type=1400 audit(1657764602.028:1350): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/host.conf" pid=23602 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:10:02 ns3140199 kernel: [12366378.128755] audit: type=1400 audit(1657764602.028:1351): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/run/resolvconf/resolv.conf" pid=23602 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:10:02 ns3140199 kernel: [12366378.129017] audit: type=1400 audit(1657764602.028:1352): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/nsswitch.conf" pid=23602 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:10:02 ns3140199 kernel: [12366378.129411] audit: type=1400 audit(1657764602.028:1353): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/hosts" pid=23602 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:10:02 ns3140199 kernel: [12366378.176498] audit: type=1400 audit(1657764602.072:1354): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/hosts" pid=23602 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:10:02 ns3140199 kernel: [12366378.278979] audit: type=1400 audit(1657764602.176:1355): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/rsyncd.secrets" pid=23602 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:11:22 ns3140199 kernel: [12366458.436406] audit: type=1400 audit(1657764682.335:1356): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/host.conf" pid=24193 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:11:22 ns3140199 kernel: [12366458.436412] audit: type=1400 audit(1657764682.335:1357): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/run/resolvconf/resolv.conf" pid=24193 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:11:22 ns3140199 kernel: [12366458.436711] audit: type=1400 audit(1657764682.335:1358): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/nsswitch.conf" pid=24193 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:11:22 ns3140199 kernel: [12366458.437064] audit: type=1400 audit(1657764682.335:1359): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/hosts" pid=24193 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:11:22 ns3140199 kernel: [12366458.452354] audit: type=1400 audit(1657764682.351:1360): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/hosts" pid=24193 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
Jul 14 02:11:22 ns3140199 kernel: [12366458.499136] audit: type=1400 audit(1657764682.399:1361): apparmor="ALLOWED" operation="open" profile="/usr/bin/rsync" name="/etc/rsyncd.secrets" pid=24193 comm="rsync" requested_mask="r" denied_mask="r" fsuid=0 ouid=0


Il faut donc les ajouter, ici, cela ne nécessite que des accès en lecture (r) :

 # CONFIGURATION

  /etc/rsyncd.conf r,
  /etc/rsyncd.secrets r,
  /etc/gai.conf r,
  /etc/hosts r,
  /etc/hosts.conf r,
  /etc/nsswitch.conf r,
  /run/resolvconf/resolv.conf r,

Logiquement rsyncd a besoin d’écrire des logs, on donne donc accès en lecture et écriture (rw) : # Logs /var/log/rsyncd.log rw,

Puis il faut pouvoir lire et écrire dans les sous-répertoires de destination de la sauvegarde :

 # Access au repertoire de sauvegarde
  owner /home/sauvegarde/** rw,

Enfin une fois tout cela configuré, on demande à AppArmor de relire le profil.
Pour cela, on utilise la commande apparmor_parser avec l’option -r :

apparmor_parser -r /etc/apparmor.d/profile

Le script final :

#include <tunables/global>

/usr/bin/rsync {

   #include <abstractions/base>

   # Privleges
   capability net_bind_service,
   capability sys_chroot,
   capability dac_read_search,
   capability setgid,
   capability setuid,
   network inet tcp,

   # Binaires
   /usr/bin/rsync mr,

  /etc/rsyncd.conf r,
  /etc/rsyncd.secrets r,
  /etc/gai.conf r,
  /etc/hosts r,
  /etc/hosts.conf r,
  /etc/nsswitch.conf r,
  /run/resolvconf/resolv.conf r,

  # Logs
  /var/log/rsyncd.log rw,

  # Access au repertoire de sauvegarde
  /home/sauvegarde rw,
  /home/sauvegarde/** rw,

}

La syntaxe AppArmor sur la création de profile

Voici quelques compléments sur la syntaxe de contrôle des fichiers et répertoires d’AppArmor

Tout d’abord, voici les accès possibles aux fichiers, répertoires et processus :

  • a : append – peut écrire à la fin du fichier
  • r : lecture
  • w : écriture
  • m : memory map comme exécutable
  • k : verrouillage de fichiers
  • l : créer des liens durs
  • rl : le mode de liaison accorde l’autorisation de créer un lien vers des fichiers arbitraires, à condition que le lien ait un sous-ensemble des autorisations accordées par la cible (test d’autorisation de sous-ensemble).
  • ix : exécution et héritage de ce profil
  • px : exécution sous un autre profil, après le nettoyage de l’environnement
  • ux : exécution non raffiné, Après avoir nettoyé l’environnement
ExempleDescription
/etc/ld.so.cache r,Le fichier peut être lu
/var/run/myprog.pid rw,Le fichier peut être lu et écrit
/etc/apache2/* r,Tous les fichiers dans /etc/apache2 peuvent être lus.
/srv/www/htdocs r,
/srv/www/htdocs/** r,
Tous les fichiers dans les HTDOC (et ci-dessous) peuvent être lus.
/tmp/myprog.* l,Le programme peut créer et supprimer des liens avec ce nom.
/bin/mount uxLe programme peut exécuter / bin / montage qui s’exécutera sans contrainte; Autrement dit, sans profil Apparmor.
/usr/bin/procmail pxLe programme peut exécuter procmail, qui s’exécutera sous contrainte de son propre profil.
/usr/bin/sendmail ixLe programme peut exécuter sendmail, qui héritera du profil du programme actuel.

Voici quelques exemples de syntaxes de contrôle d’accès AppArmor :

  • Autoriser la lecture de l’accès aux fichiers dans le répertoire /quelque/aléatoire/exemple. :
/quelque/aléatoire/exemple/* r,
  • Autoriser l’accès à lire au répertoire /quelque/aléatoire/exemple/ uniquement :
/quelque/aléatoire/exemple/ r,
  • Donner un accès à lire à tous les sous-répertoires de /quelque/aléatoire/exemple/ (mais pas /quelque/aléatoire/exemple/ lui-même) :
/quelque/aléatoire/exemple/** r,
  • Donner l’accès à la lecture aux fichiers sous /quelque/aléatoire/exemple/ mais exclus les sous-répertoires :
/quelque/aléatoire/exemple/**[^/] r,

La syntaxe supporte les expressions régulières basiques telles :

*Substituts pour n’importe quel nombre de caractères, sauf /.exemple: un nombre arbitraire d’éléments de chemin de fichier.
**Substituts de n’importe quel nombre de caractères, y compris /
?Remplace tout caractère unique, sauf /.
[abc]Substituts du caractère unique A, B ou C.
[a-c]Substituts du caractère unique a, b ou c.
[ab,cd}Se développe à une règle pour correspondre à AB et à une règle pour correspondre au CD
[^a]Substituts à tout personnage sauf a.
Syntaxe des contrôles de fichiers et répertoires

Pour aller plus loin dans la syntaxe des profils AppArmor, reportez-vous à cette documentation : Profile Components and Syntax