Archivi tag: sesearch

Breve guida su SElinux

Premesso che per i server esposti direttamente su Internet la sicurezza non è mai troppa, è sempre buona norma abilitare, lato sistema operativo, dei meccanismi stringenti per il controllo degli accessi.

In particolare, le principali tecniche di questo tipo sono 3, ovvero:

1) DAC (Discretionary Access Control), in cui è l’owner (proprietario) del file o della directory a decidere chi (e come) può averne accesso;

2) RBAC (Role Based Access Control), in cui i permessi associati a ciascun utente sono strettamente correlati al loro ruolo (ne sono un tipico esempio le view della CLI relativa ai dispositivi Cisco, oppure i meccanismi di AAA previsti nell’ambito del protocollo TACACS+);

3) MAC (Mandatory Access Control), in cui è il sistema operativo stesso a decidere chi (e come) può avere accesso ad un file o ad una directory (tale concetto, nel caso dei sistemi *nix, è estendibile anche a socket, thread e processi, poichè in Unix everything is a file). SElinux fa parte di questa categoria.

Logica di funzionamento

SElinux non fa altro che associare un security context  a ciascun elemento che compone il sistema operativo. Il security context presenta il seguente formato:

user:role:domain:level

ad esempio:

system_u:object_r:nagios_spool_t:s0

e l’interazione è consentita (di default) solo tra gli elementi appartenenti al medesimo contesto.

selinux-penguin-new_medium

Inoltre, il file di log in cui vengono salvati gli eventi generati da SElinux è audit.log, presente all’interno della directory /var/log/audit. Analizzando questo file è possibile capire se un determinato processo (o utente) che cerca di accedere ad un determinato file (o directory) è stato autorizzato o bloccato. Un esempio di accesso bloccato è il seguente:

type=AVC msg=audit(1443184099.487:4197): avc:  denied  { open } for  pid=15608 comm="submit_check_re" name="nagios.cmd" dev=dm-0 ino=394145 scontext=system_u:system_r:snmpd_t:s0 tcontext=system_u:object_r:nagios_spool_t:s0 tclass=fifo_file type=SYSCALL msg=audit(1443184099.487:4197): arch=c000003e syscall=2 success=no exit=-13 a0=1b8f490 a1=401 a2=1b6 a3=76 items=0 ppid=15607 pid=15608 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="submit_check_re" exe="/bin/bash" subj=system_u:system_r:snmpd_t:s0 key=(null)

Analizzando il suddetta entry si possono notare alcuni elementi distintivi:

type=AVC

ovvero l’azione bloccata è stata effettuata a livello di kernel (AVC) e non di user space (USER-AVC);

msg=audit(1443184099.487:4197):

che rappresenta lo Unix timestamp associato all’evento;

avc:  denied  { open }

in cui viene indicata l’azione che è stata bloccata (open);

scontext=system_u:system_r:snmpd_t:s0

ovvero il source security context;

tcontext=system_u:object_r:nagios_spool_t:s0

in cui viene specificato il target security context;

tclass=fifo_file

ovvero la target class (che può essere file, directory, fifo_file, ecc – vedi qui per approfondire).

Source security context, target security context e target class sono gli elementi essenziali per la creazione delle regole SElinux (allow o deny). Tali regole andranno a popolare un file con estensione *.te (type enforcement).

Modalità di funzionamento

SElinux prevede 2 modalità di funzionamento, enforcing e permessive. Quest’ultima è molto utile quando si vuole fare un po’ di troubleshooting (ad esempio per capire se una determianta applicazione non sta funzionando correttamente proprio a causa di qualche regola di tipo MAC), poichè in tal caso non verrà bloccato nulla ma verranno registrate (all’interno di audit.log)  tutte quelle operazioni che stanno violando una o più policy.

E’ possibile passare da una modalità all’altra utilizzando il comando setenforce, dove:

[root@server ~]# setenforce 1

abilita la modalità enforcing, mentre:

[root@server ~]# setenforce 0

abilitata la modalità permessive.

Inoltre, per visualizzare la modalità di funzionamento attuale di SElinux è necessario digitare il comando:

[root@server ~]# getenforce

o, in alternativa (ottenendo un output più dettagliato):

[root@server ~]# sestatus

Occorre precisare che la modalità enforcing prevede alcune sotto-modalità di funzionamento (se così le si può definire), ovvero:

1) targeted (quella da me utilizzata), in cui solo determinati processi sono protetti da SElinux (tutto il resto viene marcato come unconfined);

2) strict, in cui tutte le operazioni che avvegono a livello di SO sono controllate da SElinux;

3) mls (Multi-level security), in cui (e lo dice il nome stesso) sono previsti diversi livelli di sicurezza (unclassified, confidential, secret e top secret – vedi qui per ulteriori dettagli);

4) mcs (Multi-category security), in cui l’utente può associare ai propri file una determinata categoria (in base alla quale il SO deciderà chi e come potrà averne accesso).

Per definire la modalità di funzionamento in fase di boot, occorre editare il file /etc/sysconfig/selinux, il cui contenuto dovrà essere simile al seguente:

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

Visualizzazione del security context

Per visualizzare il security context associato a file o directory basta utilizzare il classico comando ls, affiancato dalla flag Z. Ad esempio:

[root@server ~]# ls -ilahZ

il cui output sarà simile al seguente:

