Archivi tag: centos 6

Configurazione del demone snmpd su CentOS 6

Utilizzare il protocollo SNMP per il monitoraggio dei dispositivi di rete è sempre una buona scelta, tenendo bene a mente, però, che le versioni 1 e 2 non prevedono cifratura della community string e quindi sono vulnerabili ad eventiali attacchi MITM. Inoltre, in determinate circostanze, tale protocollo può essere impiegato anche per il monitoraggio delle macchine *nix, soprattutto per ciò che concerne lo stato delle interfacce di rete ed il loro throughput.

snmpInstallazione e configurazione di snmpd

Vediamo adesso come configurare il demone snmpd su una macchina CentOS 6.

Per prima cosa occorre installare i seguenti pacchetti tramite yum:

[root@server ~]# yum install net-snmp net-snmp-utils

A questo punto passiamo alla configurazione del demone vera e propria, editando il file /etc/snmp/snmp.conf. 

Definiamo, dapprima, le utenze ed i gruppi, mediante le seguenti direttive:

com2sec local      localhost        secret
com2sec mynetwork  192.168.1.0/24 secret

group local      v2c        local
group mynetwork  v2c        mynetwork

In particolare, mediante la keyword com2sec stiamo definendo l’utente local, il cui IP/hostname sorgente dovrà essere localhost e la cui community string dovrà essere secret. Discorso analogo vale per l’utente mynetwork.

Invece, per ciò che concerne la definizione dei gruppi, la keyword da utilizzare è group, seguita dal nome del gruppo, dalla versione del protocollo SNMP (v2c) e dal nome degli utenti che ne fanno parte (local nel primo caso e mynetwork nel secondo).

Successivamente è necessario abilitare l’intera alberatura degli OID, mediante la seguente direttiva:

view all    included  .1                               80

Infine, passiamo alla definizione delle ACL per i gruppi appena creati:

#               context sec.model sec.level prefix   read  write notif
access  local     ""      any       noauth   exact   all   none none
access  mynetwork ""      any       noauth   exact   all   none none

dove la prima riga indica il significato di ciascun campo utilizzato dopo la keyword access ed il gruppo a cui l’ACL si riferisce. Dalla suddetta configurazione è facile notare come entrambi i gruppi (local e mynetwork) abbiano solo la possibilità di effettuare GET SNMP (read) ma non SET (write).

Per completezza, è possibile editare dei campi facoltativi quali syslocation e syscontact:

syslocation Italy server.vostrodominio.com
syscontact Nome Cognome <vostro.indirizzo@email.it>

Riavviamo snmpd per rendere effettive le suddette modifiche:

[root@server ~]# service snmpd restart

ed effettuiamo una query di prova, avvalendoci del tool snmpwalk:

[root@server ~]# snmpwalk -v 2c -c secret localhost

Se otterremo in output l’intera alberatura SNMP supportata dalla macchina significa che il demone sta funzionando come dovrebbe.

 Configurazione di Nagios

Per fare in modo che il nostro NMS sia in grado di monitorare lo stato ed il throughput delle interfacce di rete, occorre definire i seguenti comandi all’interno del file /etc/nagios/objects/commands.cfg:

# 'check_snmp_if_status' command definition
define command{
        command_name    check_snmp_if_status
        command_line    $USER1$/check_snmp -H $HOSTADDRESS$ -C $ARG1$ -P $ARG2$ -o $ARG3$ -r $ARG4$
        }

# 'check_local_mrtgtraf' command definition
define command{
        command_name    check_local_mrtgtraf
        command_line    $USER1$/check_mrtgtraf -F "$ARG1$" -a "$ARG2$" -w "$ARG3$" -c "$ARG4$" -a "$ARG5$"
        }

ed i seguenti servizi all’interno del file di configurazione associato alla macchina da monitorare:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_descripion             WAN Interface eth0 Operational Status
        check_command                   check_snmp_if_status!secret!IF-MIB::ifOperStatus.2!1
        }

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_descripion             LAN Interface eth1 Operational Status
        check_command                   check_snmp_if_status!secret!2c!IF-MIB::ifOperStatus.3!1
        }

define service{
        use                             local-service   ; Name of service template to use
        host_name                       localhost
        service_descripion             WAN Interface eth0 Bandwidth Usage
        check_command                   check_local_mrtgtraf!/var/www/mrtg/localhost_2.log!AVG!100000000,200000000!110000000,120000000!10
        }

define service{
        use                             local-service   ; Name of service template to use
        host_name                       localhost
        service_descripion             LAN Interface eth1 Bandwidth Usage
        check_command                   check_local_mrtgtraf!/var/www/mrtg/localhost_3.log!AVG!100000000,200000000!110000000,120000000!10
        }

Nella fattispecie, il monitoraggio del throughput viene realizzato mediante il plugin check_mrtgtraf, il cui scopo è quello di analizzare i file di log generati da MRTG (vedi questo post per ulteriori dettagli).

Ricarichiamo la configurazione di Nagios per rendere effettive le suddette modifiche:

[root@server ~]# service nagios reload

ed abbiamo finito.

Alla prossima.

CentOS 6: configurare delle regole di auditing mediante auditd

In questo post ho accennato all’importanza che le operazioni di auditing ricoprono durante la messa in sicurezza dei nostri server.

Nella fattispecie, per la distro CentOS 6, l’applicativo che si occupa di “monitorare” (inteso come controllo degli accessi ed accounting) il sistema operativo, prende il nome di auditd.

Vedremo adesso come fare a configurare delle regole di auditing secondo le nostre esigenze, come ricercare determinati eventi negli appositi file di log e come creare dei report giornalieri (da inviare via email al nostro indirizzo di posta) contenenti l’insieme degli eventi di auditing individuati.

audit

Creazione delle regole

Per effettuare tale operazione è necessario utilizzare il tool auditctl. Esso è in grado di creare delle regole il cui scopo è quello di monitorare le operazioni (lettura, scrittura, esecuzione e modifica degli attributi) su un dato file o su di una specifica directory. Non solo: sarà possibile anche configurare dei meccanismi di monitoraggio delle chiamate di sistema (in gergo SYSCALL) che vengono eseguite durante il normale funzionamento della nostra macchina.

