Una delle ragioni del grande successo dei sistemi operativi Linux su dispositivi embedded, mobili e server è il suo elevato livello di sicurezza del kernel, dei servizi e delle applicazioni associati. Ma se all'architettura del kernel Linux, non si può trovare un quadratino che si occupi della sicurezza in sé. Dove si nasconde dunque il sottosistema di sicurezza di Linux e di cosa è composto?
Storia dei Linux Security Modules e SELinux
Security Enhanced Linux è un insieme di regole e meccanismi di accesso, basato sui modelli di accesso mandatory e role-based, per proteggere i sistemi Linux dalle potenziali minacce e risolvere le carenze del Discretionary Access Control (DAC) - il tradizionale sistema di sicurezza Unix. Il progetto ha avuto origine presso l'Agenzia Nazionale per la Sicurezza degli Stati Uniti, con lo sviluppo principalmente a cura di appaltatori della Secure Computing Corporation e del MITRE, insieme a vari laboratori di ricerca.

Linux Security Modules
Linus Torvalds ha fatto una serie di osservazioni sui nuovi sviluppi della NSA, affinché potessero essere inclusi nel ramo principale del kernel di Linux. Ha descritto un ambiente generale con un insieme di intercettatori per gestire le operazioni sugli oggetti e un insieme di campi protettivi nelle strutture dati del kernel per memorizzare i relativi attributi. Questo ambiente può quindi essere utilizzato dai moduli del kernel caricabili per implementare qualsiasi modello di sicurezza desiderato. LSM è entrato pienamente nel kernel di Linux v2.6 nel 2003.
Il framework LSM include campi protettivi nelle strutture dati e chiamate di funzione di intercettazione in punti critici del codice del kernel per gestirli e per eseguire il controllo degli accessi. Aggiunge anche funzioni per registrare i moduli di sicurezza. L'interfaccia /sys/kernel/security/lsm contiene un elenco dei moduli attivi nel sistema. Gli hook LSM sono memorizzati in elenchi che vengono chiamati nell'ordine specificato in CONFIG_LSM. Una documentazione dettagliata sugli hook è inclusa nel file di intestazione include/linux/lsm_hooks.h.
Il sottosistema LSM ha consentito di completare l'integrazione completa di SELinux della stessa versione del kernel Linux stabile v2.6. Fin da subito, SELinux è diventato lo standard de facto per un ambiente Linux protetto ed è stato integrato nei più popolari distribuzioni: RedHat Enterprise Linux, Fedora, Debian, Ubuntu.
Glossario SELinux
- Identità — L'utente SELinux non è lo stesso dell'utente Unix/Linux a cui si è abituati; possono coesistere sullo stesso sistema, ma sono completamente diversi per natura. Ogni account standard Linux può corrispondere a uno o più in SELinux. L'identità SELinux è parte integrante del contesto di sicurezza generale, che definisce quali domini possono essere accessibili e quali no.
- Domini — In SELinux, a domain is the execution context of a subject, i.e., a process. The domain directly determines the access that a process has. A domain is essentially a list of what processes can do or what actions a process can perform on different types. Some examples of domains are: sysadm_t for system administration and user_t, which is a regular non-privileged user domain. The init initialization system runs in the init_t domain, and the named process runs in the named_t domain.
- Ruoli — The entity that acts as an intermediary between SELinux domains and users. Roles define which domains a user can belong to and what types of objects they can access. This kind of access control mechanism prevents the threat of privilege escalation attacks. Roles are embedded in the Role Based Access Control (RBAC) security model used in SELinux.
- Tipi — L'attributo di enforcement del tipo di lista assegnato a un oggetto e che definisce chi può accedervi. È simile alla definizione di dominio, tranne per il fatto che il dominio si applica ai processi mentre il tipo si applica a oggetti come directory, file, socket, ecc.
- Soggetti e oggetti — I processi sono soggetti e vengono eseguiti in un contesto specifico, o dominio di sicurezza. Le risorse del sistema operativo: file, directory, socket, ecc. sono oggetti associati a un certo tipo, in altre parole, a un livello di segretezza.
- Politiche SELinux — Per proteggere il sistema, SELinux utilizza diverse politiche. La politica SELinux definisce l'accesso degli utenti ai ruoli, dei ruoli ai domini e dei domini ai tipi. All'inizio, l'utente viene autorizzato a ottenere un ruolo, quindi il ruolo viene autorizzato ad accedere ai domini. Infine, un dominio può avere accesso solo ad alcuni tipi di oggetti.
LSM e architettura SELinux
Nonostante il nome, LSM non è veramente un modulo caricabile di Linux. Tuttavia, come SELinux, è direttamente integrato nel kernel. Qualsiasi modifica al codice sorgente di LSM richiede una nuova compilazione del kernel. L'opzione corrispondente deve essere abilitata nelle impostazioni del kernel, altrimenti il codice LSM non verrà attivato all'avvio. Ma anche in questo caso può essere attivato tramite un'opzione del bootloader del sistema operativo.

