Perché conta
Tutto ciò che abbiamo visto finora è controllo discrezionale: il proprietario di una risorsa
decide, e root scavalca ogni controllo. Il limite è evidente — se un servizio che gira come root (o un
processo che ottiene root) viene compromesso, il DAC non lo ferma. Il controllo d’accesso obbligatorio
(MAC) aggiunge una politica di sistema che vale sopra il DAC e che nemmeno root può aggirare:
anche se un processo è root, può fare solo ciò che la politica SELinux consente al suo tipo. È un
confinamento potentissimo — e la risposta sbagliata, setenforce 0, è anche la più diffusa.
L’idea: etichette e tipi
In SELinux ogni processo e ogni risorsa hanno un’etichetta (context), e la politica definisce quali interazioni tra etichette sono permesse. Il campo che conta di più è il type (type enforcement).
|
|
La politica dice, in sostanza: “un processo httpd_t può leggere file httpd_sys_content_t”. Se il
web server (confinato in httpd_t) viene compromesso, non può leggere /etc/shadow
(shadow_t) o scrivere ovunque: la politica glielo vieta, root o no.
I tre modi
|
|
|
|
Il riflesso sbagliato è passare a Disabled al primo problema. Quello giusto è passare a Permissive
temporaneamente per vedere cosa verrebbe bloccato, capirlo, correggere la politica, e tornare a
Enforcing.
Il troubleshooting che non spaventa
Quando “qualcosa non funziona e sospetto SELinux”, il flusso è preciso:
|
|
Due aggiustamenti coprono la maggioranza dei casi:
|
|
Quando serve una regola nuova: audit2allow
Se un’applicazione legittima ha bisogno di un accesso che nessun booleano copre, si genera un modulo di policy dai denial — senza disabilitare nulla.
|
|
Attenzione: audit2allow va usato con criterio — concedi solo ciò che è davvero legittimo, non tutto
ciò che l’app prova a fare (potrebbe provare anche cose che è giusto bloccare).
Domanda: SELinux ha la fama di rompere le applicazioni e di essere complicatissimo. Visto che ho già DAC stretto, capabilities e sandboxing systemd, non è più pragmatico disabilitarlo e vivere sereni?
È il ragionamento più comune e anche quello che butta via la protezione più forte proprio quando
servirebbe di più. Partiamo dalla fama: SELinux "rompe le app" quasi sempre perché i file sono nel posto
sbagliato (contesto errato) o manca un booleano — due cose che si diagnosticano in minuti con
ausearch e sealert e si risolvono con un comando, senza disabilitare niente. La
complessità vera (scrivere policy da zero) non ti riguarda nel 95% dei casi: usi la policy mirata della
distribuzione e la ritocchi con booleani e contesti. Ora il punto sostanziale: DAC stretto, capabilities
e sandboxing systemd sono ottimi, ma hanno un limite comune — operano dentro il modello discrezionale e,
soprattutto, dipendono dal fatto che tu li abbia configurati correttamente per ogni servizio.
SELinux aggiunge qualcosa che gli altri non danno: un confinamento obbligatorio, definito a
livello di sistema, che vale anche contro un processo che è diventato root e che resta in piedi anche
dove ti sei dimenticato di sandboxare. Il caso che conta è questo: un servizio ha una vulnerabilità che
permette l'esecuzione di codice e magari un'escalation a root. Il DAC a quel punto non ferma più nulla
(root scavalca tutto), e se quel servizio non l'avevi sandboxato con systemd, l'attaccante è libero. Con
SELinux in enforcing, invece, il processo resta confinato nel suo type: il web server compromesso, anche
da root, non può leggere /etc/shadow né scrivere fuori dalle sue directory, perché la policy non lo
prevede per httpd_t. È esattamente la difesa che interviene quando tutte le altre hanno
ceduto. Disabilitarlo per "vivere sereni" significa rinunciare all'unico strato che un attaccante con
root non può semplicemente aggirare — in cambio di non dover imparare due comandi. Il pragmatismo vero è
tenerlo in enforcing e imparare il flusso di troubleshooting: è molto meno lavoro di quanto la sua fama
suggerisca, e copre proprio lo scenario peggiore.
Conclusione
SELinux impone una politica di sistema che confina ogni processo al suo type e che nemmeno root
scavalca; il segreto è non disabilitarlo ma usare Permissive per diagnosticare, booleani e contesti
per correggere, audit2allow per i casi residui. Esiste un secondo approccio al MAC, più semplice da
leggere e basato sui percorsi invece che sulle etichette: AppArmor,
prossimo capitolo.