Ecco alcuni esempi di regole per il monitoraggio delle SYSCALL:

[root@linuxbox ~]# auditctl -a always,exit -F arch=b64 -S settimeofday -k time_changes
[root@linuxbox ~]# auditctl -a always,exit -F arch=b64 -S clock_settime -k time_changes
[root@linuxbox ~]# auditctl -a always,exit -F arch=b64 -S sethostname -S setdomainname -k system_locale_changes

In particolare, vengono monitorate le chiamate di sistema settimeofday, clock_settime, sethostname e setdomainname (specificate mediante la flag -S), le quali indicano palesemente delle modifiche macroscopiche relative alla configurazione del sistema operativo. Occorre precisare, inoltre, che è stato necessario indicare (mediante la flag -F) l’architettura della CPU (recuperabile mediante il comando uname -m), poichè i codici numerici che identificano ciascuna SYSCALL variano a seconda che si tratti di una x86 (32 bit) oppure di una x86_64 (64 bit). Qui trovate la lista delle chiamate di sistema per x86 e qui trovate quella per x86_64.

Per il monitoraggio di file e directory l’opzione da utilizzare è -w, seguita dal nome del file (o della directory) di interesse. Inoltre, mediante la flag -p, potranno essere specificate le operazioni di cui tenere traccia (a per modifica degli attributi, x per esecuzione, w per scrittura ed r per lettura). Infine, mediante la flag -k sarà possibile associare un’etichetta a ciascuna regola di auditing precedentemente definita. Eccco alcuni esempi:

[root@linuxbox ~]# auditctl -w /etc/shadow -p wa -k shadow-file
[root@linuxbox ~]# auditctl -w /etc/passwd -p wa -k passwd_changes
[root@linuxbox ~]# auditctl -w /etc/group -p wa -k group_changes
[root@linuxbox ~]# auditctl -w /etc/sudoers -p wa -k sudoers_changes
[root@linuxbox ~]# auditctl -w /etc/selinux/ -p wa -k selinux_changes
[root@linuxbox ~]# auditctl -w /sbin/insmod -p x -k module_insertion
[root@linuxbox ~]# auditctl -w /tmp -p x -k webserver_watch_tmp
[root@linuxbox ~]# auditctl -w /etc/ssh/sshd_config -p wa -k sshd_config
[root@linuxbox ~]# auditctl -w /etc/httpd/conf/httpd.conf -p wa -k httpd_config
[root@linuxbox ~]# auditctl -w /etc/ntp.conf -p wa -k ntp_config

Possiamo, inoltre, elencare le regole finora definite utilizzando il comando:

[root@linuxbox ~]# auditctl -l

il cui output sarà simile al seguente:

-a always,exit -F arch=x86_64 -S settimeofday -F key=time_changes
-a always,exit -F arch=x86_64 -S clock_settime -F key=time_changes
-a always,exit -F arch=x86_64 -S sethostname,setdomainname -F key=system_locale_changes
-w /etc/shadow -p wa -k shadow-file
-w /etc/passwd -p wa -k passwd_changes
-w /etc/group -p wa -k group_changes
-w /etc/sudoers -p wa -k sudoers_changes
-w /etc/selinux/ -p wa -k selinux_changes
-w /sbin/insmod -p x -k module_insertion
-w /tmp/ -p x -k webserver_watch_tmp
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/httpd/conf/httpd.conf -p wa -k httpd_config
-w /etc/ntp.conf -p wa -k ntp_config
-w /etc/sysconfig/iptables -p wa -k iptables_config

Ricerca degli eventi

Il file di log in cui vengono salvati gli eventi di auditing è /var/log/audit/audit.log. Attraverso l’applicativo ausearch, che punta al suddetto file, è possibile effettuare delle ricerche mirate specificando il file di interesse, ad esempio:

[root@linuxbox ~]# ausearch -f /etc/passwd

oppure l’etichetta precedentemente assegnata all’evento:

[root@linuxbox ~]# ausearch -k webserver_watch_tmp

Generazione dei report

E’ possibile generare dei report contenenti gli eventi di auditing di interesse. Per fare ciò è sufficiente utilizzare l’applicativo aureport, comprensivo di flag -k, -ts (time start) e -te (time end). Ad esempio:

aureport -k -ts yesterday 00:00:00 -te yesterday 23:59:59

Per schedulare il suddetto report ad intervalli di tempo regolari (ad esempio ogni giorno) e fare in modo di riceverlo sulla propria casella di posta elettronica, è necessario creare un apposito file di cronjob all’interno della directory /etc/cron.d:

[root@linuxbox cron.d]# nano ausearchreport

il cui contenuto dovrà essere:

MAILTO=vostro.indirizzo@email.it

00    00   * * *     root          /sbin/aureport -k -ts yesterday 00:00:00 -te yesterday 23:59:59

Da notare che tutte le regole precedentemente create mediante auditctl hanno durata temporanea (ovvero vengono eliminate dopo un reboot). Per renderle quindi permanenti, occorre inserirle all’interno del file /etc/audit/audit.rules, il cui contenuto dovrà essere simile al seguente:

# First rule - delete all
-D

# Increase the buffers to survive stress events.
# Make this bigger for busy systems
-b 320

# Feel free to add below this line. See auditctl man page

-a always,exit -F arch=b64 -S settimeofday -k time_changes
-a always,exit -F arch=b64 -S clock_settime -k time_changes
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system_locale_changes
-w /etc/shadow -p wa -k shadow-file
-w /etc/passwd -p wa -k passwd_changes
-w /etc/group -p wa -k group_changes
-w /etc/sudoers -p wa -k sudoers_changes
-w /etc/selinux/ -p wa -k selinux_changes
-w /sbin/insmod -p x -k module_insertion
-w /tmp -p x -k webserver_watch_tmp
-w /etc/ssh/sshd_config -p wa -k sshd_config
-w /etc/httpd/conf/httpd.conf -p wa -k httpd_config
-w /etc/ntp.conf -p wa -k ntp_config
-w /etc/sysconfig/iptables -p wa -k iptables_config