Stack di controlli LSM
LSM è dotato di hook nelle funzioni principali del kernel, che possono essere rilevanti per i controlli. Una delle caratteristiche principali di LSM è che sono strutturati secondo il principio dello stack. In questo modo, i controlli standard vengono comunque eseguiti e ogni livello di LSM aggiunge solo ulteriori elementi di gestione e controllo. Ciò significa che un divieto non può essere annullato. Questo è illustrato nella figura: se il risultato dei controlli DAC di routine è un rifiuto, l'operazione non raggiungerà nemmeno gli hook di LSM.
SELinux ha adottato l'architettura di sicurezza di Flask, il sistema operativo Fluke, in particolare il principio del minimo privilegio. Il concetto alla base di questo principio, come suggerisce il nome, è quello di fornire all'utente o al processo solo i diritti necessari per svolgere le azioni previste. Questo principio è attuato attraverso la tipizzazione forzata degli accessi, quindi il controllo degli accessi in SELinux si basa sul modello dominio => tipo.
Grazie alla tipizzazione forzata degli accessi, SELinux offre capacità di segregazione degli accessi molto superiori rispetto al tradizionale modello DAC utilizzato nei sistemi operativi Unix/Linux. Ad esempio, è possibile limitare il numero della porta di rete che sarà utilizzata dal server ftp, consentire la scrittura e la modifica dei file in una determinata cartella, ma non la loro eliminazione.
I componenti principali di SELinux sono:
- Policy Enforcement Server — Il meccanismo principale per l'organizzazione del controllo degli accessi.
- DB delle politiche di sicurezza del sistema.
- Interazione con l'intercettatore di eventi LSM.
- Selinuxfs — Pseudo-FS, simile a /proc e montato in /sys/fs/selinux. Viene riempito dinamicamente dal kernel Linux durante l'esecuzione e contiene file che forniscono informazioni sullo stato di SELinux.
- Access Vector Cache — Meccanismo ausiliario per migliorare le prestazioni.

