Concetti di SELinux

Consulta questa pagina per acquisire familiarità 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. Essendo un sistema MAC, differisce dal familiare sistema di controllo degli accessi discrezionali (DAC) 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. Si tratta generalmente di un approccio a grana grossa e soggetto a un'escalation involontaria dei privilegi. Un sistema MAC, invece, consulta un'autorità centrale per prendere 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 momento in cui ciascuna di queste azioni verrà eseguita, viene richiamata una funzione hook LSM per determinare se l'azione debba 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 policy, 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'utilizzo di strumenti come i controlli di accesso discrezionali e obbligatori di Android ti offre una struttura per garantire che il tuo software venga eseguito solo al livello di privilegio minimo. Ciò mitiga 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 degli accessi obbligatorio (MAC) rispetto ai tradizionali ambienti di controllo degli accessi discrezionali (DAC). 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, 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 è assegnato il privilegio 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.

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

Livelli di applicazione

SELinux può essere implementato in diverse modalità:

  • Permissivo : la politica di sicurezza di SELinux non viene applicata, ma 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 policy agisce o ti consente semplicemente di raccogliere potenziali fallimenti. Il permissivo è particolarmente utile durante l'implementazione.

Tipi, attributi e regole

Android si affida al componente Type Enforcement (TE) di SELinux per la sua policy. Significa che a tutti gli oggetti (come file, processo o socket) è associato un tipo . Ad esempio, per impostazione predefinita, un'app avrà il tipo untrusted_app . Per un processo, il suo tipo è noto anche 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, esiste il permesso open per il file di classe. Mentre i tipi e gli attributi vengono aggiornati regolarmente come parte della policy SELinux di Android, le autorizzazioni e le classi vengono definite staticamente e raramente aggiornate come parte di una nuova versione di Linux.

Una regola politica ha la forma: allow source target : class permissions ; Dove:

  • Sorgente : il tipo (o attributo) dell'oggetto della regola. Chi richiede l'accesso?
  • Target : il tipo (o attributo) dell'oggetto. A cosa è richiesto l'accesso?
  • Classe - Il tipo di oggetto (ad esempio file, socket) a cui si accede.
  • Autorizzazioni : l'operazione (o l'insieme di operazioni) (ad esempio 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 app con isolatedProcess=true nel 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 espanso nell'elenco di domini o tipi associati all'attributo. Alcuni attributi notevoli 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 richiamare 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 le autorizzazioni 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 ogni volta che è possibile per contribuire a ridurre la probabilità di errori dovuti al rifiuto delle relative autorizzazioni.

Una volta definito un tipo, è necessario associarlo al file o al processo che rappresenta. Vedi 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

Durante il debug delle policy SELinux o l'etichettatura dei file (tramite file_contexts o quando si esegue ls -Z ), potresti imbatterti 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 è possibile ignorare i campi user , role e sensitivity di un contesto (vedi Specificità ). Il campo type è spiegato nella sezione precedente. categories fanno parte del supporto Multi-Level Security (MLS) in SELinux. A partire 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 policy 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à SELinux non vengono utilizzate. La sensibilità s0 predefinita è sempre impostata.
  • I booleani di SELinux non vengono utilizzati. Una volta creata la policy per un dispositivo, questa non dipende dallo stato del dispositivo. Ciò semplifica il controllo e il debug delle policy.