# Disable adding any additional rules - note that adding new rules will require a reboot
-e 2

Come si può facilmente notare, in coda alla lista ho aggiunto l’opzione -e 2 che impedisce l’aggiunta di nuove regole on-the-fly (per questioni di sicurezza).

E’ sufficiente quindi restartare il demone auditd per rendere operative le suddette regole:

[root@linuxbox ~]# service auditd restart

Per ora è tutto. Nei prossimi post vedremo come monitorare in modo proattivo le regole di auditing mediante swatch, NRDP e Nagios.

Alla prossima.

yum-cron: verificare automaticamente la disponibilità degli aggiornamenti su CentOS 6

In questo post ho reso disponibile uno scrip bash (scritto di mio pugno) in grado di verificare (tramite yum) la disponibilità di security fix, bug fix e CVE.

Adesso vedremo come estendere tale funzionalità a qualsiasi tipo di update, usufruendo di un pacchetto software creato appositamente per CentOS 6, ovvero yum-cron.

yum

Per prima cosa installiamo il suddetto applicativo:

[root@linuxbox ~]# yum install yum-cron

Ad installazione completa modifichiamo il file di configurazione /etc/sysconfig/yum-cron secondo le nostre esigenze. In particolare, vogliamo fare in modo che ci venga notificata tramite email la disponibilità di eventuali update, senza installare nulla automaticamente:

# Don't install, just check (valid: yes|no)
CHECK_ONLY=yes

# Check to see if you can reach the repos before updating (valid: yes|no)
CHECK_FIRST=yes

MAILTO=vostro.indirizzo@email.it

A questo punto non ci rimane che avviare il servizio yum-cron:

[root@linuxbox ~]# service yum-cron start

e fare in modo che venga eseguito in automatico dopo ogni reboot della nostra macchina:

[root@linuxbox ~]# chkconfig yum-cron on

E’ tutto. Alla prossima.

CentOS 6: Riavviare automaticamente il servizio barnyard2 mediante Nagios e gli event handlers

In questo post ho mostrato il codice sorgente del demone barnyard2 da me customizzato. Esso, in soldoni, non fa altro che monitorare il contenuto del file alert generato da snort, in modo da poter individuare gli allarmi creati dall’IDS in questione, inserendoli (dopo un’opportuna formattazione) all’interno di uno specifico DBMS (nel nostro caso MySQL).

Purtroppo, però, tale servizio tende a crashare in modo randomico, ragion per cui ho deciso di creare un event handler (per Nagios) in grado di riavviarlo automaticamente.

nagios

Configurazione del SO che ospita L’NMS (Nagios)

Poichè l’operazione di riavvio del demone barnyard2 richiede i privilegi di root, è stato necessario fare in modo che l’utente nagios (che esegue gli event handlers) fosse abilitato all’interno del file /etc/sudoers:

nagios   ALL=NOPASSWD: /sbin/service barnyard2 restart

In particolare, ho fatto in modo che l’esecuzione del comando sudo non richiedesse la password (ALL=NOPASSWD:) solo per il comando /sbin/service barnyard2 restart (per la serie less is more). Inoltre, sempre all’interno del suddetto file, ho inserito, subito dopo la direttiva Defaults    requiretty, la stringa:

Defaults:nagios        !requiretty

in modo tale da consentire all’utente nagios di lanciare il comando sudo anche quando non è in possesso di un terminale (tty). Ciò è necessario poichè tutti gli event handlers vengono lanciati dal nostro NMS in assenza di sessione tty.

Un’altra modifica altrettanto importante ha riguardato SElinux. Esso, infatti, essendo attivo in modalità Enforcing, vietava puntualmente l’esecuzione dell’event handler in questione. Per “aggirare” tale divieto, ho dovuto modificare alcune regole MAC (Mandatory Access Control), attraverso 2 passaggi: il settaggio di una variabile booleana e la creazione di un modulo custom per SElinux.

Nel primo caso è stato sufficiente lanciare il comando:

[root@NMS]# setsebool -P nagios_run_sudo 1

mentre nel secondo caso ho dapprima creato il file permitnagioseventhandlers.te, di cui riporto il contenuto:

module permitnagioseventhandler 1.0;

require {
        type nagios_system_plugin_t;
        type nagios_unconfined_plugin_exec_t;
        type nagios_eventhandler_plugin_t;
        type httpd_t;
        class file { getattr };
        class dir { getattr search };
}

#============= nagios_system_plugin_t ==============
allow nagios_system_plugin_t nagios_unconfined_plugin_exec_t:file {getattr};

#============= httpd_t ==============
allow httpd_t nagios_eventhandler_plugin_t:dir { getattr search };

per poi verificarne la sintassi:

[root@NMS]#  checkmodule -M -m -o permitnagioseventhandler.mod permitnagioseventhandler.te

compliarlo:

[root@NMS]# semodule_package -o permitnagioseventhandler.pp -m permitnagioseventhandler.mod

ed installarlo:

[root@NMS]# semodule -i permitnagioseventhandler.pp

Configurazione di Nagios

Il riavvio del demone barnyard2 richiede parecchio tempo (soprattutto se esso è stato associato a più interfacce di rete, come nel mio caso). Per questo motivo si è reso necessario modificare il paramentro event_handler_timeout presente all’interno del file di configurazione Nagios (/etc/nagios/nagios.cfg), portandolo da 30 secondi (valore di default) a 300 secondi:

event_handler_timeout=400

Per ciò che concerne il servizio (relativo al nostro NMS) che si occupa del monitoraggio di barnyard2, è stata creata la seguente configurazione:

define service{
        use                             local-service         ; Name of service template to use
        host_name                       localhost
        service_descripion             Barnyard2 Service Status
        check_command                   check_local_process_status_all!2!2!barnyard2
        event_handler                   restart_barnyard
        }