Schema di funzionamento di SELinux
Tutto funziona in questo modo.
- Un certo soggetto, in termini di SELinux, esegue un'azione autorizzata su un oggetto dopo aver superato il controllo DAC, come mostrato nell'immagine sopra. Questa richiesta di esecuzione viene inviata all'interceptor di eventi LSM.
- Da lì, la richiesta viene inviata insieme al contesto di sicurezza del soggetto e dell'oggetto al modulo SELinux Abstraction and Hook Logic, responsabile dell'interazione con LSM.
- L'istanza di decisione sull'accesso del soggetto all'oggetto è Policy Enforcement Server e riceve dati da SELinux AnHL.
- Per prendere una decisione sull'accesso o sul divieto, il Policy Enforcement Server consulta il sottosistema di caching delle regole più utilizzate, Access Vector Cache (AVC).
- Se la decisione per la regola corrispondente non è trovata nella cache, la richiesta viene inoltrata ulteriormente al database delle politiche di sicurezza.
- Il risultato della ricerca dal database e dall'AVC viene restituito al Policy Enforcement Server.
- Se la politica trovata corrisponde all'azione richiesta, l'operazione è consentita. Altrimenti, l'operazione è vietata.
Gestione delle impostazioni SELinux
SELinux opera in una delle seguenti tre modalità:
- Enforcing — Applicazione rigorosa delle politiche di sicurezza.
- Permissive — È consentita una violazione dei vincoli, viene registrato un avviso nel log.
- Disabled — Le politiche di sicurezza non sono attive.
È possibile vedere in quale modalità si trova SELinux con il seguente comando.
[admin@server ~]$ getenforce
PermissiveCambio della modalità fino al riavvio, ad esempio impostando su enforcing, oppure 1. Al parametro permissive corrisponde il codice numerico 0.
[admin@server ~]$ setenfoce enforcing
[admin@server ~]$ setenfoce 1 #stessa cosa
È possibile modificare la modalità anche modificando il file:
[admin@server ~]$ cat /etc/selinux/config # 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 three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targete
La differenza con setenfoce è che all'avvio del sistema operativo la modalità SELinux sarà impostata in conformità con il valore del parametro SELINUX nel file di configurazione. Inoltre, le modifiche tra enforcing disabled entrano in vigore solo modificando il file /etc/selinux/config e dopo il riavvio.
Visualizza un breve rapporto di stato:
[admin@server ~]$ sestatus Stato di SELinux: abilitato
Mount di SELinuxfs: /sys/fs/selinux
Directory principale di SELinux: /etc/selinux
Nome della policy caricata: targeted
Modalità attuale: permissiva
Modalità dal file di configurazione: enforcing
Stato della policy MLS: abilitato
Stato della policy deny_unknown: consentito
Versione massima della policy del kernel: 31
Alcuni strumenti di sistema utilizzano il parametro -Z per visualizzare gli attributi SELinux.
[admin@server ~]$ ls -lZ /var/log/httpd/
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20200920
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20200927
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20201004
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20201011
[admin@server ~]$ ps -u apache -Z
LABEL PID TTY TIME CMD
system_u:system_r:httpd_t:s0 2914 ? 00:00:04 httpd
system_u:system_r:httpd_t:s0 2915 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 2916 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 2917 ? 00:00:00 httpd
...
system_u:system_r:httpd_t:s0 2918 ? 00:00:00 httpdRispetto all'output normale di ls -l, qui ci sono alcuni campi aggiuntivi nel seguente formato:
:::
L'ultimo campo indica un tipo di classificazione della segretezza ed è composto da una combinazione di due elementi:
- s0 — significatività, può essere registrato anche con un intervallo da lowlevel a highlevel
- c0, c1… c1023 — categoria.
Modifica della configurazione degli accessi
Utilizza semodule per caricare i moduli SELinux, aggiungere e rimuovere.
[admin@server ~]$ semodule -l |wc -l #elenco di tutti i moduli
408
[admin@server ~]$ semodule -e abrt #attivare il modulo
[admin@server ~]$ semodule -d accountsd #disattivare il modulo
[admin@server ~]$ semodule -r avahi #rimuovere il moduloPrimo comando semanage login collega un utente SELinux a un utente del sistema operativo; il secondo visualizza l'elenco. Infine, l'ultimo comando con l'opzione -r rimuove il collegamento tra gli utenti SELinux e gli account OS. La sintassi dei valori MLS/MCS Range è spiegata nella sezione precedente.
[admin@server ~]$ semanage login -a -s user_u karol
[admin@server ~]$ semanage login -l Nome di accesso SELinux Utente Intervallo MLS/MCS Servizio
__default__ unconfined_u s0-s0:c0.c1023 *
root unconfined_u s0-s0:c0.c1023 *
system_u system_u s0-s0:c0.c1023 *
[admin@server ~]$ semanage login -d karol
Team semanage user viene utilizzato per gestire le associazioni tra utenti e ruoli SELinux.
[admin@server ~]$ semanage user -l
Etichettatura MLS/ MLS/
Utente SELinux Prefisso Livello MCS Intervallo MCS Ruoli SELinux
guest_u utente s0 s0 guest_r
staff_u personale s0 s0-s0:c0.c1023 staff_r sysadm_r
...
user_u utente s0 s0 user_r
xguest_u utente s0 s0 xguest_r
[admin@server ~]$ semanage user -a -R 'staff_r user_r'
[admin@server ~]$ semanage user -d test_uParametri del comando:
- -a aggiungere una registrazione utente di corrispondenza ruoli;
- -l elenco delle corrispondenze tra utenti e ruoli;
- -d rimuovere una registrazione utente di corrispondenza ruoli;
- -R elenco dei ruoli associati all'utente;
File, porte e valori booleani
Ogni modulo SELinux fornisce un insieme di regole per la marcatura dei file, ma è possibile aggiungere anche regole personalizzate se necessario. Ad esempio, desideriamo dare al server web i permessi per accedere alla cartella /srv/www.
[admin@server ~]$ semanage fcontext -a -t httpd_sys_content_t "/srv/www(\/.*)?
[admin@server ~]$ restorecon -R /srv/www/Il primo comando registra nuove regole di marcatura, mentre il secondo ripristina, o meglio imposta, i tipi di file secondo le regole attuali.
Allo stesso modo, le porte TCP/UDP sono contrassegnate in modo tale che solo i servizi corrispondenti possano ascoltarle. Ad esempio, affinché il server web possa ascoltare la porta 8080, è necessario eseguire il comando.
[admin@server ~]$ semanage port -m -t http_port_t -p tcp 8080Un numero significativo di moduli SELinux ha parametri che possono assumere valori booleani. È possibile visualizzare l'intero elenco di tali parametri usando getsebool -a. I valori booleani possono essere modificati utilizzando setsebool.
[admin@server ~]$ getsebool httpd_enable_cgi
httpd_enable_cgi --> on
[admin@server ~]$ setsebool -P httpd_enable_cgi off
[admin@server ~]$ getsebool httpd_enable_cgi
httpd_enable_homedirs --> off
Pratica, accedere all'interfaccia di Pgadmin-web
Consideriamo un esempio pratico: abbiamo installato pgadmin4-web su RHEL 7.6 per l'amministrazione del database PostgreSQL. Abbiamo affrontato un piccolo con la configurazione di pg_hba.conf, postgresql.conf e config_local.py, impostato i permessi sulle cartelle e installato i moduli Python mancanti tramite pip. Tutto è pronto, avviamo e otteniamo 500 Internal Server error.

