Product SiteDocumentation Site

14.4. Introduzione a AppArmor

14.4.1. Princìpi

AppArmor è un sistema di Mandatory Access Control (Controllo Accesso Obbligatorio) costruito sull'interfaccia LSM (Linux Security Modules) di Linux. In pratica, il kernel interroga AppArmor prima di ogni chiamata di sistema per sapere se il processo è autorizzato ad eseguire una data operazione. Attraverso questo meccanismo, AppArmor confina programmi ad una serie limitata di risorse.
AppArmor applica una serie di regole (note come "profilo") su ciascun programma. Il profilo applicato dal kernel dipende dal percorso di installazione del programma in esecuzione. Al contrario di SELinux (discusso nella Sezione 14.5, «Introduzione a SELinux»), le norme applicate non dipendono l'utente. Tutti gli utenti devono sottostare allo stesso insieme di regole quando è in esecuzione lo stesso programma (ma le autorizzazioni utente tradizionali sono ancora valide e potrebbero causare un comportamento diverso!).
I profili AppArmor sono memorizzati in /etc/apparmor.d/ e contengono un elenco delle regole di controllo d'accesso alle risorse che ogni programma può utilizzare. I profili sono compilati e caricati nel kernel dal comando apparmor_parser. Ogni profilo può essere caricato sia in esecuzione sia in complaining mode. La prima fa rispettare la policy e registra i tentativi di violazione, mentre la seconda non applica la policy ma registra sempre le chiamate di sistema che sarebbero state negate.

14.4.2. Abilitazione di AppArmor e gestione dei profili di AppArmor

Supporto ad AppArmor è integrato nei kernel standard forniti da Debian. Abilitazione AppArmor è quindi solo una questione di installare alcuni pacchetti e l'aggiunta di alcuni parametri alla riga di comando del kernel:
# 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
Dopo un riavvio, AppArmor è funzionante e aa-status lo confermerà in fretta:
# 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.
Lo stato di ogni profilo può essere scambiato tra la modalità enforce e complain con le chiamate di aa-enforce e aa-complain passando come parametro o il percorso del file eseguibile oppure il percorso del file della policy. Inoltre un profilo può essere completamente disabilitato con aa-disable o messo in modalità di controllo (per registrare anche le chiamate di sistema accettate) con 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.

14.4.3. Creare un nuovo profilo

Anche se la creazione di un profilo di AppArmor è piuttosto facile, la maggior parte dei programmi non ne hanno uno. In questa sezione verròà mostrato come creare un nuovo profilo da zero solo utilizzando il programma di destinazione e lasciando che AppArmor monitori le chiamate che il sistema fa e le risorse a cui accede.
I programmi più importanti che devono essere monitorati sono i programmi che si affacciano sulla rete che come tali sono i più probabili obiettivi di aggressori remoti. Per questo AppArmor fornisce il comodo comando aa-unconfined per elencare i programmi che non hanno un profilo associato che sono esposti ad un socket di rete aperto. Con l'opzione --paranoid si ottengono tutti i processi non confinati che hanno una connessione di rete attiva.
# aa-unconfined
801 /sbin/dhclient not confined
890 /sbin/rpcbind not confined
899 /sbin/rpc.statd not confined
929 /usr/sbin/sshd not confined
941 /usr/sbin/avahi-daemon confined by '/usr/sbin/avahi-daemon (complain)'
988 /usr/sbin/minissdpd not confined
1276 /usr/sbin/exim4 not confined
1485 /usr/lib/erlang/erts-6.2/bin/epmd not confined
1751 /usr/lib/erlang/erts-6.2/bin/beam.smp not confined
19592 /usr/lib/dleyna-renderer/dleyna-renderer-service not confined
Nell'esempio seguente, cercheremo quindi di creare un profilo per /sbin/dhclient. Per questo useremo aa-genprof dhclient. Vi invitiamo ad utilizzare l'applicazione in un'altra finestra e una volta finito tornare a aa-genprof per cercare eventi AppArmor nei log di sistema e convertire quei log in regole d'accesso. Per ogni evento registrato, verranno suggerite una o più regole che è possibile approvare o modificare ulteriormente in diversi modi:
# aa-genprof dhclient
Writing updated profile for /sbin/dhclient.
Setting /sbin/dhclient to complain mode.

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:
http://wiki.apparmor.net/index.php/Profiles

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.

Profiling: /sbin/dhclient

[(S)can system log for AppArmor events] / (F)inish
Reading log entries from /var/log/audit/audit.log.

Profile:  /sbin/dhclient 1
Execute:  /usr/lib/NetworkManager/nm-dhcp-helper
Severity: 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 when
switching profiles?

Sanitising environment is more secure,
but some applications depend on the presence
of 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_raw

Profile:    /sbin/dhclient 2
Capability: net_raw
Severity:   unknown