dove il comando check_local_process_status_all è così definito:

# 'check_local_process_status_all' command definition
define command{
        command_name    check_local_process_status_all
        command_line    $USER1$/check_procs -c $ARG1$:$ARG2$ -C $ARG3$
        }

Nella fattispecie, le variabili $ARG1$ e $ARG2$ rappresentano, rispettivamente, il numero minimo e massimo di processi (recanti la stringa barnyard2, specificata mediante la variabile $ARG3$) attivi sulla macchina da monitorare.

Inoltre, è stato definito il comando restart_barnyard, il cui scopo è quello di eseguire l’event handler in questione:

# 'restart_barnyard' command definition
define command {
        command_name      restart_barnyard
        command_line      /usr/lib64/nagios/plugins/eventhandlers/restart_barnyard $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$
}

Ho quindi riavviato Nagios per rendere effettive le suddette modifiche:

[root@NMS]# service nagios reload

Contenuto dell’event handler (restart_barnyard)

Una volta completata la fase preliminare relativa alla configurazione del SO e dell’NMS, mi sono dedicato alla creazione dell’event handler vero e proprio (che ho chiamato, molto semplicemente, restart_barnyard). Esso presenta il seguente contenuto:

#!/bin/bash

case "$1" in
OK)
        ;;
WARNING)
        ;;
UNKNOWN)
        ;;
CRITICAL)
       case "$2" in
                SOFT)
                        case "$3" in
                        3)
                                echo -n "Restarting barnyard2 service (3rd soft critical state)..."
                                /usr/bin/sudo /sbin/service barnyard2 restart
                                ;;
                                esac
                        ;;
                HARD)
                        echo -n "Restarting barnyard2 service..."
                        /usr/bin/sudo /sbin/service barnyard2 restart
                        ;;
                esac
                ;;
        esac

exit 0

ovvero non fa altro che riavviare il servizio in oggetto nel caso del terzo critical state (soft) o del quarto critical state (hard).

L’ho quindi reso eseguibile:

[root@NMS]# chmod +x restart_barnyard

e l’ho salvato all’interno della dir /usr/lib64/nagios/plugins/eventhandlers:

[root@NMS]# mv restart_barnyard /usr/lib64/nagios/plugins/eventhandlers

Test di funzionamento

Infine, ho testato il tutto semplicemente arrestando il servizio barnyard2:

[root@NMS]# service barnyard2 stop

verificando che Nagios svolgesse tutta la trafila per ritirarlo su in modo automatico:

[root@NMS]# tail -f /var/log/nagios/nagios.log

il cui output mi ha mostrato le diverse fasi di passaggio dallo stato CRITICAL allo stato OK:

[1448964811] SERVICE EVENT HANDLER: localhost;Barnyard2 Service Status;CRITICAL;SOFT;3;restart_barnyard
[1448965026] SERVICE ALERT: localhost;Barnyard2 Service Status;CRITICAL;HARD;4;PROCS CRITICAL: 0 processes with command name 'barnyard2'
[1448965026] SERVICE EVENT HANDLER: localhost;Barnyard2 Service Status;CRITICAL;HARD;4;restart_barnyard
[1448965313] SERVICE ALERT: localhost;Barnyard2 Service Status;OK;HARD;4;PROCS OK: 2 processes with command name 'barnyard2'
[1448965313] SERVICE EVENT HANDLER: localhost;Barnyard2 Service Status;OK;HARD;4;restart_barnyard

Inoltre, digitando il comando:

[root@NMS]# ps aux | grep barn

ho visualizzato i processi di barnyard2 durante il loro avvio da parte dell’event handler:

nagios    2799  0.0  0.0 108208  1352 ?        S    11:17   0:00 /bin/bash /usr/lib64/nagios/plugins/eventhandlers/restart_barnyard CRITICAL HARD 4
root      2800  0.1  0.1 189744  3392 ?        S    11:17   0:00 /usr/bin/sudo /sbin/service barnyard2 restart
root      2803  0.0  0.0 106460  1680 ?        S    11:17   0:00 /bin/sh /sbin/service barnyard2 restart
root      2809  0.0  0.0 108568  1868 ?        S    11:17   0:00 /bin/sh /etc/init.d/barnyard2 restart
root      3194 65.8  1.2  92668 40796 ?        Rs   11:18   1:06 barnyard2 -D -c /etc/snort/barnyard2eth0.conf -d /var/log/snort/eth0 -w /var/log/snort/eth0/barnyard2.waldo -l /var/log/snort/eth0 -a /var/log/snort/eth0/archive -f snort.log --pid-path /var/run
root      3196  0.0  0.0 108200  1284 ?        S    11:18   0:00 /bin/bash -c ulimit -S -c 0 >/dev/null 2>&1 ; barnyard2 -D -c /etc/snort/barnyard2eth1.conf -d /var/log/snort/eth1 -w /var/log/snort/eth1/barnyard2.waldo -l /var/log/snort/eth1 -a /var/log/snort/eth1/archive -f snort.log --pid-path /var/run
root      3197 61.4  0.2  58856  7808 ?        R    11:18   1:01 barnyard2 -D -c /etc/snort/barnyard2eth1.conf -d /var/log/snort/eth1 -w /var/log/snort/eth1/barnyard2.waldo -l /var/log/snort/eth1 -a /var/log/snort/eth1/archive -f snort.log --pid-path /var/run
root      3710  0.0  0.0 103268   864 pts/2    S+   11:20   0:00 grep barn

E’ tutto. Alla prossima.

CentOS 6: realizzare un network intrusion detection system open source – Parte 1

Premessa

A differenza delle numerose guide cooked e dei vari howto che si possono trovare in rete, questo post (primo di una serie di 3), ha come scopo quello di illustrare in modo esaustivo i vari passi necessari per la realizzazione di una sistema NIDS.

Un po’ di teoria