dr-xr-x---. root root system_u:object_r:admin_home_t:s0 .
dr-xr-xr-x. root root system_u:object_r:root_t:s0      ..
-rw-r--r--. root root system_u:object_r:admin_home_t:s0 acl_home

Per ciò che concerne i processi, si può, invece, utilizzare il comando:

[root@server ~]# ps auxZ

il cui output potrebbe contenere:

system_u:system_r:postfix_pickup_t:s0 postfix 31620 0.0  0.1 81416 3820 ?      S    11:20   0:00 pickup -l -t fifo -u

Visualizzazione e gestione delle policy

Prima di tutto occorre precisare che SElinux può gestire l’interazione tra elementi appartenenti a security context differenti attraverso due metodi:

1) utilizzo delle variabili booleane;

2) utilizzo dei moduli.

Per visualizzare i valori associati alle variabili booleane occorre lanciare il comando:

[root@server ~]# getsebool -a

mentre per modificare il valore di una variabile (da true a false e viceversa), è necessario utilizzare il comando:

[root@server ~]# setsebool <nomevariabile> <0|1>

Da notare che una modifica può essere fatta in modo permanente avvalendosi della flag -P, oppure editando il contenuto del file /etc/selinux/SELINUXTYPE/booleans.

Il comando che ci consente di visualizzare tutte le policy presenti sul sistema è il seguente:

[root@server ~]# sesearch --all

utile anche per filtrare ulteriormente le suddette policy, visualizzando, ad esempio, solo quelle di tipo allow:

[root@server ~]# sesearch --allow

E’ anche possibile listare i moduli attualmente in uso:

[root@server ~]#  semodule -l

Creazione di regole custom

Per effettuare tale operazione si possono seguire 2 strade: avvalersi di un’apposita utility che automatizza il tutto (audit2allow) oppure creare delle regole “a mano”. Personalmente, credo che la seconda opzione sia la più sicura, in quanto ci permette di avere un controllo maggiore su ciò che deve essere effettivamente consentito.

Per utilizzare audit2allow è necessario, dapprima, scaricare il pacchetto policycoreutils-python mediante yum:

[root@server ~]# yum install policycoreutils-python

A questo punto, è possibile avvalersi dell’utility in questione per listare il contenuto del file audit.log, ottenendo una descrizione dettagliata di quanto sta avvenendo (attraverso la flag -w):

[root@server ~]# audit2allow -a -w

Come accennavo in precedenza, tale applicativo può essere utilizzato per creare dei moduli custom da dare in pasto a SElinux. Ad esempio, se volessimo consentire l’interazione tra un oggetto appartenente al dominio httpd_t ed uno appartenente al dominio nagios_t, potremmo utilizzare il comando:

[root@server ~]# grep httpd_t | audit2allow -a -M <nomemodulo.pp>

Una volta creato il modulo lo si può installare lanciando il comando:

[root@server ~]# semodule -i <nomemodulo.pp>

Una nota a margine di quanto appena detto: se il file audit.log viene popolato costantemente da nuove entry, la creazione del modulo custom mediante la suddetta utility richiederà molto (per non dire troppo) tempo. Anche per questo motivo preferisco creare “a mano” le regole che andranno a formare i miei moduli personalizzati.

Per ottenere in maniera semi-automatica le regole da inserire all’interno dei suddetti moduli è sufficiente digitare il comando:

[root@servers]# audit2allow -i /var/log/audit/audit.log

il cui output sarà simile al seguente:

#============= nagios_log_t ==============

#!!!! This avc is allowed in the current policy
allow mrtg_t nagios_log_t:file { open };

Alla luce di ciò,  il contenuto di un modulo (da me creato) necessario per consentire l’accesso in lettura da parte di MRTG al file status.dat di Nagios (affinchè possano essere monitorate le prestazioni dell’NMS in questione), sarà il seguente:

module permitmrtgnagios 1.0;

require {
        type mrtg_t;
        type nagios_log_t;
        class file { open };
}

#============= nagios_log_t ==============

#!!!! This avc is allowed in the current policy
allow mrtg_t nagios_log_t:file { open };

Il suddetto contenuto si riferisce ad un file con estensione *.te. Tale file va compilato lanciando il comando:

[root@server ~]# checkmodule -M -m -o permitmrtgnagios.mod permitmrtgnagios.te

e successivamente:

[root@server ~]# semodule_package -o permitmrtgnagios.pp -m  permitmrtgnagios.mod

Una volta creato il modulo vero e proprio (con estensione *.pp), si può procedere con la sua installazione:

[root@server ~]# semodule -i permitmrtgnagios.pp

Altro consiglio: scegliete un prefisso (o suffisso) standard per i moduli da voi creati, in modo da identificarli facilmente tra quelli già presenti sul sistema (ed impiegati da SElinux). Inoltre, nel caso in cui venga installato un modulo già presente ed utilizzato, quest’ultimo verrà sovrascritto (motivo più che valido per scegliere dei nomi con un costrutto particolare e standard).

Infine, un avvertimento: alcune azioni di blocco effettuate da SElinux non vengono loggate all’interno del file di audit (donotaudit), principalmente per evitare che quest’ultimo raggiunga dimensioni eccessive. Per disabilitare temporaneamente tale opzione è necessario utilizzare il comando:

[root@server ~]# semodule -BD

mentre per riabilitarla nuovamente occorre digitare:

[root@server ~]# semodule -B

E’ tutto. Da adesso in poi SElinux non dovrebbe più essere un mistero.

Alla prossima.