Salut à tous, aujourd’hui on va regarder ce qu’on peut faire avec l’IDS/IPS Suricata 4.1 dans Splunk. Suricata est un logiciel issu un développement « from scratch » dans le but de faire un IDS/IPS libre compatible avec les règles de Snort (tenues par Cisco). On va donc voir comment on installe Suricata 4.1 (en beta actuellement) sur une Debian 9 et ce qu’on peut faire pour le configurer et intégrer les résultats dans Splunk.
Installation Suricata 4.1 (beta)
La procédure d’installation de Suricata est très bien documenté ici et là. Je n’en reprends donc ci-dessous que les grandes lignes pour la version 4.1.
# apt-get install libpcre3 libpcre3-dbg libpcre3-dev build-essential libpcap-dev libnet1-dev libyaml-0-2 libyaml-dev pkg-config zlib1g zlib1g-dev libcap-ng-dev libcap-ng0 make libmagic-dev libjansson-dev libnss3-dev libgeoip-dev liblua5.1-dev libhiredis-dev libevent-dev libnetfilter-queue-dev libnetfilter-queue1 libnetfilter-log-dev libnetfilter-log1 libnfnetlink-dev libnfnetlink0 # curl -O https://www.openinfosecfoundation.org/download/suricata-4.1.0-beta1.tar.gz # tar xzvf suricata-4.1.0-beta1.tar.gz # cd suricata-4.1.0-beta1 # ./configure --sysconfdir=/etc/ --localstatedir=/var/ --enable-nfqueue --enable-nflog # make # make install-full #make install + rules&conf # ldconfig # suricata -h
Une fois ces opérations effectuées, il reste un peu de configuration à faire dans le fichier /etc/suricata/suricata.yaml :
# global stats configuration # Optionnel : Désactivez la fonction stats (on veut un IDS/IPS pas un soft de métrologie) stats: enabled: no # The interval field (in seconds) controls at what interval # the loggers are invoked. interval: 8 # Obligatoire : si vous protégez un réseau, le subnet en question, si vous l'installer sur un hôte seul l'adresse IP. HOME_NET: "[YourServerNetwork]" EXTERNAL_NET: "!$HOME_NET" [...] # Optionnel : désactivez l'analyse des flux qui log un volume important de données. #- flow [...] # Optionnel : désactiver l'output de stats (on veut un IDS pas un équipement de métrologie réseaux) #- stats: # totals: yes # stats for all threads merged together # threads: no # per thread stats # deltas: no # include delta values host-os-policy: # Optionnel : indiquez le type de machine protégées dans chaque subnet. linux: [YourServerIP] [...]
Vous pouvez alors contrôler que le programme est bien installé et fonctionne correctement avec la configuration via la commande suivante :
suricata -c /etc/suricata/suricata.yaml -i enp0s20f0 --init-errors-fatal
Mode IPS inline
Dans ce TP le mode IDS ne m’intéresse pas, je vais configurer Suricata en tant qu’IPS. Plusieurs raisons à cela :
- Il sait le faire !
- Je n’ai pas un réseau de 2500 machines derrière Suricata, le risque de coupure de service ne me concerne pas vraiment.
- Le mode IDS écoute l’ensemble du trafic et pas seulement celui autorisé par le firewall. Du coup, Suricata se retrouve à analyser du trafic qui n’atteindra jamais le serveur.
Alors que le mode IPS permet de passer uniquement le trafic souhaité à Suricata. Ce qui est bien mieux pour les performances de votre serveur et bien plus logique vu les différents degrés d’analyses entre un IPS et un firewall.
Pour passer Suricata en mode IPS (doc) allez dans /etc/suricata/suricata.yaml et modifier la ligne suivante pour activer la « queue » iptables :
nfq: mode: accept fail-open: yes # optionnel, si suricata tombe on laisse passer les paquets pour éviter la rupture de service
Du coup, il vous faudra aussi modifier vos règles iptables pour passer les paquets à Suricata plutôt que d’accepter les paquets. Si vous n’êtes pas au point sur iptables, je vous invite à consulter mes articles précédents sur le sujet (configuration, logs et Splunk). Par rapport, à ces TP il vous faudra donc modifier la règle que j’avais nommée LOG_N_ACCEPT et remplacer toutes ses occurrences par une nouvelle chaine LOG_N_IPS-ACCEPT. Cette file LOG_N_IPS-ACCEPT est définie par les lignes suivantes dans votre sauvegarde des règles iptables dans la table filter :
-A LOG_N_IPS-ACCEPT -j LOG --log-prefix "ACTION=ACCEPT-INPUT " -A LOG_N_IPS-ACCEPT -j NFQUEUE -A LOG_N_IPS-ACCEPT -j ACCEPT
Et n’oubliez pas de faire la même chose pour IPv6, iptables utilisant deux jeux de règles distincts pour ipv4 et ipv6.
Passage de Suricata en service Systemd
Avant de démarrer Suricata pour de bon, on va le configurer comme un service Systemd pour gérer Suricata un peu plus intelligemment que de le faire tourner dans un screen… Si vous ne connaissez pas Systemd je vous invite à lire la documentation suivante :
- https://wiki.ubuntu.com/SystemdForUpstartUsers – Aperçu global des commandes systemctl.
- https://wiki.archlinux.org/index.php/Systemd – Documentation globale très complète.
- https://www.freedesktop.org/software/systemd/man/systemd.service.html – Documentation de référence service.
- https://www.freedesktop.org/software/systemd/man/systemd.unit.html – Documentation de référence unit.
TLDR : créez et éditez le fichier /lib/systemd/system/suricata.service avec la configuration ci-dessous :
[Unit] Description=Suricata Intrusion Detection Service After=network.target Requires=network.target Documentation=man:suricata(8) man:suricatasc(8) Documentation=https://redmine.openinfosecfoundation.org/projects/suricata/wiki [Service] Type=forking PIDFile=/var/run/suricata.pid Environment=CFG=/etc/suricata/suricata.yaml PID=/var/run/suricata.pid ExecStart=/usr/local/bin/suricata --pidfile $PID -c $CFG -D -q 0 #IPS vs IDS: "-q 0" = inline-IPS-mode || "-i <ifname>" = monitor-IDS mode ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill $MAINPID Restart=always PrivateTmp=yes InaccessibleDirectories=/home /root ReadOnlyDirectories=/boot /usr /etc [Install] WantedBy=multi-user.target
Pour activer le démarrage automatique de Suricata avec le serveur exécuter la commande suivante :
systemctl enable suricata.service
Puis pour démarrer et vérifier qu’il tourne bien :
systemctl start suricata systemctl status suricata.service
Logrotate
Je vous conseille aussi de mettre en place un logrotate sur le fichier eve.json qui comme iptables peut vite vous consommer pas mal d’espace disque si votre serveur reçoit un peu de trafic. Il suffit de créer le fichier /etc/logrotate.d/suricata suivant à adapter selon vos besoins pour cela.
/var/log/suricata/*.log /var/log/suricata/*.json { rotate 7 daily create missingok notifempty delaycompress compress sharedscripts postrotate systemctl restart suricata > /dev/null endscript }
Mise à jour des règles de détection
Comme un antivirus, Suricata a besoin de mettre à jour ses règles de détection régulièrement. Le nerf de la guerre après c’est aussi de trouver les sources de règles pertinentes pour votre serveur, réseaux, entreprises. Et là ça dépend de ce que vous protégerez techniquement avec Suricata (frontend web, réseau d’entreprise Windows, infrastructure.). Je vous propose deux techniques ci-dessous, sachant que la seconde est plus simple mais n’intègre pas les règles Snort en l’état. A vous de voir ce que vous préférez mettre en place.
A la main :
Pour cette manière, j’ai configuré les règles Emmerging Threat (i.e. native Suricata) et Snort et je vous propose le petit script ci-dessous pour récupérer les mises à jour à l’aide d’une crontab. Pour les règles Snort vous devrez au préalable vous inscrire chez Snort pour obtenir un oinkcode. Le logiciel oinkmaster permet à priori aussi de mettre à jour automatiquement vos règles, enfin ça tiens aussi dans un script de 10 lignes :
#/bin/bash # Get signature curl -o /tmp/emerging.rules.tar.gz https://rules.emergingthreats.net/open/suricata/emerging.rules.tar.gz wget --directory-prefix=/tmp https://www.snort.org/downloads/community/snort3-community-rules.tar.gz -O /tmp/snort3-community-rules.tar.gz wget https://www.snort.org/rules/snortrules-snapshot-3000.tar.gz?oinkcode=<votreoinkcodeàcréersibesoin> -O /tmp/snortrules-snapshot-3000.tar.gz # unzip signature tar -xzf /tmp/emerging.rules.tar.gz -C /tmp tar -xzf /tmp/snort3-community-rules.tar.gz -C /tmp tar -xzf /tmp/snortrules-snapshot-3000.tar.gz -C /tmp # instal signature mv /tmp/snort3-community-rules/snort3-community.rules /tmp/rules cp -f /tmp/rules/* /etc/suricata/rules/ # Cleanup your mess rm -Rf /tmp/snort3-community-rules /tmp/rules /tmp/emerging.rules.tar.gz /tmp/snort3-community-rules.tar.gz /tmp/so_rules /tmp/etc /tmp/snortrules-snapshot-3000.tar.gz # reload suricata rules suricatasc -c reload-rules # done
Notez au passage que ce script n’active pas les règles Snort (qu’il met pourtant à jour), pour cela il vous faudra ajouter chaque fichier .rules de Snort qui vous intéresse dans le fichier de configuration /etc/suricata/suricata.yaml dans la section rule-files, exemple :
- snort3-community.rules - snort3-exploit-kit.rules - snort3-file-executable.rules #- snort3-file-flash.rules [...]
Quelques détails sur les règles Snort ici.
Avec la commande suricata-update
Le script ci-dessus, fonctionnel en 4.1 et 4.0, ne prend pas en compte l’existence de la nouvelle commande suricata–update dans la 4.1 (uniquement) qui fait les mise à jours pour vous comme une grande ! Pour l’utiliser, il vous suffira d’installer les paquets suivants :
apt-get install python-yaml python-pip
Puis à mettre à jour la commande avec pip :
pip install --pre --upgrade suricata-update
Et mettre à jour votre configurations /etc/suricata/suricata.yaml pour remplacer la section « rule » par :
default-rule-path: /var/lib/suricata/rules rule-files: - suricata.rules
Et lancer la mise à jour des règles avec :
suricata-update
Cette commande à le bon goût de vous proposer d’intégrer nativement d’autres jeu de règles que vous pouvez aller chercher avec la commande suivante :
suricata-update update-sources
Pour lister les sources de règles disponibles :
suricata-update list-sources
Pour lister les règles actives :
suricata-update list-enabled-sources
Pour activer un jeu de règles :
suricata-update enable-source <RuleName(exemple:"oisf/trafficid")>
Si vous souhaitez gérer finement les règles activées, je vous invite à jeter un œil à la doc ici. Et pour finir, un petit restart ne faisant jamais de mal après une mise à jour des règles :
systemctl restart suricata.service
Suricata avec Splunk.
Intégration des logs
Bon c’est bien tout ça, mais si on regardait un peu ce qu’il crache comme informations Suricata. Par défaut, 2 fichiers sont alimentés par l’IPS :
- /var/log/suricata/fast.log ; et
- /var/log/suricata/eve.json.
Le premier est un fichier human readable (ou « grepable » pour les linuxiens) : un événement égal une ligne de log, assez synthétique mais un peu relou à intégrer dans Splunk vu que ce n’est pas trop structuré comme donnée. Le second donne les même informations en JSON, beaucoup plus simple à donner à manger à Splunk, mais à peu près deux fois plus verbeux.
On va donc utiliser le format JSON du fichier eve.json pour intégrer Suricata 4.1 dans Splunk. On a déjà vu dans le TP Splunk et Nginx comment faire Je vous laisse refaire un tour si besoin, il suffit juste de sélectionner le format JSON et le fichier /var/log/suricata/eve.json et de créer un nouvel index pour Suricata. Notez que je ne suis pas du tout les préconisation Splunk sur le sujet car l’application TA proposée par Splunk me paraît toute moisie et m’a fait planter Splunk. Prochain TP refaire une application TA pour Suricata ?
Recherches sur les logs Suricata 4.1 dans Splunk
On y arrive ! Alors j’ai fait quelques tests avec Splunk et Suricata en mode IDS et en mode IPS. Le mode IPS derrière le firewall est beaucoup plus pertinent car il analyse uniquement le trafic réel et pas tout ce qui se fait dropper par le firewall (qu’on analyse déjà avec les logs ipatbles). La contrepartie c’est que même après plus d’un mois de log suricata, je manque un peu de données pertinentes pour faire un « joli dashboard ».
Pour vous faire un dessin, la moitié des alertes qu’il remontent concerne les signatures suivantes :
- TOR Known Tor Exit Node – OK j’ai des gens qui utilise tor qui consulte le site ; pas passionnant comme info…
- COMPROMISED Known Compromised or Hostile Host Traffic group ou CINS Active Threat Intelligence Poor Reputation IP group- Il y’a des IP qui ont mauvaise réputation qui me scannent, à l’ouest rien de nouveau…
- SCAN Potential SSH Scan ; Waouh, je ne m’en doutais pas entre les logs iptables et fail2ban…tu m’en diras tant Suricata…
Bon après je joue le blasé mais faut admettre que c’est un peu overkill de ma part d’installer Suricata sur un petit serveur comme le mien avec un misérable blog ranké 3,689,581 par Alexa… ^^
Après il y a quand même des recherches un peu rigolotes que j’ai pu faire avec les logs Suricata j’ai :
#les IP qui déclenche le plus d'attaque index=suricata | stats count by src_ip | sort - count | top 50 # les ports les plus étudié index=suricata | top dest_port # A quelles heures/jour de la semaine ont plus lieu les attaques (en moyenne) : par signature. index=suricata | chart count by date_hour | date_wday | alert.signature # détection Splunk "automatique" des scans ssh atypique index=suricata | anomalies | search alert.signature="ET SCAN Potential SSH Scan" # comparaison croisée des IP qui déclenchent le plus d'alertes de scan SSH avec le nombre de logs iptables détecté dans l'heure. index=suricata alert.signature="ET SCAN Potential SSH Scan" | top src_ip | map search="search index=iptables src_ip=$src_ip$ | transaction maxspan=1h" | stats count by SRC, FLAGS # Les alertes par catégorie. index=suricata | stats count by alert.category
Bref ça peut vous donner un dashboard comme celui-ci :
Conclusion
Bon voilà c’est tout pour Suricata 4.1 dans Splunk. Un article qui sent bon la savane en tout cas et qui combiné avec les logs nginx et iptables de mes articles précédents peut commencer à bien ressembler à une supervision de sécurité sympa de vos sites web… Et complètement overkill pour mon cas… parce que je peux le faire, hein…
Pour la suite des aventures, il y a plein de log que l’on peut exploiter avec Splunk quelques pistes qu’il faut que je regarde :
- FTP avec vsftpd ;
- mail avec postfix ;
- fail2ban ;
- PHP ;
- MySQL ;
Autant vous dire que ce n’est pas les idées à la con qui me manquent, si vous avez une préférence, à vous les commentaires !
Je vous remercie monsieur
Avec plaisir ! (et le « monsieur » est un peu superflu là quand même… ^^).
super tuto, merci !