Esistono diverse metodologie per difendere l’infrastruttura IT dai cyber attacchi, e, tutto sommato, le si può riassumere in 2 macro categorie, ovvero quelle attive e quelli passive. Per strategia difensiva attiva basti pensare ad un firewall, ad un antivirus oppure ad un IPS (Intrusion Preventetion System). Per contro, un tipico esempio di strategia difensiva di tipo passivo è rappresentato dai sistemi IDS (Intrusion Detection System), i quali possono agire localmente sulla macchina interessata (in tal caso parliamo di HIDS, ovvero Host IDS), oppure a livello di rete (in questo caso parliamo di NIDS, ovvero Network IDS).

I sistemi NIDS (detti anche sonde o sensori), non fanno altro che analizzare il traffico del segmento di rete a cui sono collegati (DMZ, LAN, Outside), alla ricerca di eventuali tentativi di attacco.

Solitamente, essi non vengono posizionati inline (come invece avviene per i sistemi IPS), ma sono collegati ad una porta dello switch configurata in mirror (monitor/span), sulla quale viene inoltrata una replica esatta di tutto il traffico passante per lo switch in questione. In questo modo un eventuale sovraccarico del sensore non comporterà automaticamente un rallentamento della rete in termini di throughput.

Topoligia

Poichè la rete sulla quale ho configurato il sistema NIDS è dotata di un firewall *nix che filtra tutto il traffico in ingresso ed in uscita, per questioni di budget e di praticità, ho ritenuto opportuno installare la sonda sulla macchina in questione. Va da se che l’analisi preventiva del carico computazionale a cui era soggetto il firewall ha restituito valori di overhead davvero irrisori, dunque l’installazione della sonda non ha comportato grossi cambiamenti in termini prestazionali.

NIDS

Ingredienti

Il software che fungerà da sensore prende il nome di snort. Inoltre, per aggiornare in modo automatico le signature/pattern degli attacchi verrà utilizzato pulledpork (a tutti gli effetti il successore di oinkmaster), mentre per convertire in formato SQL e salvare gli alert generati da snort all’interno di un DB (MySQL) verrà utilizzato barnyard2. Infine, verrà installata sulla macchina ospite un’interfaccia Web (GUI) scritta in Ruby ed accessibile tramite Apache, dalla quale poter estrapolare gli allarmi con le relative statistiche,  il cui nome è snorby (SNORt ruBY).

Occorre precisare che MySQL (DBMS) ed Apache (server Web) sono già installati sulla macchina ospite.

Installazione e configurazione di snort

Tale attività si divide in 3 step:

1) l’installazione dei software prerequisiti;

2) l’installazione delle librerie daq;

3) l’installazione e la configurazione di snort.

I software prerequisiti sono bison, flex, libpcap e libdnet e li si può installare utilizzando il packet manager di casa CentOS/Red Hat, ovvero yum:

yum install bison flex libpcap libpcap-devel libdnet libdnet-devel

Posizioniamoci nella directory /usr/local/src per poi scaricare, compilare ed installare le librerie daq (le quali servono a reindirizzare il network I/O ai software di “cattura” veri e propri, quali, ad esempio, PCAP, AFPACKET e simili):

wget https://www.snort.org/downloads/snort/daq-2.0.6.tar.gz
tar -xvf daq-2.0.6.tar.gz
cd daq-2.0.6
./configure
make
make install
ldconfig
cd ..

A questo punto possiamo scaricare ed installare snort:

wget https://www.snort.org/downloads/snort/snort-2.9.7.5.tar.gz
tar -xvf snort-2.9.7.5.tar.gz
cd snort-2.9.7.5
./configure
make
make install

Ad installazione completata creiamo utente e gruppo per il suddetto applicativo:

groupadd snort
useradd snort -g snort -s /sbin/nologin

per poi creare la directory su cui salvare i file di configurazione e le regole per la rilevazione delle intrusioni:

mkdir -p /etc/snort
mkdir -p /etc/snort/rules
cd etc
cp -R * /etc/snort
cd ..

Inoltre, scarichiamo le regole vere e proprie e salviamole all’interno della dir /etc/snort/rules:

wget https://www.snort.org/downloads/community/community-rules.tar.gz
tar -xvf community-rules.tar.gz
cd community-rules
cp * /etc/snort/rules
wget https://www.snort.org/downloads/registered/snortrules-snapshot-2975.tar.gz?oinkcode=<vostro oinkcode ricavabile dalla pagina Web di snort, previa registrazione>
tar -xvf nortrules-snapshot-2975.tar.gz
cd snortrules-snapshot-2975
cp -R preproc_rules/ /etc/snort/rules
cp -R so_rules/ /etc/snort/rules
cd rules
cp * /etc/snort/rules

Assegniamo il giusto owner alla directory /etc/snort:

chown snort:snort -R /etc/snort

e concentriamoci sulle dynamic rules (con relative librerie):

mkdir -p /usr/local/lib/snort_dynamicrules
chown -R snort:snort /usr/local/lib/snort_dynamicrules
cp /usr/local/src/so_rules/precompiled/RHEL-6-0/x86-64/2.9.7.5 /usr/local/lib/snort_dynamicrules
chmod -R 700 /usr/local/lib/snort_dynamicrules

Ora passiamo alla configurazione di snort:

nano /etc/snort/snort.conf

nella quale occorre definire le reti locali (HOME_NET), le reti esterne (EXTERNAL_NET), il pathname delle regole utilizzate da snort e quello delle whitelist/blacklist (basate sulla reputazione). Inoltre, bisogna definire il tipo di output generato da snort (il quale dovrà essere interpretabile da barnyard2).

Ecco uno stralcio delle modifiche apportate al file di configurazione di snort:

ipvar HOME_NET [192.168.1.0,192.168.12.0]
ipvar EXTERNAL_NET !$HOME_NET

var RULE_PATH /etc/snort/rules
var SO_RULE_PATH /etc/snort/rules/so_rules
var PREPROC_RULE_PATH /etc/snort/rules/preproc_rules

var WHITE_LIST_PATH /etc/snort/rules
var BLACK_LIST_PATH /etc/snort/rules