Iniziamo con i sospetti abituali, controlliamo /var/log/httpd/error_log. Ci sono alcuni messaggi interessanti.
[timestamp] [core:notice] [pid 23689] Politica SELinux attivata; httpd in esecuzione come contesto system_u:system_r:httpd_t:s0
...
[timestamp] [wsgi:error] [pid 23690] [Errno 13] Permesso negato: '/var/lib/pgadmin'
[timestamp] [wsgi:error] [pid 23690]
[timestamp] [wsgi:error] [pid 23690] SUGGERIMENTO: Potresti dover impostare manualmente i permessi su
[timestamp] [wsgi:error] [pid 23690] /var/lib/pgadmin per consentire ad apache di scriverci.
A questo punto, la maggior parte degli amministratori Linux avrà una forte tentazione di eseguire setenforce 0, e considerare la questione risolta. Confesso che la prima volta l'ho fatto. È sicuramente una soluzione, ma non la migliore.
Nonostante la complessità delle strutture, SELinux può essere amichevole per l'utente. È sufficiente installare il pacchetto setroubleshoot e controllare il registro di sistema.
[admin@server ~]$ yum install setroubleshoot
[admin@server ~]$ journalctl -b -0
[admin@server ~]$ service restart auditd
Si noti che il servizio auditd deve essere riavviato in questo modo e non tramite systemctl, nonostante la presenza di systemd nel sistema operativo. Nel registro di sistema sarà indicato non solo il fatto del blocco, ma anche la causa e il modo per superare il divieto.

Eseguiamo questi comandi:
[admin@server ~]$ setsebool -P httpd_can_network_connect 1
[admin@server ~]$ setsebool -P httpd_can_network_connect_db 1
Verifichiamo l'accesso alla pagina web pgadmin4-web, tutto funziona.
Fonte: habr.com
