Concetti di SELinux

Rivedi questa pagina per familiarizzare con i concetti di SELinux.

Controllo accessi obbligatorio

Security Enhanced Linux (SELinux), è un sistema di controllo degli accessi (MAC) obbligatorio per il sistema operativo Linux. Come sistema MAC, differisce dal familiare sistema DAC (Discretional Access Control) di Linux. In un sistema DAC esiste un concetto di proprietà, in base al quale il proprietario di una particolare risorsa controlla i permessi di accesso ad essa associati. Questo è generalmente a grana grossa e soggetto a un'escalation di privilegi non intenzionale. Un sistema MAC, tuttavia, consulta un'autorità centrale per una decisione su tutti i tentativi di accesso.

SELinux è stato implementato come parte del framework Linux Security Module (LSM), che riconosce vari oggetti del kernel e le azioni sensibili eseguite su di essi. Nel punto in cui ciascuna di queste azioni verrebbe eseguita, viene chiamata una funzione di hook LSM per determinare se l'azione deve essere consentita o meno in base alle informazioni memorizzate in un oggetto di sicurezza opaco. SELinux fornisce un'implementazione per questi hook e la gestione di questi oggetti di sicurezza, che si combinano con la propria politica, per determinare le decisioni di accesso.

Insieme ad altre misure di sicurezza di Android, la politica di controllo degli accessi di Android limita notevolmente il potenziale danno di macchine e account compromessi. L'uso di strumenti come i controlli di accesso discrezionali e obbligatori di Android ti offre una struttura per garantire che il tuo software funzioni solo al livello di privilegio minimo. Ciò attenua gli effetti degli attacchi e riduce la probabilità che processi errati sovrascrivano o addirittura trasmettano dati.

In Android 4.3 e versioni successive, SELinux fornisce un ombrello di controllo dell'accesso (MAC) obbligatorio rispetto agli ambienti DAC (Discretional Access Control) tradizionali. Ad esempio, il software deve in genere essere eseguito come account utente root per scrivere su dispositivi a blocchi grezzi. In un ambiente Linux tradizionale basato su DAC, se l'utente root viene compromesso, l'utente può scrivere su ogni dispositivo a blocchi non elaborati. Tuttavia, SELinux può essere utilizzato per etichettare questi dispositivi in ​​modo che il processo a cui è stato assegnato il privilegio di root possa scrivere solo su quelli specificati nella policy associata. In questo modo, il processo non può sovrascrivere dati e impostazioni di sistema al di fuori dello specifico dispositivo a blocchi grezzi.

Vedere Casi d'uso per ulteriori esempi di minacce e modi per affrontarle con SELinux.

Livelli di applicazione

SELinux può essere implementato in diverse modalità:

  • Permissiva - La politica di sicurezza di SELinux non viene applicata, solo registrata.
  • Applicazione : la politica di sicurezza viene applicata e registrata. Gli errori vengono visualizzati come errori EPERM.

Questa scelta è binaria e determina se la tua politica interviene o ti consente semplicemente di raccogliere potenziali fallimenti. Permissive è particolarmente utile durante l'implementazione.

Tipi, attributi e regole

Android si basa sul componente Type Enforcement (TE) di SELinux per la sua politica. Significa che tutti gli oggetti (come file, processo o socket) hanno un tipo ad essi associato. Ad esempio, per impostazione predefinita, un'app avrà il tipo untrusted_app . Per un processo, il suo tipo è anche noto come dominio . È possibile annotare un tipo con uno o più attributi . Gli attributi sono utili per fare riferimento a più tipi contemporaneamente.

Gli oggetti sono mappati su classi (ad esempio, un file, una directory, un collegamento simbolico, un socket) e i diversi tipi di accesso per ciascuna classe sono rappresentati da permessi . Ad esempio, l'autorizzazione open esiste per il file di classe . Sebbene i tipi e gli attributi vengano aggiornati regolarmente come parte della politica SELinux di Android, i permessi e le classi sono definiti staticamente e raramente aggiornati come parte di una nuova versione di Linux.

