Dettagli di AppArmor

Icon-obsolete.png Questo articolo o questo paragrafo fanno riferimento alla versione '9.x', che attualmente è obsoleta!
Per favore fai riferimento alla pagina di discussione di questo articolo per maggiori informazioni.

AppArmor Design

AppArmor è progettato per prendere di mira il problema della sicurezza delle applicazioni, che è di far si che un attacco non causi un comportamento indesiderato delle applicazioni. A dirsi sembra facile, ma attualmente è molto difficoltoso: mentre si può verificare un'applicazione per accertarsi che compia la relativa specifica funzionale, non si può verificare un'applicazione per accertarsi che non faccia mai niente altro quando riceve input sconosciuti, perché la lista degli input sconosciuti possibili è solitamente infinita. Citando Ivan Arce:"Il software affidabile fa ciò che si suppone che faccia. Il software sicuro fa ciò che si suppone che faccia... e niente altro".

Ci sono strumenti a tempo di compilazione che scandiscono il codice sorgente e/o i file binari per le potenziali vulnerabilità. Tuttavia, per motivi teorici e tecnici, tali soluzioni fanno un lavoro incompleto e sono difficili da applicare. Per motivi economici e sociali, strumenti e ragionevoli attenzioni sono raramente applicate. Come risultato, la moggior parte del software ha difetti latenti e molti di loro sono sfruttabili da un attacco che li porti a comportarsi in maniera non corretta. La sicurezza sarebbe facile da gestire se solo potessimo avere software privo di difetti, ma tale approccio presenta un problema dal lato della fornitura :)

Obiettivi di AppArmor

Per difenderci dai potenziali comportamenti scorretti del software, vogliamo applicare il principio del minor privilegio per le applicazioni. Ogni volta che un'applicazione è in esecuzione, limitarla all'accesso delle sole risorse di cui ha bisogno per compiere il suo lavoro. In questo modo, se mai fosse sfruttata, l'ammontare dei danni sarebbe minimizzato. Tuttavia abbiamo bisogno che anche la limitazione dei privilegi sia sicura, trasparente e veloce.

  • Sicura - l'applicazione non può sfuggire o by-passare il confinamento.
  • Trasparente - il software e gli utenti possono fare ciò che facevano prima, con il minor numero di cambiamenti possibile.
  • Veloce - la diminuzione della prestazione è trascurabile

Sicuro è vitale, perché la sicurezza non è uno scherzo. Trasparente e veloce sono vitali perché il modo peggiore di gestire la sicurezza è di non considerarla perché è troppo fastidiosa o ingombrante. Qui si descrive come AppArmor realizza la sicurezza, la prestazione e la trasparenza.

La sicurezza attraverso LSM: Linux Security Modules Interface

Per realizzare metodi di mediazione di sicurezza (non-oltrepassaggio) come AppArmor, è necessario che sia all'interno del kernel. AppArmor originariamente era una patch del kernel, ma questo crea maggiori problemi per la distribuzione e la pubblicazione, specialmente per gli utenti enterprise. Per realizzare la sicurezza a livello di kernel senza ricorrere a una patch, la società Immunix Inc. (che sviluppò AppArmor prima che fosse acquisita da Novell) creò un componente per Linux 2.6 chiamato LSM: Linux Security Modules Interface. LSM fornisce un API del kernel per i moduli che consente ai moduli caricabili di fare una mediazione efficace sul controllo di accesso. Lo sviluppo di LSM include altri partecipanti come la comunità di SELinux, IBM e altre comunità di sviluppatori open source.

