TP Détection d'intrusions (Suricata)
Introduction à Suricata
Suricata est un système de détection d’intrusion (IDS) et de prévention d’intrusion (IPS) open-source conçu pour détecter et prévenir les cybermenaces en temps réel. C’est un outil efficace et flexible qui peut être utilisé pour surveiller le trafic réseau et identifier les activités malveillantes, telles que les attaques réseau, les violations de données et les infections par des logiciels malveillants. Suricata utilise une combinaison de techniques de détection basées sur les signatures et les anomalies pour identifier les menaces, et il peut être configuré pour alerter les administrateurs et prendre des mesures pour atténuer les menaces identifiées.
Préparation du TP
1. Verification de la configuration réseau des VMs
A. Adresses IP:
L’exécution de la commande $ ip -4 addr show | grep inet
sur les différentes machines donne les résultats suivants.
- Sous la machine
server
: - Sous la machine
backtrack
: - Sous la machine
suricata
:
B. Tables de routage:
L’execution de la commande $ ip route
sur les différentes machines donne les résultats suivante.
- Sous la machine
server
: - Sous la machine
backtrack
: - Sous la machine
suricata
:
Et sur un ipconfig /all
sur mon ordinateur (hôte windows):
Ce qui correspond à cette image:
2. Initialisation
- La configuration du réseau est faite à l’étape précédente.
- Le machine
backtrack
peut bien communiquer avecserver
. - Suricata is dead and we killed him
- On utilise
nano
pour configurer suricata afin d’activer la sauvegarde des paquets avec - On execute
$ suricata /etc/suricata/suricata.yaml -i eth0
pour lancer suricata en mode capture live sur l’interfaceeth0
. on execute$ ping 192.168.5.2
depuis la machinebacktrack
. Un nouveau fichier pcap apprait. On utilisewireshark
pour le lire:$ wireshark /var/log/suricata/log.pcap.1671321732
. On observe un échangeecho
etreply
du protocolICMP
entre les deux machines. On capture aussi le requêtesARP
trouver les addresses IP de la gateway (machinesuricata
) et la machineserver
.
Fonctions NIDS (Network-based Intrusion Detection System)
Le réseau à surveiller est DMZ, où machine server
est connectée. Les attaques sont initiées depuis le réseau WAN, où la machine backtrack
est connectée.
1. Détection de balayage de ports
A. Mise à jour de règles
Mise à jour des sources: $ suricata-update update-sources
Mise à jour la base de signatures de suricata: $ suricata-update
Les règles disponibles listés ci-dessous:
Activation de l’ensemble des règles open-source Emerging Threats
: $ suricata-update enable-source et/open && suricata-update
Les règles sont écrites dans le fichier /var/lib/suricata/rules/suricata.rules
. Dans le fichier de configuration /etc/suricata/suricata.yaml
, on prend en compte ce dernier: Je ne suis pas fan de modifier les paramètres par défault mais j’ai été motivé par cette PR. (askip suricata et suricata-update n’étaient pas installés ensemble)
B. nmap
On lance $ nmap 192.168.5.2
depuis la machine backtrack
. Regardons le contenu du fichier de log /var/log/suricata/fast.log
, et on remarque:
Suricata a détecté le scan par nmap. Voici quelques signatures mis en jeux sont:
2100469, 2009583, 2009582, 200537, 200545, 2009584, …
L’astuce est de regarder la préfixe que Suricata ajoute sur chaque ligne d’alerte: C’est l’id de la signature (sid) qui l’a produite.
On peut lire la règle qui a produit (par exemple) la deuxième alerte: Cette règle produit une alerte pour toute connection TCP depuis $EXTERNAL_NET
vers $HOME_NET
, quelque soit les ports et produit le message ET SCAN NMAP -sS window 3072
si quelques conditions conditions sur l’entête TCP sont vérifiées. Ces conditions sont plus explicités dans la documentation de règles de Suricata, précisément Header keywords et Thresholding keywords.
2. Limites de la détection par signature
Exemple d’une signature
Cette signature est censée detecter les activité de minage de crypto-monnaies. Elle crée une alert sur toute méthode POST du protocole HTTP depuis le $HOME_NET
vers $EXTERNAL_NET
quelque soit les ports si elle définit le custom header X-Mining-Extensions
.
Déclenchement intentionnel de l’alerte
On utilise netcat pour écouter une connection HTTP sur la machine backtrack
et envoie une requête POST avec le header malveillant depuis server
.
Sur la machine suricata
, 3 alertes sont générées dont deux liées à curl et une à notre header malveillant. Selon cette page sur Bitcoin Wikipedia, le serveur subit une instance de cryptojacking. C’est est une forme de piratage qui consiste à utiliser la puissance de calcul de l’ordinateur d’une personne sans son consentement pour extraire des cryptomonnaies.
3. Écriture de signature
Vérification du fonctionnement du serveur
On lance le serveur depuis la machine server
: Puis on cherche la page index.html
en utilisant curl: => ça fonctionne bien .
Exploitation de la vulnerabilité “Directory Traversal”
Le serveur envoie les pages situées dans /usr/local/httpd/buggyhttp/html
. Grâce a cette vulnerabilité, si on cherche la page ../../../../../etc/shadow
on sera sur le chemin /etc/shadow
du fichier des mots de passes. Comme le serveur s’éxecute avec les droits root, il aura accès au fichier en mode lecture et on pourra le leaker.
Détection du vol du fichier /etc/shadow
On utilise une règle simple: si la route contient /etc/shadow
on alerte. Elle est efficace parce que eventuellement tous les chemins mènent à rome /etc/shadow
en présence de cette vulnerabilité. On ajoute
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"Password file leak!"; content:"/etc/shadow";sid:1000001;)
à /var/lib/suricata/rules/suricata.rules
.
On relance suricata, on effectue la même requête pour cherche le fichier des mot de passes et on regarde le ficher des alertes:
Qui correspond à la signature qu’on vient d’ajouter (look at the sid
).
Amélioration de la règle
- Une classe d’attaque pertinente:
classtype: successful-recon-limited;
. - Je pense qu’il n’y a pas besoin de modifier le flux
$EXTERNAL_NET any -> $HOME_NET any
- On peut le restreindre le flux à
flow:established, to_server;
. - On ajoute
http.uri
après le content pour la précision. - Finalement pourra aussi préciser le port du serveur
buggyhttp
mais ça devient trop spécifique.
Ceci produit la règle suivante:
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"Password file leak!"; flow: established, to_server; classtype: successful-recon-limited; content:"/etc/shadow"; http_uri; sid:1000001;)
Maintenant regardons si la signature marche encore: => Et oui.
Dans mon cas, /etc/./shadow
et /etc/python/../shadow
ont généré une alerte qui correspond à la signature que je viens d’écrire. Si ça n’avait pas marché, j’aurais dit:
/etc/./shadow
correspond au même fichier que/etc/shadow
mais il n’est pas reconnu par l’expression dans la signature. Pour ça il faudra utiliser une expression plus intelligente qui tient en compte l’expressions des chemins de linux.
Après lecture de la documentation de Suricata relative au protocole HTTP. Apparement cet avantage vient de la précision http.uri
qui normalize le chemin en contraite de http.uri.raw
ou si on ne précise pas du tout.
Amélioration de la règle (continued)
Le serveur apache n’est pas vulnerable à Directory Traversal
. On ne reçoit plus le contenu de /etc/shadow
mais Suricata continue à générer l’alerte (nouveau port). C’est une fausse alerte, un faux positif, une perte de temps, etc…
On peut modifier la signature pour décrire un Attempted password file leak
et une crée une nouvelle signature pour générer une alerte sauf si le serveur répond avec un fichier qui contient root:
.
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"Attempted password file leak!"; flow: established, to_server; classtype: attempted-recon; content:"/etc/shadow"; http_uri; sid:1000001;)
alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"Password file leak!"; flow: established, to_client; classtype: successful-recon-limited; file_data; content:"root:"; sid:1000002;)
Cette méthode génère deux alerte quand l’attaque réussit et une seule alerte quand l’attaque échoue:
Pour corréler les deux alertes, on utilise flowbits. En place de génerer une alerte pour la tentative de vol, on met un flag steal_attempt
sur la connection TCP. Si dans la suite de cette connection, si on match la 2ème signature, ayant le flag actif donc on sait on est en train de voler le fichier des mots de passe par Directory Traversal
. Les nouvelles règles sont:
alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"Attempted password file leak!"; flow: established, to_server; classtype: attempted-recon; content:"/etc/shadow"; http_uri; flowbits:set, steal_attempt; flowbits: noalert; sid:1000001;)
alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"Password file leak!"; flow: established, to_client; classtype: successful-recon-limited; file_data; content:"root:"; flowbits:isset, steal_attempt; sid:1000002;)
Une tentative de vol ne génère plus d’alerte: c’est seulement le vol qui produit une alerte maintenant. Peut-être est-il temps de dropper ces paquets ?
Closing remarks:
Merci de nous avoir donné la chance de continuer le TP hors de classe. Pour moi c’était une chance pour explorer le sujet en profondeur.