[(A)llow] / (D)eny / (I)gnore / Audi(t) / Abo(r)t / (F)inish
A
Adding capability net_raw to profile.

Profile:  /sbin/dhclient 3
Path:     /etc/nsswitch.conf
Mode:     r
Severity: 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)ore
3

Profile:  /sbin/dhclient
Path:     /etc/nsswitch.conf
Mode:     r
Severity: 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)ore
A
Adding #include <abstractions/nameservice> to profile.

Profile:  /sbin/dhclient
Path:     /proc/7252/net/dev
Mode:     r
Severity: 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)ore
A
Adding /proc/*/net/dev r to profile

[...]
Profile:  /sbin/dhclient 4
Path:     /run/dhclient-eth0.pid
Mode:     w
Severity: 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)ore
N

Enter new path: /run/dhclient*.pid

Profile:  /sbin/dhclient
Path:     /run/dhclient-eth0.pid
Mode:     w
Severity: 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)ore
A
Adding /run/dhclient*.pid w to profile

[...]
Profile:  /usr/lib/NetworkManager/nm-dhcp-helper 5
Path:     /proc/filesystems
Mode:     r
Severity: 6

 [1 - /proc/filesystems]
[(A)llow] / (D)eny / (I)gnore / (G)lob / Glob with (E)xtension / (N)ew / Abo(r)t / (F)inish / (M)ore
A
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)t
S
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)inish
F
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/Profiles

Finished generating profile for /sbin/dhclient.
Notare che il programma non visualizza i caratteri di controllo indietro che si digitano ma per la chiarezza espositiva sono stati inclusi nella trascrizione precedente.

1

Il primo evento rilevato è l'esecuzione di un altro programma. In tal caso, si dispone di più opzioni: è possibile eseguire il programma con il profilo del processo padre (la scelta “Inherit”), è possibile eseguirlo con il proprio profilo dedicato (le scelte "Profile" e "Named", differiscono solo per la possibilità di utilizzare un nome di profilo arbitrario), è possibile eseguirlo con un sub-profilo del processo padre (la scelta "Child"), è possibile eseguirlo senza alcun profilo (la scelta "Unconfined") o si può decidere di non farlo eseguire a nessuno (la scelta "Deny").
Si noti che quando si sceglie di eseguire il programma sotto un profilo dedicato che non esiste ancora, lo strumento creerà il profilo mancante per voi ed allo stesso tempo proporrà delle regole per tale profilo.

2

A livello di kernel, i poteri speciali dell'utente root vengono suddivisi in "capacità". Quando una chiamata di sistema richiede una capacità specifica, AppArmor verificherà se il profilo permette al programma di fare uso di questa capacità.

3

Qui il programma cerca le autorizzazioni di lettura per /etc/nsswitch.conf. aa-genprof ha rilevato che questo permesso è stato concesso anche da "astrazioni" multiple e le offre come scelte alternative. Un'astrazione fornisce un insieme riutilizzabile di regole di accesso raggruppando più risorse che sono di solito utilizzate insieme. In questo caso specifico, il file è generalmente reso accessibile attraverso le funzioni NameService relative della libreria C e digitiamo "3" per selezionare prima la scelta “#include <astrazioni/nomeservizio>” e poi "A" per consentirla.

4

Il programma cerca di creare il file /run/dhclient-eth0.pid. Se permettiamo la creazione di questo specifico file soltanto, il programma non funzionerà quando l'utente utilizzerà un'altra interfaccia di rete. Così selezioniamo "Nuovo" per sostituire il nome del file con il "/run/ddclient*.pid" più generico prima di registrare il dominio con "Consenti".

5

Si noti che la richiesta di accesso non è parte del profilo dhclient ma del nuovo profilo che abbiamo creato quando abbiamo permesso a /usr/lib/NetworkManager/nm-dhcp-helper di essere eseguito con il proprio profilo.
Dopo aver percorso tutti gli eventi registrati, il programma propone di salvare tutti i profili che sono stati creati durante l'esecuzione. In questo caso, abbiamo due profili che sono salvati in una volta con "Salva" (ma si possono salvare anche singolarmente) prima di lasciare il programma con "Fine".
aa-genprof è in realtà solo un modulo intelligente intorno a aa-logprof: esso crea un profilo vuoto, lo carica in modalità compain ed esegue aa-logprof che è uno strumento per aggiornare il profilo in base alle violazioni del profilo che sono state registrate. Così in seguito si può eseguire nuovamente questo strumento per migliorare il profilo appena creato.
Se si desidera che il profilo generato sia completo, è necessario utilizzare il programma in tutti i modi legittimamente possibili. Nel caso di dhclient, significa eseguirlo tramite Network Manager, eseguirlo tramite ifupdown, eseguirlo manualmente, ecc Alla fine, si potrebbe ottenere un /etc/apparmor.d/sbin.dhclient simile a questo:
# 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,

  }
}