IDS/Prelude
Introduction
Ce document décrit le déroulement pas à pas de l'installation d'un serveur de détection d'intrusion.
Nous utiliserons <package>prelude</package> comme aggrégateur, <package>snort</package> ou <package>suricata</package> pour la partie NIDS, <package>ossec</package> pour la partie HIDS, <package>prelude-lml</package> pour parser les fichiers de log locaux et <package>prewikka</package> pour l'affichage des données.
Prelude est un système de détection d’intrusion hybride composé de plusieurs plugins, sondes. Prelude a été conçu dans le but d’être modulaire, souple, et résistant aux attaques. Sa modularité permet notamment de lui rajouter facilement de nouveaux types de détecteurs d’intrusion, d’analyseurs de logs et d’une solution de corrélation, le tout au format et à la norme IDMEF (Intrusion Detection Message Exchange Format), bien que de nombreux autres formats de logs sont compatibles.
On prendra soin d'installer soit snort soit suricata, mais il est conseillé d'en avoir qu'un seul actif par hôte.
Prérequis :
- CentOS fresh install.
- Dépôt yum b2pweb.
Installation du système de détection d'intrusion
Installation des dépendances
Nous aurons besoin d'un serveur de base de données MySQL, d'un serveur web ( avec les modules mod_ssl et mod_python ) et de php.
yum install mysql-server httpd mod_ssl mod_python php php-mysql
Installation de la suite prelude
Avec les RPM, ça se résume à :
yum install libprelude libprelude-devel libpreludedb-mysql prelude-manager mysql-client prelude-manager-xml-plugin prelude-manager-db-plugin prelude-lml
On créer la base de données
mysql -e "create database prelude;" mysql -e "grant all privileges on prelude.* to prelude@localhost identified by 'prelude';" sed -i -e "/InnoDB/ s/TYPE/ENGINE/g" /usr/share/libpreludedb/classic/mysql.sql mysql -u prelude -p prelude < /usr/share/libpreludedb/classic/mysql.sql
On enregistre prelude-manager et on démarre le manager
prelude-admin add "prelude-manager" --uid 0 --gid 0 /etc/init.d/prelude-manager start
Installation de prewikka
yum install prewikka
On créer sa base de données
mysql -e "create database prewikka;" mysql -e "grant all privileges on prewikka.* to prewikka@localhost identified by 'prewikka';" mysql -u prewikka -p prewikka < /usr/share/prewikka/database/mysql.sql
on créer le virtual host
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName vmdidier1.b2pweb.com
Alias /prewikka /usr/share/prewikka/htdocs
ScriptAlias /ids /usr/share/prewikka/cgi-bin/prewikka.cgi
<Directory "/usr/share/prewikka">
AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
<Limit GET POST OPTIONS>
Order allow,deny
Allow from all
</Limit>
<LimitExcept GET POST OPTIONS>
Order deny,allow
Deny from all
</LimitExcept>
</Directory>
</VirtualHost>
Installation ossec
yum install ossec-hids-server
enregistrement d'ossec comme sonde prelude
Ouverture de deux shells en parallèle
# prelude-admin registration-server prelude-manager The "app4yb0m" password will be requested by "prelude-admin register" in order to connect. Please remove the quotes before using it. Generating 1024 bits Diffie-Hellman key for anonymous authentication... Waiting for peers install request on :::5553... Waiting for peers install request on 0.0.0.0:5553... Connection from ::ffff:127.0.0.1:34094... Registration request for analyzerID="1008635719879802" permission="idmef:w admin:r". Approve registration? [y/n]: y ::ffff:127.0.0.1:34094 successfully registered.
# prelude-admin register ossec "idmef:w admin:r" 127.0.0.1 --uid 0 --gid 0 You now need to start "prelude-admin" registration-server on 127.0.0.1: example: "prelude-admin registration-server prelude-manager" Enter the one-shot password provided on 127.0.0.1: Confirm the one-shot password provided on 127.0.0.1: Connecting to registration server (127.0.0.1:5553)... Authentication succeeded. Successful registration to 127.0.0.1:5553.
On modifie la configuration d'ossec, dans le fichier <path>/var/ossec/etc/ossec.conf</path>, rajouter à la balise <global>
<global> ... <prelude_output>yes</prelude_output> <prelude_profile>ossec</prelude_profile> <prelude_log_level>6</prelude_log_level> ... </global>
redémarrage d'ossec
/etc/init.d/ossec-hids start
Installation de oinkmaster
C'est le script perl de mise à jour des règles officielles VTR de snort ( qui fonctionne aussi avec suricata )
yum install oinkmaster
on récupère le "oink code" sur le site de snort ( après enregistrement )
d5f57c7ff55b8e103893eb2f9aa1a933f36ea424
et on remplace dans /etc/oinkmaster.conf
url = http://www.snort.org/pub-bin/oinkmaster.cgi/d5f57c7ff55b8e103893eb2f9aa1a933f36ea424/snortrules-snapshot-2900.tar.gz
Téléchargement des règles officiellespetit script pour wrapper le script perl
Fichier <path>/usr/bin/oinkmaster</path>
#!/bin/sh
BIN_PATH="/usr/bin"
RULES_PATH="/etc/snort/rules"
RULES_BACKUP_PATH="/etc/snort/rules-backup"
OINKMASTER_CONF_FILE="/etc/oinkmaster.conf"
LOG_FILE="/var/log/oinkmaster.log"
${BIN_PATH}/oinkmaster.pl -o ${RULES_PATH} -b ${RULES_BACKUP_PATH} -C ${OINKMASTER_CONF_FILE} 1>${LOG_FILE} 2>&1
Et voilà, pour mettre à jour les règles, il suffit de taper ( plus facile pour le cron )
oinkmaster
Installation de snort
Ici on installe snort, THE détecteur d'intrusion.
yum install snort
dans le fichier /etc/snort/snort.conf, dé-commenter les lignes
output unified2: filename merged.log, limit 128, nostamp, mpls_event_types, vlan_event_types output alert_prelude profile=snort
On enregistre snort dans prelude, l'uid et le gid peuvent être trouvé avec la commande
SNORT_UID=`cat /etc/passwd | grep "^snort" | awk -F ':' '{print $3}'` ; SNORT_GID=`cat /etc/group | grep "^snort" | awk -F ':' '{print $3}'` ; echo "snort: uid=${SNORT_UID}, gid=${SNORT_GID}"
Ouverture de deux shells en parallèle
# prelude-admin registration-server prelude-manager The "105g5ukk" password will be requested by "prelude-admin register" in order to connect. Please remove the quotes before using it. Generating 1024 bits Diffie-Hellman key for anonymous authentication... Waiting for peers install request on :::5553... Waiting for peers install request on 0.0.0.0:5553... Connection from ::ffff:127.0.0.1:44183... Registration request for analyzerID="2107009181484785" permission="idmef:w admin:r". Approve registration? [y/n]: y ::ffff:127.0.0.1:44183 successfully registered.
# prelude-admin register snort "idmef:w admin:r" 127.0.0.1 --uid 500 --gid 500 Generating 1024 bits RSA private key... This might take a very long time. [Increasing system activity will speed-up the process]. Generation in progress... X.+++++O.+++++O You now need to start "prelude-admin" registration-server on 127.0.0.1: example: "prelude-admin registration-server prelude-manager" Enter the one-shot password provided on 127.0.0.1: Confirm the one-shot password provided on 127.0.0.1: Connecting to registration server (127.0.0.1:5553)... Authentication succeeded. Successful registration to 127.0.0.1:5553.
On Commente ALERTMODE dans /etc/sysconfig/snort ( sinon prelude ne reconnaît pas snort ) et on le démarre
sed -i -e "/ALERTMODE/ s|^|#|" /etc/sysconfig/snort /etc/init.d/snortd start
Installation de suricata
L'outsider des sniffeurs.
yum install suricata
On enregistre suricata dans prelude, l'uid et le gid peuvent être trouvé avec la commande
SURICATA_UID=`cat /etc/passwd | grep "^suricata" | awk -F ':' '{print $3}'` ; SURICATA_GID=`cat /etc/group | grep "^suricata" | awk -F ':' '{print $3}'` ; echo "suricata: uid=${SURICATA_UID}, gid=${SURICATA_GID}"
Ouverture de deux shells en parallèle
# prelude-admin registration-server prelude-manager The "105g5ukk" password will be requested by "prelude-admin register" in order to connect. Please remove the quotes before using it. Generating 1024 bits Diffie-Hellman key for anonymous authentication... Waiting for peers install request on :::5553... Waiting for peers install request on 0.0.0.0:5553... Connection from ::ffff:127.0.0.1:44183... Registration request for analyzerID="2107009181484785" permission="idmef:w admin:r". Approve registration? [y/n]: y ::ffff:127.0.0.1:44183 successfully registered.
# prelude-admin register suricata "idmef:w admin:r" 127.0.0.1 --uid 105 --gid 105 Generating 1024 bits RSA private key... This might take a very long time. [Increasing system activity will speed-up the process]. Generation in progress... X.+++++O.+++++O You now need to start "prelude-admin" registration-server on 127.0.0.1: example: "prelude-admin registration-server prelude-manager" Enter the one-shot password provided on 127.0.0.1: Confirm the one-shot password provided on 127.0.0.1: Connecting to registration server (127.0.0.1:5553)... Authentication succeeded. Successful registration to 127.0.0.1:5553.
Création d'un script de démarrage et d'un fichier sysconfig
Le fichier <path>/etc/init.d/suricata</path>
#!/bin/bash
#
# suricata This shell script takes care of starting and stopping suricata.
#
# chkconfig: 345 55 45
# description: suricata Intrusion Detection and Prevention Engine.
# probe: false
# processname: suricata
# pidfile: /var/run/suricata.pid
# config: /etc/sysconfig/suricata
### BEGIN INIT INFO
# Provides: suricata
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 3 4 5
# Short-Description: suricata.
# Description: Open Source Next Generation Intrusion Detection and Prevention Engine.
### END INIT INFO
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 0
[ -f /usr/bin/suricata ] || exit 0
[ -f /etc/sysconfig/suricata ] || exit 0
. /etc/sysconfig/suricata
if "${SURICATA_CONF_FILE}" == ""
then
echo -n "No conf file in /etc/sysconfig/suricata"
failure
echo
exit 1
fi
SURICATA_OPTIONS="-c ${SURICATA_CONF_FILE} -D"
if [[ "${SURICATA_IFACE}" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} -i ${SURICATA_IFACE}"
fi
if [[ "${SURICATA_LOG_DIR}" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} -l ${SURICATA_LOG_DIR}"
SURICATA_START=${SURICATA_LOG_DIR}/start.log
fi
if [[ "${SURICATA_PID_FILE}" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} --pidfile ${SURICATA_PID_FILE}"
fi
if [[ "${SURICATA_RULES}" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} -s ${SURICATA_RULES}"
fi
if [[ "${SURICATA_QID" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} -q ${#SURICATA_QID}"
fi
if [[ "${SURICATA_USER}" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} --user ${SURICATA_USER}"
fi
if [[ "${SURICATA_GROUP}" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} --group ${SURICATA_GROUP}"
fi
if [[ "${SURICATA_PCAP_BUFFER_SIZE}" != "" ]]
then
SURICATA_OPTIONS="${SURICATA_OPTIONS} --pcap-buffer-size ${SURICATA_PCAP_BUFFER_SIZE}"
fi
# See how we were called.
case "$1" in
start)
if [ -n "`/sbin/pidof suricata`" ]; then
echo -n "suricata: already running"
RETVAL=$?
echo
exit $RETVAL
fi
echo -n "Starting suricata: "
suricata ${SURICATA_OPTIONS} 1>${SURICATA_START-"/var/log/suricata/start.log"} 2>&1
RETVAL=$?
[ $RETVAL -eq 0 ] && success || failure
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/suricata
;;
stop)
echo -n "Stopping suricata: "
killproc suricata
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/suricata
;;
status)
status suricata
RETVAL=$?
;;
restart|reload)
$0 stop
$0 start
RETVAL=$?
;;
*)
echo "Usage: suricata {start|stop|status|restart}"
exit 1
esac
exit $RETVAL
Le fichier <path>/etc/sysconfig/suricata</path>
# suricata sysconfig file
# path to configuration file
SURICATA_CONF_FILE=/etc/suricata/suricata.yaml
# run in pcap live mode
#SURICATA_IFACE=eth0
# default log directory
SURICATA_LOG_DIR=/var/log/suricata
# write pid to this file
SURICATA_PID_FILE=/var/run/suricata.pid
# path to signature file
SURICATA_RULES=/etc/suricata/rules
# run in inline nfqueue mode
SURICATA_QID=0
# run suricata as this user after init
SURICATA_USER=suricata
# run suricata as this group after init
SURICATA_GROUP=suricata
# size of the pcap buffer value from 0 - 2147483647
#SURICATA_PCAP_BUFFER_SIZE=
Comparatif snort - suricata
| snort | suricata | |
|---|---|---|
| dépendances | facile | facile |
| installation | facile | moyen |
| configuration | moyen | moyen+ |
| règles | facile | moyen |
| Intégration avec prelude | moyen | facile |
dépendances
On trouve facilement des RPM pour CentOS. Ils sont de facture maison sur le repo b2pweb
installation
RPM créer facilement pour les deux NIDS.suricata ne dispose pas de script d'init.
configuration
La documentation de suricata est mieux faites ( au niveau de l'index ), mais celle de snort est énorme.
règles
Les règles snort (officielles ou emerging ) ne sont pas supportées à 100% par suricata. Les deux softs ont un système de mise à jour des règles officielles via oinkmaster.
intégration dans prelude
La conf par défaut de suricata contient toutes les entrées nécessaires ( en commentaire ), alors qu'il faut fouiller dans la doc et les wiki pour que snort puisse être une sonde de prelude.
Les deux NIDS ont des besoins similaires :
- écouter l'intégralité du réseau, ce qui fait que le déploiement sur la plateforme publique ne pourra que se cantonner au LAN.
- machine dédiée
- carte réseau dédiée sinon les sniffeurs ne détectent rien du tout.
Configuration de la carte réseau dédiée
DEVICE=eth1 BOOTPROTO=static ONBOOT=yes HWADDR=52:54:00:12:34:58
Comme on le constate, la carte est activée au boot, avec une adresse statique mais non renseignée. En fait elle va prendre l'adresse 0.0.0.0 MASK 0.0.0.0Elle est invisible sur le réseau et peut capturer tout le trafic réseau qui est routé sur la branche réseau ( donc le trafic du switch ou de l'hôte dans le cas de VM )
Problèmes connus
Prelude
Une sonde lancé avec un utilisateur différent de root n'envoie pas de heartbeat à prelude.
Ex : suricata est lancé avec l'utilisateur suricata et le groupe suricata.
Il faut vérifier que la sonde a été enregistrée avec les droit de l'utilisateur actuel.
Sinon réinscrire la sonde ( prelude détecte que c'est juste un changement d'uid et de gid )
Mais il peut arriver que le premier lancement de la sonde soit fait en tant que root, et il faut donc fixer les droits du répertoire spool de prélude ( /var/spool/prelude/suricata ).
# prelude-admin chown suricata --uid suricata --gid suricata
Suricata / snort
La sonde ne détecte rien du tout :
affecter une adresse IP ( non attribuée dans le plan IP de préférence
)
ifconfig eth1 inet 192.168.0.131 netmask 255.255.255.0 -promisc
repassé en mode sniffer.
ifconfig eth1 inet 0.0.0.0 promisc
La commande lancée depuis un hôte quelconque du réseau devrait maintenant être détectée.
nmap -PN 192.168.0.130