La mediazione a livelli diversi da quello del kernel, per esempio nelle librerie, conduce alla oltrepassabilità: se un attacco può indurre l'esecuzione di codice arbitrario in un'applicazione confinata (p.e. buffer overflow), allora può causare una chiamata diretta al kernel invece di usare le librerie, quindi oltrepassando la mediazione. Inoltre tale mediazione si realizza meglio all'interno del kernel anziché intercettando le chiamate di sistema. Una mediazione sicura può essere realizzata rimpiazzando la tabella delle chiamate di sistema (così come fa Systrace) ma questo comporta tre significativi problemi:

  • Embolia del codice: il kernel ha molte infrastrutture da tradurre, per esempio una richiesta di aprire un file chiamato "foo" in un inode specifico considerando la directory corrente, ecc. Nessuna di queste informazioni è disponibile nel momento in cui è intercettata la chiamata di sistema, così il sistema di mediazione deve duplicare il codice per fare la traduzione prima che possa prendere una decisione adeguata sul consentire o meno l'accesso a "foo". Peggio, la traduzione è ora fatta due volte, penalizzando le prestazioni.
  • Protezione SMP: il nome del file richiesto è nella memoria accessibile all'utente, quindi è pericoloso cambiare tra il momento in cui il modulo per la mediazione controlla l'accesso e il momento in cui il kernel consente l'accesso. Così il modulo per la mediazione vede una richiesta di accesso per il file "foo" e il richiedente, dopo che è stato approvato modifica la richiesta in "../bar". Questo attacco ha successo particolarmente sulle macchine SMP, è le macchine multicore sono destinate a diventare prevalenti.
  • Linus: per motivi legati alla GPL, Linus ha deciso di rimuovere in Linux 2.6 la capacità di ricaricare la tabella delle chiamate di sistema, così l'interposizione tra esse diventa più problematica nei kernel moderni senza applicare una patch.

Così, invece di una mediazione sulle chiamate di sistema, LSM inserisce dei ganci all'interno del kernel. Ogni volta che una richiesta da parte di un processo a livello di utente conduce all'accesso di una importante struttura di dati all'interno del kernel, come i descrittori delle operazioni o gli inode, il gancio di LSM fa una chiamata a qualunque modulo LSM caricato chiedendo:"questo è ok?". Il modulo LSM valuta la situazione, prende una decisione e risponde con un "si" o "no" al kernel, il quale a sua volte consente l'accesso o restituisce un errore al richiedente. Quindi le tecnologie sul controllo degli accessi come SELinux e AppArmor possono svolgere il loro compito moduli caricabili, senza richiedere continue patch del kernel.

Le prestazioni attraverso la semplicità

Per ottenere la velocità, AppArmor usa un modello di sicurezza molto semplice, così che i controlli possano essere fatti rapidamente. In particolare, le regole sulla sicurezza sono molto piccole, così da poterle caricare completamente nella memoria del kernel, eliminando la necessità di una cache di secondo livello per la memorizzazione delle regole.

La trasparenza attraverso la familiarità

Per ottenere la trasparenza, AppArmor usa la classica semantica UNIX sulla sicurezza, ma la applica ai programmi. Una regola di AppArmor specifica l'insieme delle possibilità che un programma può avere rispetto alle estensioni POSIX standad sulla sicurezza (POSIX.1e capabilities) e specifica l'insieme dei file cui può avere accesso. Le POSIX.1e capabilities sono specificate dal nome. I file sono specificati dal path assoluto, includendo i lasciapassare integrati nella sintassi shell, seguito dalla modalità di accesso (R,W e X con giusto qualche abbellimento). Così una regola di AppArmor per confinare ntpd (il demone Network Time Protocol) appare come segue:

/usr/sbin/ntpd {
 #include <abstractions/base>
 #include <abstractions/nameservice>
 #include <program-chunks/ntpd>
 capability ipc_lock,
 capability net_bind_service,
 capability sys_time,
 capability sys_chroot,
 capability setuid,
 /etc/ntp.conf             r,
 /etc/ntp/drift*           rwl,
 /etc/ntp/keys             r,
 /etc/ntp/step-tickers     r,
 /tmp/ntp*                 rwl,
 /usr/sbin/ntpd            rix,
 /var/log/ntp              w,
 /var/log/ntp.log          w,
 /var/run/ntpd.pid         w,
 /var/lib/ntp/drift        rwl,
 /var/lib/ntp/drift.TEMP   rwl,
 /var/lib/ntp/var/run/ntp/ntpd.pid w,
 /var/lib/ntp/drift/ntp.drift      r,
 /drift/ntp.drift.TEMP     rwl,
 /drift/ntp.drift          rwl,
}