# Reputation preprocessor. For more information see README.reputation
preprocessor reputation: \
   memcap 500, \
   priority whitelist, \
   nested_ip inner, \
#   whitelist $WHITE_LIST_PATH/white_list.rules, \
   blacklist $BLACK_LIST_PATH/black_list.rules

output unified2: filename snort.log, limit 128

Creiamo la directory in cui snort dovrà salvare i log e gli allarmi, assegnandole il giusto owner:

mkdir -p /var/log/snort/
chown snort:snort /var/log/snort/

Infine, testiamo la configurazione di snort, lanciando il comando:

snort -T -i <interface-name> -u snort -g snort -c /etc/snort/snort.conf

il cui output (se non vi sono errori) dovrà contenere la seguente stringa:

Snort successfully validated the configuration!

Eseguire snort come demone

Per fare in modo che snort venga eseguito sulla macchina ospite come demone, occorre, prima di tutto, configurare le opzioni di avvio (definendole all’interno del file /etc/sysconfig/snort):

nano /etc/sysconfig/snort

il cui contenuto dovrà essere simile al seguente:

# /etc/sysconfig/snort
# $Id$

# All of these options with the exception of -c, which tells Snort where
# the configuration file is, may be specified in that configuration file as
# well as the command line. Both the command line and config file options
# are listed here for reference.

#### General Configuration

# What interface should snort listen on?  [Pick only 1 of the next 3!]
# This is -i {interface} on the command line
# This is the snort.conf config interface: {interface} directive
#INTERFACE=eth0
#
# The following two options are not directly supported on the command line
# or in the conf file and assume the same Snort configuration for all
# instances
#
# To listen on all interfaces use this:
INTERFACE=ALL
#
# To listen only on given interfaces use this:
#INTERFACE="eth1 eth2 eth3 eth4 eth5"

# Where is Snort's configuration file?
# -c {/path/to/snort.conf}
CONF=/etc/snort/snort.conf

# What user and group should Snort drop to after starting? This user and
# group should have very few privileges.
# -u {user} -g {group}
# config set_uid: user
# config set_gid: group
USER=snort
GROUP=snort

# Should Snort change the order in which the rules are applied to packets.
# Instead of being applied in the standard Alert->Pass->Log order, this will
# apply them in Pass->Alert->Log order.
# -o
# config order: {actions in order}
# e.g. config order: log alert pass activation dynamic suspicious redalert
PASS_FIRST=0

#### Logging & Alerting

# NOTE: NO_PACKET_LOG and BINARY_LOG, ALERTMODE, etc. are mutually
# exclusive. Use either NO_PACKET_LOG or any/all of the other logging
# options. But the more logging options use you, the slower Snort will run.

# Where should Snort log?
#
#-l {/path/to/logdir}
# config logdir: {/path/to/logdir}
LOGDIR=/var/log/snort

# config basename:
BASENAME=snort.log

# How should Snort alert? Valid alert modes include fast, full, none, and
# unsock.  Fast writes alerts to the default "alert" file in a single-line,
# syslog style alert message.  Full writes the alert to the "alert" file
# with the full decoded header as well as the alert message.  None turns off
# alerting. Unsock is an experimental mode that sends the alert information
# out over a UNIX socket to another process that attaches to that socket.
# -A {alert-mode}
# output alert_{type}: {options}
#ALERTMODE=full

# Should Snort dump the application layer data when displaying packets in
# verbose or packet logging mode.
# -d
# config dump_payload
DUMP_APP=1

# Should Snort keep binary (AKA pcap, AKA tcpdump) logs also? This is
# recommended as it provides very useful information for investigations.
# -b
# output log_tcpdump: {log name}
#BINARY_LOG=1

# Should Snort turn off packet logging?  The program still generates
# alerts normally.
# -N
# config nolog
NO_PACKET_LOG=0

# Print out the receiving interface name in alerts.
# -I
# config alert_with_interface_name
PRINT_INTERFACE=0

# When dumping the stats, what log file should we look in
SYSLOG=/var/log/messages

# When dumping the stats, how long to wait to make sure that syslog can
# flush data to disk
SECS=5

# To add a BPF filter to the command line uncomment the following variable
# syntax corresponds to tcpdump(8)
#BPF="not host 192.168.1.1"

# To use an external BPF filter file uncomment the following variable
# syntax corresponds to tcpdump(8)
# -F {/path/to/bpf_file}
# config bpf_file: /path/to/bpf_file
#BPFFILE=/etc/snort/bpf_file

a tal proposito, occorre precisare che è necessario commentare le direttive ALERTMODE e BINARY_LOG, altrimenti barnyard2 non sarà in grado di inserire gli allarmi all’interno del database.

Inoltre, poichè il sensore è posizionato inline, esso si trova in ascolto su tutte le interfacce della macchina (INTERFACE=ALL).

Di seguito riporto lo script che consente di demonizzare l’applicativo in questione:

#!/bin/sh
# $Id$
#
# snortd         Start/Stop the snort IDS daemon.
#
# chkconfig: 2345 40 60
# description:  snort is a lightweight network intrusion detection tool that \
#                currently detects more than 1100 host and network \
#                vulnerabilities, portscans, backdoors, and more.
#

# Source function library.
. /etc/rc.d/init.d/functions

# Source the local configuration file
. /etc/sysconfig/snort

#PID file location
PID=/var/run/snort

# Convert the /etc/sysconfig/snort settings to something snort can
# use on the startup line.
if [ "$ALERTMODE"X = "X" ]; then
   ALERTMODE=""
else
   ALERTMODE="-A $ALERTMODE"
fi

if [ "$USER"X = "X" ]; then
   USER="snort"
fi

if [ "$GROUP"X = "X" ]; then
   GROUP="snort"
fi

if [ "$BINARY_LOG"X = "1X" ]; then
   BINARY_LOG="-b"
else
   BINARY_LOG=""
fi

if [ "$CONF"X = "X" ]; then
   CONF="-c /etc/snort/snort.conf"