Una regola dei criteri si presenta nella forma: allow source target : class permissions ; dove:

  • Fonte : il tipo (o attributo) dell'oggetto della regola. Chi richiede l'accesso?
  • Destinazione - Il tipo (o attributo) dell'oggetto. A cosa è richiesto l'accesso?
  • Classe - Il tipo di oggetto (es. file, socket) a cui si accede.
  • Autorizzazioni - L'operazione (o insieme di operazioni) (ad es. lettura, scrittura) eseguita.

Un esempio di regola è:

allow untrusted_app app_data_file:file { read write };

Questo dice che le app possono leggere e scrivere file etichettati app_data_file . Esistono altri tipi di app. Ad esempio, isolated_app viene utilizzato per i servizi dell'app con isolatedProcess=true nel file manifest. Invece di ripetere la regola per entrambi i tipi, Android utilizza un attributo denominato appdomain per tutti i tipi che coprono le app:

# Associate the attribute appdomain with the type untrusted_app.
typeattribute untrusted_app, appdomain;

# Associate the attribute appdomain with the type isolated_app.
typeattribute isolated_app, appdomain;

allow appdomain app_data_file:file { read write };

Quando viene scritta una regola che specifica un nome di attributo, tale nome viene automaticamente esteso all'elenco di domini o tipi associati all'attributo. Alcuni attributi degni di nota sono:

  • domain - attributo associato a tutti i tipi di processo,
  • file_type - attributo associato a tutti i tipi di file.

Macro

Per l'accesso ai file in particolare, ci sono molti tipi di autorizzazione da considerare. Ad esempio, il permesso di read non è sufficiente per aprire il file o chiamare stat su di esso. Per semplificare la definizione delle regole, Android fornisce una serie di macro per gestire i casi più comuni. Ad esempio, per includere i permessi mancanti come open , la regola sopra potrebbe essere riscritta come:

allow appdomain app_data_file:file rw_file_perms;

Vedi i file global_macros e te_macros per ulteriori esempi di macro utili. Le macro dovrebbero essere utilizzate quando possibile per ridurre la probabilità di errori dovuti al rifiuto delle autorizzazioni correlate.

Una volta definito un tipo, è necessario associarlo al file o al processo che rappresenta. Vedere Implementazione di SELinux per maggiori dettagli su come viene eseguita questa associazione. Per ulteriori informazioni sulle regole, vedere SELinux Notebook .

Contesto e categorie di sicurezza

Quando si esegue il debug delle politiche di SELinux o si etichettano i file (tramite file_contexts o durante l'esecuzione di ls -Z ), è possibile imbattersi in un contesto di sicurezza (noto anche come label ). Ad esempio: u:r:untrusted_app:s0:c15,c256,c513,c768 . Un contesto di sicurezza ha il formato: user:role:type:sensitivity[:categories] . Di solito puoi ignorare i campi user , role e sensitivity di un contesto (vedi Specificità ). Il campo del type è spiegato nella sezione precedente. le categories fanno parte del supporto Multi-Level Security (MLS) in SELinux. Da Android S, le categorie vengono utilizzate per:

  • Isolare i dati dell'app dall'accesso da parte di un'altra app,
  • Isola i dati dell'app da un utente fisico a un altro.

Specificità

Android non utilizza tutte le funzionalità fornite da SELinux. Quando leggi la documentazione esterna, tieni presente questi punti:

  • La maggior parte delle politiche in AOSP sono definite utilizzando il Kernel Policy Language. Esistono alcune eccezioni per l'utilizzo del Common Intermediate Language (CIL).
  • Gli utenti SELinux non vengono utilizzati. L'unico utente definito è u . Quando necessario, gli utenti fisici vengono rappresentati utilizzando il campo delle categorie di un contesto di sicurezza.
  • I ruoli SELinux e il controllo degli accessi basato sui ruoli (RBAC) non vengono utilizzati. Vengono definiti e utilizzati due ruoli predefiniti: r per i soggetti e object_r per gli oggetti.
  • Le sensibilità di SELinux non vengono utilizzate. La sensibilità s0 predefinita è sempre impostata.
  • I booleani di SELinux non vengono utilizzati. Una volta che il criterio è stato creato per un dispositivo, non dipende dallo stato del dispositivo. Ciò semplifica il controllo e il debug delle politiche.