Da qui, dovrebbe essere relativamente seplice manipolare le regole di sicurezza per le applicazioni attraverso una combinazione di conoscenza approfondita e di tentativi. Tuttavia, potrebbe essere così noioso che la maggior parte degli sviluppatori e degli utenti potrebbe rifiutarsi di fare questo lavoro. Per migliorare la trasparenza, AppArmor include una "modalità di apprendimento" per consentire la modifica delle regole eseguendo l'applicazione e osservando cosa fa. Nella modalità di apprendimento, le regole non sono forzate all'istante, ma le violazioni sono registrate, e vengono tracciate le biforcazioni del processo, così che il registro dell'esecuzione di un'applicazione costruisca una descrizione caratteristica delle attività dell'applicazione. AppArmor include un programma per l'analisi del registro che scandisce i log, fa domande all'utente e automaticamente crea un profilo del programma. La modalità di apprendimento e l'analizzatore del registro sono inoltre capaci di un miglioramento incrementale del profilo se ne esiste già uno, ma omette alcune regole necessarie.

Sicurezza delle applicazioni e sicurezza del sistema

Una singola applicazione può essere messa in sicurezza usando un profilo individuale, ma come si può mettere in sicurezza un sistema? La domanda cruciale è "contro quale minaccia?". Si potrebbe creare un profilo per tutti i programmi del sistema, ma sarebbe molto faticoso e nella maggior parte dei casi non necessario. Per esempio, si consideri il modello delle minacce dalla rete: si vogliono prevenire gli attacchi da remoto per ottenere il controllo del sistema. Per questo tipo di attacco è necessario assicurarsi che tutti i programmi che comunicano con la rete abbiano un profilo AppArmor. Se si crea un profilo per tutte le applicazioni che si connettono alla rete, allora i profili di AppArmor controllano completamente tutto ciò che un attacco dalla rete potrebbe causare al sistema.

Nota: quando un profilo AppArmor concede il permesso di eseguire un altro programma, specifica se il processo figlio sia eseguito nel suo stesso profilo (denotato px), nello stesso profilo del processo padre ereditandone le peculiarità (denotato ix) o se il processo figlio non debba avere limitazioni (denotato ux). I permessi px dovrebbero essere usati per i programmi più importanti i cui dati sono acceduti dal mediatore, così come Apache esegue Sendmail per iviare i messaggi. I permessi ix dovrebbero essere usati per i più piccoli, utility che operano su qualsiasi dato che gli viene passato dal processo padre, così come uno script shell esegue cp per copiare un file. I permessi ux sono molto pericolosi, dovrebbero essere usati con attenzione per consentire un accesso amministrativo che non è regolato da AppArmor, come l'ultima shell dell'amministratore di sistema eseguita dal demone SSH.

Poiché le minacce dalla rete sono una preoccupazione così diffusa, AppArmor include un analizzatore di sistema chiamato unconfined, che scandisce le porte di rete aperte della macchina, cerca i programmi che sono in ascolto su queste porte e fa una lista dei profili inerenti a quei programmi, se ce ne sono. Se unconfined rileva che tutte le porte di rete aperte conducono a profili di AppArmor, allora questo è il caso in cui questi profili definiscono la peggiore situazione che un attacco potrebbe imporre sulla macchina.

Similmente, per proteggere una workstation da un attacco dalla rete, tutti i programmi che processano imput provenienti dalla rete dovrebbero avere un profilo. Alcuni di questi programmi hanno persistenti porte aperte verso la rete, come i client ssh. Alcuni hanno porte aperte transienti, come i browser web, i client di posta e i client IM. Alcuni di tali programmi non hanno porte di rete, tuttavia processano imput provenienti dalla rete con elevati rischi di sicurezza, come OpenOffice cui viene spesso chiesto di aprire immediatamente file .doc che sono stati allegati a messaggi di posta. Tuttavia non c'è bisogno di un profilo per tutti i programmi installati sulla workstation, ma solo per quelli che processano imput provenienti dalla rete.

In una situazione differente, per proteggere una postazione dagli attacchi degli utenti, devono avere un profili tutti i programmi che accettano imput da tastiera e mouse, così come ogni altro lettore di periferiche come i lettori di codici a barre o di bande magnetiche. Questo "modello di minaccia da tastiera" è molto simile al modello di minaccia dalla rete, solo che le minacce arrivano da dispositivi IO locali come una tastiera o un card reader, piuttosto che dalle interfacce di rete.