else
   CONF="-c $CONF"
fi

if [ "$INTERFACE"X = "X" ]; then
   INTERFACE="-i eth0"
else
   INTERFACE="-i $INTERFACE"
fi

if [ "$DUMP_APP"X = "1X" ]; then
   DUMP_APP="-d"
else
   DUMP_APP=""
fi

if [ "$NO_PACKET_LOG"X = "1X" ]; then
   NO_PACKET_LOG="-N"
else
   NO_PACKET_LOG=""
fi

if [ "$PRINT_INTERFACE"X = "1X" ]; then
   PRINT_INTERFACE="-I"
else
   PRINT_INTERFACE=""
fi

if [ "$PASS_FIRST"X = "1X" ]; then
   PASS_FIRST="-o"
else
   PASS_FIRST=""
fi

if [ "$LOGDIR"X = "X" ]; then
   LOGDIR=/var/log/snort
fi

# These are used by the 'stats' option
if [ "$SYSLOG"X = "X" ]; then
   SYSLOG=/var/log/messages
fi

if [ "$SECS"X = "X" ]; then
   SECS=5
fi

if [ ! "$BPFFILE"X = "X" ]; then
   BPFFILE="-F $BPFFILE"
fi

######################################
# Now to the real heart of the matter:

# See how we were called.
case "$1" in
  start)
        echo -n "Starting snort: "
        cd $LOGDIR
        if [ "$INTERFACE" = "-i ALL" ]; then
           for i in `cat /proc/net/dev|grep eth|awk -F ":" '{ print $1; }'`
           do
                mkdir -p "$LOGDIR/$i"
                chown -R $USER:$GROUP $LOGDIR
                daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE -i $i -u $USER -g $GROUP $CONF -l $LOGDIR/$i 

$PASS_FIRST $BPFFILE $BPF
           done
        else
           # check if more than one interface is given
           if [ `echo $INTERFACE|wc -w` -gt 2 ]; then
              for i in `echo $INTERFACE | sed s/"-i "//`
                do
                  mkdir -p "$LOGDIR/$i"
                  chown -R $USER:$GROUP $LOGDIR
                  daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE -i $i -u $USER -g $GROUP $CONF -l $LOGDIR/$i 

$PASS_FIRST $BPFFILE $BPF
             done
           else
              # Run with a single interface (default)
              daemon /usr/sbin/snort $ALERTMODE $BINARY_LOG $NO_PACKET_LOG $DUMP_APP -D $PRINT_INTERFACE $INTERFACE -u $USER -g $GROUP $CONF -l $LOGDIR 

$PASS_FIRST $BPFFILE $BPF --pid-path $PID
           fi
        fi
        touch /var/lock/subsys/snort
        echo
        ;;
  stop)
        echo -n "Stopping snort: "
        killproc snort
        rm -f /var/lock/subsys/snort
        echo
        ;;
  reload)
        echo "Sorry, not implemented yet"
        ;;
  restart)
        $0 stop
        $0 start
        ;;
  condrestart)
        [ -e /var/lock/subsys/snort ] && $0 restart
        ;;
  status)
        status snort
        ;;
  stats)
        TC=125                          # Trailing context to grep
        SNORTNAME='snort'               # Process name to look for

        if [ ! -x "/sbin/pidof" ]; then
           echo "/sbin/pidof not present, sorry, I cannot go on like this!"
           exit 1
        fi

        #Grab Snort's PID
        PID=`pidof -o $$ -o $PPID -o %PPID -x ${SNORTNAME}`

        if [ ! -n "$PID" ]; then        # if we got no PID then:
           echo "No PID found: ${SNORTNAME} must not running."
           exit 2
        fi

        echo ""
        echo "*******"
        echo "WARNING:  This feature is EXPERIMENTAL - please report errors!"
        echo "*******"
        echo ""
        echo "You can also run: $0 stats [long | opt]"
        echo ""
        echo "Dumping ${SNORTNAME}'s ($PID) statistics"
        echo "please wait..."

        # Get the date and tell Snort to dump stats as close together in
        # time as possible--not 100%, but it seems to work.
        startdate=`date '+%b %e %H:%M:%S'`

        # This causes the stats to be dumped to syslog
        kill -USR1 $PID

        # Sleep for $SECS secs to give syslog a chance to catch up
        # May need to be adjusted for slow/busy systems
        sleep $SECS

        if [ "$2" = "long" ]; then              # Long format
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                grep snort.*:
        elif [ "$2" = "opt" ]; then             # OPTimize format
           # Just show stuff useful for optimizing Snort
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                egrep "snort.*: Snort analyzed |snort.*: dropping|emory .aults:"
        else                                    # Default format
            egrep -B 3 -A $TC "^$startdate .* snort.*: ={79}" $SYSLOG | \
                grep snort.*: | cut -d: -f4-
        fi
        ;;
  *)
        echo "Usage: $0 {start|stop|reload|restart|condrestart|status|stats (long|opt)}"
        exit 2
esac

exit 0

Copiamo il binario di snort nella dir /usr/sbin:

cp /usr/local/bin/snort /usr/sbin/

e rendiamo il suddetto scrip eseguibile, per poi avviarlo e fare in modo che venga eseguito automaticamente dopo ogni riavvio della macchina:

chmod +x /etc/init.d/snortd
chkconfig --add snortd
chkconfig snortd on

Per ora abbiamo finito. Nel prossimo post vedremo come installare e configurare pulledpork e barnyard2.

A presto.

Configurare un server VNC su CentOS 6

Avere a disposizione un server VNC sulla nostra linux box è molto comodo, soprattutto quando la si utilizza come “ponte” per accedere all’interfaccia Web di configurazione di alcuni dispositivi di rete (quali NAS, access point, router e così via).

vnc

Di seguitò illustrerò come fare ad installare e configurare un server VNC sulla nostra macchina CentOS 6.

Installazione  del server VNC

Per scaricare il server VNC è sufficiente utilizzare il packet manager integrato alla distro, ovvero yum:

[root@vncserver ~]# yum install tigher-vnc

Configurazione del server VNC

Per prima cosa occorre creare le utenze che andranno ad utilizzare il server VNC:

[root@vncserver ~]# useradd <username1>
[root@vncserver ~]# passwd <username1>
[root@vncserver ~]# useradd <username2>
[root@vncserver ~]# passwd <username2>

Una volta create le utenze,  occorre settare i parametri delle sessioni VNC a cui avranno accesso, editando il file /etc/sysconfig/vncserver:

VNCSERVERS="1:username1 2:username2"
VNCSERVERARGS[1]="-geometry 1024x768"
VNCSERVERARGS[2]="-geometry 1024x768"

Per entrambi gli utenti precedentemente definiti abbiamo previsto delle sessioni VNC con risoluzione a 1024×768.

A questo punto, ciascun utente, dovrà impostare la propria password VNC mediante il comando:

[username1@vncserver ~]$ vncpasswd

Infine, dovrà editare il file xstartup presente nella propria home directory:

[username1@vncserver ~]$ nano /home/username/.vnc/xstartup

commentando la entry:

#twm &

ed inserendo la seguente direttiva (nel caso in cui sulla linux box sia installato KDE come X server):

startkde &

Invece, se si sta utilizzando Gnome, la direttiva da inserire è la seguente:

exec gnome-session

Configurazione del firewall

Per configurare il firewall (netfilter) occorre editare il file /etc/sysconfig/iptables, aggiungendo quanto segue:

-A INPUT -m state --state NEW -m tcp -p tcp -m multiport --dports 5901:5903,6001:6003 -j ACCEPT

Riavviamo netfilter con il seguente comando:

[root@vncserver ~]# service iptables restart

e facciamo in modo che il nostro server VNC venga eseguito in modo automatico dopo ogni riavvio della macchina:

[root@vncserver ~]# chkconfig vncserver on

Infine, avviamo il suddetto demone:

[root@vncserver ~]# service vncserver start

Client VNC

Il client che preferisco è Real VNC Viewer e potete scaricarlo da qui.

Fine del post, a presto.

VMWare ESX 5.1: ridimensionare i dischi su macchine virtuali Centos 6

Dopo aver aumentato la dimensione di un disco relativo ad una macchina virtuale tramite VSphere client (supponendo che il sistema operativo sia stato precedentemente installato e dunque che le partizioni siano già state create), è necessario modificare la tabella delle partizioni e successivemente le dimensioni dello spazio usufruibile dal sistema operativo (altrimenti lo spazio aggiuntivo non potrà essere utilizzato).

 

VMWare-Logo.JPG

Per fare ciò, occorre operare come segue:

[root@vm ~]# fdisk

per invocare l’utility fdisk, la quale ci permette di operare sulla tabella delle partizioni, supponendo, nella fattispecie, che il disco sia mappato come /dev/sda (SCSI o SATA).

Una volta entrati nel menù della suddetta utility, è necessario creare una nuova partizione, semplicemente digitando n:

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): n

La nuova partizione dovrà essere primaria (tenendo a mente che è possibile creare un massimo di 4 partizioni primarie). Per fare ciò si deve cliccare sul tasto p della nostra tastiera.

Command action
   e   extended
   p   primary partition (1-4)
p

Scegliamo quindi l’id della partizione (nel mio caso è 3 dato che vi sono già due partizioni primarie installate, rispettivamente con id 1, ovvero la partizione di boot e 2, quella in cui risiede il SO). Digitiamo dunque 3.

Partition number (1-4): 3

Se non siete sicuri di quante partizioni siano effettivamente presenti sulla vostra macchina, digitate p (che in questo caso sta per print):

Command (m for help): p

Infine, creiamo la nuova partizione semplicemente digitando w.

Command (m for help): w

Per rendere effettive le modifiche appena effettuate, si rende necessario il riavvio della macchina virtuale:

[root@vm ~]# reboot

Una volta che la suddetta macchina si è avviata, possiamo verificare che la nuova partizione sia effettivamente presente digitando il comando:

[root@vm ~]# ls -al /dev/sda*

Aggiungiamo la nuova partizione al volume group, il cui nome, solitamente è costituito da un prefisso standard, ovvero vg_ e dal nome che abbiamo assegnato alla nostra macchina virtuale, vm in questo caso:

[root@vm ~]# vgextend vg_vm /dev/sda3

Infine ridimensioniamo la partizione aggiungendo ulteriori 39 GB di spazio:

[root@vm ~]# lvresize --size +39g --resizefs /dev/mapper/vg_wm-lv_root

A questo punto lanciando un semplice df possiamo verificare che effettivamente lo spazio associato alla partizione del SO è effettivamente aumentato.

Enjoy!

NB: tale procedura si rende necessaria in quanto alcuni tool nati proprio per la gestione delle partizioni (come gparted) non supportano LVM (nativo in Centos 6).

Centos 6: Apache e le ACL basate sull’IP sorgente

Per fare in modo che il contenuto di alcuni file presenti nella directory a cui punta Apache possa essere visualizzato solo da determinati IP sorgenti è necessario definire delle ACL direttamente nel file .htaccess posizionato nella suddetta dir, oltre ad effettuare una piccola modifica all’interno del file di configurazione di Apache stesso, ovvero /etc/httpd/conf/httpd.conf.

 

apache-logo_new.png

Il contenuto del file .htaccess dovrà essere strutturato nel modo seguente:

Order Deny,Allow
Deny from All
Allow from <IP1>
Allow from <IP2>
Allow from <IP3>
Allow from <IP4>
Allow from <IP5>

mentre all’interno del file di configurazione di Apache occorre aggiungere la seguente direttiva:

<Directory /var/www/securecontent>
         AllowOverride All
</Directory>

dove securecontent è la directory il cui contenuto vuole essere riservato solo ai suddetti IP.

Infine eseguiamo un reload della configurazione di Apache:

[root@webserver ~]# service httpd reload

ed abbiamo finito.

Alla prossima.