Archivi tag: mac

SElinux e CentOS 6: ricevere un’email di notifica in caso di policy violate

In questo post ho discusso di SElinux, illustrandone la logica di funzionamento ed i comandi da utilizzare per la sua configurazione e gestione.

Adesso vedremo come rendere tale sistema di sicurezza il più proattivo possibile, ovvero facendo in modo che sia in grado di inviarci una mail di notifica nel caso in cui una o più policy MAC vengano violate.

selinux-penguin-new_medium

Installazione e configurazione di SEtroubleshoot

Il software in grado di implementare la funzionalità in questione prende il nome di setroubleshoot. Per installarlo possiamo utilizzare il packet manager di casa CentOS/RedHat, ovvero yum:

[root@linuxbox ~]# yum install setroubleshoot

Successivamente, passiamo alla configurazione dell’applicativo in questione, editando il file /etc/setroubleshoot/setroubleshoot.conf. Le entry da modificare sono le seguenti:

recipients_filepath = /var/lib/setroubleshoot/email_alert_recipients
smtp_port = 25
smtp_host = localhost
from_address = mittente@vostrodominio.com
subject = SELinux AVC Alert for nomeserver

Va da sè che l’opzione smtp_host deve essere popolata in base al server SMTP che si vuole utilizzare. Ad esempio, nel mio caso, esiste un’unica macchina che funge da STMP “in uscita”, configurata in modo tale da interfacciarsi con un relay host “esterno” ed “affidabile” (in tal modo evito che le mie email vengano respinte costantemente poichè provenienti da un indirizzo IP pubblico di tipo dinamico e non dotato di record DNS PTR).

Inseriamo adesso, all’interno del file /var/lib/setroubleshoot/email_alert_recipients, il destinatario delle email di notifica:

[root@linuxbox ~]# echo "indirizzo.email@vostrodominio.com" >> /var/lib/setroubleshoot/email_alert_recipients

e riavviamo il servizio che si occupa di gestire tale funzionalità (in modo da attivare le suddette modifiche):

[root@linuxbox ~]# service messagebus restart

Test

Per testare il corretto funzionamento del sistema di notifica appena configurato è necessario fare in modo che uno dei moduli SELinux custom che abbiamo realizzato venga momentaneamente disattivato (in tal modo “forzeremo” il popolamento del file audit.log generando così il trigger che causerà l’inoltro della notifica email sulla nostra casella di posta):

[root@linuxbox ~]# semodule -d <nomemodulo>

Se tutto funziona come dovrebbe, riceveremo una notifica dal contenuto simile al seguente:

[SELinux AVC Alert for linuxbox] SELinux is preventing /usr/sbin/sedispatch from sendto access on the unix_dgram_socket 

SELinux is preventing /usr/sbin/sedispatch from sendto access on the unix_dgram_socket .

*****  Plugin catchall (100. confidence) suggests   **************************

... OMISSIS ...

Alla prossima.

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.

Gli IP Plan non aggiornati

In un ambiente enterprise mantenere un IP plan aggiornato è un’operazione alquanto ardua (soprattutto se coloro che devono gestire l’infrastruttura IT sono dislocati su sedi diverse).

 

networking.jpg

Quello che mi è capitato di recente mi ha fatto capire quanto un IP plan attendibile possa essere importante. Nello specifico, dopo aver installato e configurato un nuovo server, ho richiesto un indirizzo IP privato da poter assegnare alla suddetta macchina, senza creare eventuali conflitti con gli altri apparati già in produzione.

La prima cosa che ho fatto è stata quella di consultare l’IP Plan, scegliendo un indirizzo libero. Successivamente ho comunicato l’indirizzo in questione al sistemista network, il quale mi ha confermato la disponibilità dello stesso.

Per scrupolo ho effettuato un ping, il quale non ha fornito alcuna risposta, ergo tutti gli indizi mi lasciavano pensare che l’indirizzo scelto fosse effettivamente disponibile.

Fast forward di 30 minuti: una volta patchata la porta del server ed attestata sulla porta dello switch appartenente alla VLAN di riferimento, ho iniziato a ricevere degli ICMP echo reply a singhiozzo.

Tentando di connettermi via RDP alla suddetta macchina, con mio enorme stupore, ho notato che l’hostname del server su cui ero atterrato era differente da quello da me configurato, ergo vi era già una macchina che utilizzava l’indirizzo IP che credevo libero.

Nuovo giro di telefonate, altri check al volo e finalmente sono riuscito ad individuare un indirizzo IP effettivamente disponibile.

Contromisure

Per non incappare in una simile problematica è necessario aggiungere altri check al semplice ping ed alla consultazione dell’IP plan. Infatti, alcuni SO, quali Windows Server 2008 R2, hanno il firewall embedded configurato in modo da droppare le richieste ICMP. Quindi, per sincerarsi dell’effettiva disponibilità di un indirizzo, occorre dapprima consultare l’arp table dello switch su cui sono attestati i server della farm (generalmente trattasi di un core switch). Tale check va fatto a server disconnesso e partendo dal presupposto che non vi siano degli switch intermedi.

Per i Cisco, il comando da lanciare è il seguente:

Switch# sh arp | i <indirizzo IP>

Se l’arp table non restituisce alcun risultato significa che l’indirizzo IP scelto è libero. Ovviamente, se il server è stato disconnesso immediatamente prima di effettuare il suddetto controllo, è necessario aspettare che scada il cosiddetto aging time delle entry relative alla arp table (che varia in base alla tipologia ed al vendor dello switch, sempre che i valori impostati siano quelli di default).

Successivamente, a server connesso, si potrebbe individuare il MAC address della sua scheda di rete e controllare se l’associazione IP-MAC presente nella tabella ARP contiene il suddetto indirizzo fisico.

Infine, controllando le entry della CAM, ci si può sincerare che il MAC individuato sia stato letto sulla porta dello switch sul quale il server è effettivamente attestato.

Per i Cisco il comando da utilizzare è questo:

Switch# sh mac-address-table | i <indirizzo MAC>

Da notare che il MAC dovrà essere digitato nella forma aaaa.bbbb.cccc

In alternativa a tale procedura (che richiede comunque una certa familiarità con il networking), si potrebbe utilizzare un port scanner, ad esempio nmap.

Esiste anche una versione per Windows, scaricabile da qui, ed il comando da lanciare è il seguente:

nmap -P0 <indirizzo IP>

In particolare, con la flag -P0 sto imponendo al software di non lanciare dei ping preliminari per testare l’effettiva raggiungibilità dell’IP (evitando quindi i falsi negativi), procedendo immediatamente con la scansione delle porte.

State tranquilli, il port scan non è reato se non è seguito da dei tentativi di accesso non autorizzati (verificate comunque le policy aziendali prima di lanciarlo).

E’ tutto. Alla prossima.

Apple Power User

Dedicato a tutti gli Apple Power User 😀 (Per gentile concessione di Matteo Calabrò)

appale, power user, java, mac

public interface Troll extends Ignorant {
public Object think();
}

public class Macaco implements Troll {}

public class AppleUser extends Macaco {

private static final boolean ableToThink = false;
private static final boolean ableToCompareOrJudge = false;

private String name;
private String surname;
private Object device = Apple.iSomething();

public final Object think() {
throw new UnsupportedOperationException();
}
}

Nessun problema, la maggior parte di loro non ci capirà un fico secco.

Alla prossima.