/* Lab */

TP Détection d'intrusions (Suricata)

Dec 25, 2022 · 15 min read

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.

B. Tables de routage:

L’execution de la commande $ ip route sur les différentes machines donne les résultats suivante.

Et sur un ipconfig /all sur mon ordinateur (hôte windows):

Ce qui correspond à cette image:

2. Initialisation

  1. La configuration du réseau est faite à l’étape précédente.
  2. Le machine backtrack peut bien communiquer avec server.
  3. Suricata is dead and we killed him
  4. On utilise nano pour configurer suricata afin d’activer la sauvegarde des paquets avec
  5. On execute $ suricata /etc/suricata/suricata.yaml -i eth0 pour lancer suricata en mode capture live sur l’interface eth0. on execute $ ping 192.168.5.2 depuis la machine backtrack. Un nouveau fichier pcap apprait. On utilise wireshark pour le lire: $ wireshark /var/log/suricata/log.pcap.1671321732. On observe un échange echo et reply du protocol ICMP entre les deux machines. On capture aussi le requêtes ARP trouver les addresses IP de la gateway (machine suricata) et la machine server.

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

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.