LPCyber/tp2-idps.md
Francois Lesueur 00bcb3d3c1 tp2
2021-10-22 14:29:31 +02:00

22 KiB

TP 2 : IDPS

François Lesueur (francois.lesueur@univ-ubs.fr), avec des bouts récupérés de Sébastien Mériot

Ce TP sera réalisé dans la VM MI-LXC disponible ici. L'infrastructure déployée simule plusieurs postes dont un SI d'entreprise (firewall, DMZ, intranet, authentification centralisée, serveur de fichiers, quelques postes de travail internes de l'entreprise Target), une machine d'attaquant "isp-a-hacker" et quelques autres servant à l'intégration de l'ensemble.

Pour les curieux, le code de MI-LXC, qui sert à générer cette VM automatiquement, est disponible avec une procédure d'installation documentée ici

Vous devez vous connecter à la VM en root/root. MI-LXC est déjà installé et l'infrastructure déployée, il faut avec un terminal aller dans le dossier /root/mi-lxc. Pour démarrer l'infrastructure, tapez ./mi-lxc.py start. Durant ce TP, vous allez analyser un scénario d'attaque et travailler à sa détection par NIDS (Network IDS), HIDS (Host IDS) puis corrélation d'alertes. Les outils utilisés seront Suricata (NIDS), OSSEC (HIDS), Prelude (SIEM et corrélation).

L'architecture réseau et les petits guides de démarrage des outils à manipuler sont à retrouver dans les (nombreuses) annexes (à diagonaliser avant de démarrer, bien sûr) !

Dans la VM et sur les machines MI-LXC, vous pouvez installer des logiciels supplémentaires. Par défaut, vous avez mousepad pour éditer des fichiers de manière graphique. La VM peut être affichée en plein écran. Si cela ne fonctionne pas, il faut parfois changer la taille de fenêtre manuellement, en tirant dans l'angle inférieur droit, pour que VirtualBox détecte que le redimensionnement automatique est disponible. Il y a une case adéquate (taille d'écran automatique) dans le menu écran qui doit être cochée. Si rien ne marche, c'est parfois en redémarrant la VM que cela peut se déclencher. Mais il faut la VM en plein écran.

Cheat sheet

Voici un petit résumé des commandes dont vous aurez besoin :

Commande Description Utilisation
print Génère la cartographie du réseau ./mi-lxc.py print
attach Permet d'avoir un shell sur une machine ./mi-lxc.py attach root@target-admin
display Lance un serveur X sur la machine cible ./mi-lxc.py display target-admin

Rappel: Vous devez être dnas le répertoire mi-lxc pour exécuter ces commandes.

Analyse de l'attaque

À partir du scénario d'attaque développé dans le TP1, proposez une stratégie de détection mêlant NIDS, HIDS et corrélation. Par exemple :

  • Un NIDS (Suricata) est un IDS réseau. Il permet de détecter des motifs dans des paquets réseau
  • Un HIDS (OSSEC) est un IDS hôte. Il permet de surveiller des logs, des apparitions/modifications de fichiers
  • Un corrélateur (Prelude) permet de collecter des alertes variées vers un point unique. Il permet également d'associer des alertes qui correspondent à un même événement vu par plusieurs sondes.

Faîtes valider cette stratégie par un enseignant !

Yakafokon

Déployez cette stratégie sur le SI. Les logiciels sont pré-installés mais il faut :

  • configurer les outils
  • créer les règles adaptées (règles vides au départ) ;
  • connecter les sondes à prelude-manager ;
  • créer le script de corrélation adapté.

Une suggestion (forte) est d'écrire et tester les règles de chaque sonde indépendamment (suricata, OSSEC), sans passage par prelude-manager, via leurs fichiers de logs respectifs. Une fois que la sonde fonctionne comme souhaité, elle peut être reliée au manager. Il faut enfin vérifier que les alertes remontent bien.

Annexes

Architecture réseau

L'infrastructure réseau du SI à surveiller est la suivante :

  • router en entrée de réseau
  • ldap, dmz, intranet et filer sont des serveurs internes
  • commercial, dev et admin sont des postes clients internes
  • elle est affichable avec ./mi-lxc.py print

Les logiciels suivants sont pré-installés :

  • Suricata (router)
  • Prelude-manager (router)
  • Prelude-correlator (router)
  • Prewikka (router)
  • OSSEC (dmz)

Suricata (NIDS)

Suricata est un IDPS réseau. Il est installé sur "target-router". Sa configuration est dans /etc/suricata/suricata.yaml et nous allons utiliser le fichier de règles /etc/suricata/rules/local.rules. Vous pourrez visualiser les alertes dans le fichier de log /var/log/suricata/fast.log (tail -f /var/log/suricata/fast.log permet de suivre l'évolution des alertes).

La règle

 alert tcp 10.0.0.1 80 -> 192.168.1.0/24 111 (content:"Waldo"; msg:"Waldo's here";sid:1001;)

signifie par exemple que :

  • On étudie les paquets TCP allant de 10.0.0.1:80 vers le sous-réseau:port 192.168.1.0/24:111 (attention, les règles sont orientées et Suricata regarde uniquement les paquets allant de la partie gauche de la règle à la partie droite !)
  • Contenant la chaîne "Waldo"
  • Le log affichera "Waldo's here" s'il y a une correspondance
  • alert peut être remplacé par drop pour jeter le paquet au lieu de le journaliser
  • Le sid est un identifiant de règle, il doit être unique
  • Les règles peuvent être composées de nombreux éléments (contenu, taille, expressions régulières, etc.). Tout est ici : Règles Suricata. http_stat_code (avec un _ et non un ., attention) permet par exemple de surveiller le code de retour HTTP et threshold de gérér des seuils.

Lisez les règles présentes dans le fichier local.rules. Déclenchez la règle "COMMUNITY WEB-MISC Test Script Access" en accédant au serveur web de la DMZ (http://www.target.milxc), par ex. depuis la machine isp-a-hacker. La requête est-elle exécutée par le serveur DMZ, malgré l'alerte ?

Analysez ensuite la signature de CodeRed (un ver se propageant via une faille des serveurs web Microsoft IIS). Arrivez-vous à déclencher cette alerte ? Peut-on vraiment parler d'intrusion ou de risque ici ? Comment qualifier cette alerte ?

Pour avoir un aperçu du type de règles fournies par défaut avec Suricata, vous pouvez exécuter suricata-oinkmaster-updater qui téléchargera des listes de règles dans /etc/suricata/rules/*.rules.

Lorsque vous modifiez les règles, il faut recharger le fichier avec service suricata reload. Vous pouvez suivre l'activité de Suricata et l'absence d'erreur à l'intégration des règles dans /var/log/suricata/suricata.log.

Dans la configuration préinstallée, Suricata est en écoute seulement (donc "IDS" mais pas "IPS"). D'autres configurations de Suricata permettent de le mettre en interception. Si vous souhaitez tester Suricata en IPS, voici les étapes :

  • cp /lib/systemd/system/suricata.service /etc/systemd/system/suricata.service
  • Remplacer --af-packet par -q0 dans /etc/systemd/system/suricata.service
  • Recharger systemd systemctl daemon-reload
  • Utiliser drop au lieu de alert dans les règles
  • service suricata restart

Pour ensuite activer le passage des paquets par Suricata, il faut ajouter une décision NFQUEUE au lieu des décision ACCEPT dans les règles IPTables. Par exemple, pour faire passer par Suricata tout le trafic forwardé : iptables -I FORWARD -j NFQUEUE (attention, suricata prend des décisions définitives, le reste des règles n'est pas appelé ensuite ! Une solution plus évoluée utilisant les marques et le mode repeat de Suricata existe.)

OSSEC (HIDS)

OSSEC est un HIDS installé sur la machine "target-dmz". Il permet notamment de surveiller les logs (dont accès/refus d'accès du serveur web) et les fichiers présents sur la machine. Sa configuration se trouve dans /var/ossec/etc/ossec.conf.

Les alertes sont dans /var/ossec/logs/alerts/alerts.log. Chaque alerte contient un identifiant de règle, qui permet de retrouver la règle originale dans les fichiers /var/ossec/rules/*.xml.

syscheck

Le module syscheck est responsable de surveiller les fichiers présents pour détecter leurs modifications ou même les apparitions de nouveaux fichiers (pas activé par défaut). Il se configure dans la section <syscheck> de /var/ossec/etc/ossec.conf. Lire la doc et cette réponse de FAQ.

Sur la machine "target-dmz" les fichiers uploadés sur dokuwiki sont stockés dans /var/lib/dokuwiki/data/media. Configurez ce qu'il faut comme indiqué précédemment (une option et une règle) pour obtenir une alerte à chaque nouveau fichier sur le wiki.

Attention :

  • la règle est à ajouter impérativement dans un <group> (dans /var/ossec/rules/local_rules.xml)
  • syscheck fonctionne grâce à des scans réguliers (très lents pour ne pas impacter le système) et compare les résultats avec la base du précédent scan. Il faut donc attendre que le scan soit passé et cela prend un certain temps... On peut le surveiller dans /var/ossec/logs/ossec.log
    • début du scan : "INFO: Starting syscheck database (pre-scan)."
    • fin du scan (peut prendre plusieurs minutes !) : "INFO: Finished creating syscheck database (pre-scan completed)."
  • comme le processus est long, limitez les dossiers à surveiller au strict minimum (désactivez les dossiers par défaut, mettez juste le dossier dokuwiki)

Pour tester vous aurez besoin du mot de passe de l'utilisateur admin sur le wiki (cf. TP1) et d'utiliser le "Media Manager".

Plutôt qu'attendre on peut déclencher un re-scan du système avec /var/ossec/bin/agent_control -r -u 000, mais attention il s'écoule toujours plusieurs (5 ?) minutes entre les scans.

logs

Il est aussi possible d'analyser les logs : doc

Relancez depuis la machine "isp-a-hacker" le bruteforce sur le mot de passe de l'admin du wiki avec la commande : python3 tp/intrusion/dokuwiki.py www.target.milxc et observez les alertes OSSEC.

Mise en place d'un proxy HTTP

Installation

Un proxy HTTP filtrant a l'intérêt de permettre de contrôler de manière fine le contenu accessible par les utilisateurs d'un réseau. Cette technique a l'avantage d'être relativement facile à mettre en place et c'est ce que nous allons voir durant ce TP.

Nous allons utiliser un proxy très connu du nom de squid avec son extension squid-guard afin de mettre en place un contrôle du flux HTTP. Pour commencer, nous allons les installer sur la machine "target-router".

apt-get update
apt-get install -y squid squidguard

Vous pouvez vérifier la bonne installation de squid en forgeant une requête HTTP en utilisant le proxy local sur le port TCP/3128 ce qui vous donnera une réponse similaire à celle-ci :

# curl -I -x localhost:3128 https://www.insa-lyon.fr/
HTTP/1.1 200 Connection established

HTTP/2 200
date: Sun, 02 May 2021 11:43:13 GMT
server: Apache
vary: User-Agent,Accept-Encoding
last-modified: Sun, 02 May 2021 02:01:20 GMT
accept-ranges: bytes
content-length: 40774
x-content-type-options: nosniff
x-frame-options: sameorigin
cache-control: max-age=0, no-cache, no-store, must-revalidate
pragma: no-cache
expires: Mon, 29 Oct 1923 20:30:00 GMT
content-type: text/html; charset=UTF-8

Vous pouvez remarquez les 2 codes HTTP 200 qui sont remontés, le premier indiquant la bonne connexion au proxy, la seconde étant la réponse du serveur distant interrogé (insa-lyon.fr).

Configuration du proxy

Par défaut, squid joue uniquement le rôle de proxy et permet notamment de mettre en cache des ressources. C'était notamment très utile lorsqu'une entreprise disposait d'une connectivité limitée afin de réduire la bande passante consacrée à la navigation Internet. De nos jours, les proxies ont plutôt un rôle destiné à la sécurité des réseaux. Pour cela, nous allons devons indiquer à squid d'utiliser le module squid-guard dès lors qu'une URL est visitée afin de savoir s'il faut rediriger l'utilisateur quelque part. Pour ce faire, nous allons ajouter le paramètre de configuration url_rewrite_program dans la configuration située dans /etc/squid/squid.conf tel que :

url_rewrite_program /usr/bin/squidGuard -c /etc/squidguard/squidGuard.conf

Il faut également autoriser les IPs du réseau à se connecter car, par défaut, squid n'autorise que localhost. A la ligne 1408, modifiez la configuration pour ajouter une directive autorisant la sous-réseau de l'entreprise "target" à utiliser le proxy afin d'avoir quelque chose ressemblant à ceci:

acl allowed_ips src 100.80.0.0/16

http_access allow localhost
http_access allow allowed_ips

# And finally deny all other access to this proxy
http_access deny all

Puis on relance squid pour prendre en compte les modifications.

# service squid restart
# service squid status
● squid.service - Squid Web Proxy Server
   Loaded: loaded (/lib/systemd/system/squid.service; enabled; vendor preset: en
   Active: active (running) since Sun 2021-05-02 13:00:17 CEST; 10s ago
     Docs: man:squid(8)
  Process: 1798 ExecStartPre=/usr/sbin/squid --foreground -z (code=exited, statu
  Process: 1801 ExecStart=/usr/sbin/squid -sYC (code=exited, status=0/SUCCESS)
 Main PID: 1802 (squid)
    Tasks: 4 (limit: 3556)
   Memory: 16.6M

La configuration par défaut de squid-guard n'est pas correcte et interdit tout trafic. Ouvrez le fichier /etc/squidguard/squidGuard.conf. Celui-ci est organisé en 4 grandes catégories:

  • Définition d'horaires d'activité: il est possible d'autoriser le trafic uniquement sur des plages horaires configurées par exemple pour interdire le trafic web le week-end lorsque personne n'est au bureau.
  • Définition de règles en fonction des IPs sources.
  • Définition de règles en fonction des sites de destination.
  • Les ACLs qui sont une combinaison de toutes les règles précédemment définies.

Nous allons nous limiter à un cas simple: interdire l'accès au site example.com au développeur et lui interdire de naviguer sur le web le week-end. Lorsqu'il enfreindra cette politique, il sera redirigé sur perdu.com. L'admin au contraire pourra faire tout ce qu'il souhaite quand il le souhaite.

Dans un premier temps, nous allons créer un fichier contenant les domaines que nous souhaitons interdire. Créez un nouveau fichier /etc/squidguard/interdit-domains.txt et sur la première ligne, ajoutez example.com. Maintenant, reprenez le fichier /etc/squidguard/squidGuard.conf. Modifiez la variable dbhome afin d'indiquer à squid-guard de charger le fichier que nous venons de créer au bon endroit: dbhome /etc/squidguard/.

Au niveau de la définition des IPs sources, nous allons configurer uniquement 2 groupes:

  • admin composé du routeur et de la machine de l'administrateur réseau
  • user composé des machines du développeur et du commercial. Puisque nous souhaitons contraindre les plages horaires, n'oubliez pas la directive within.

Nous n'utilisons pas ici d'utilisateur. Sachez que squid peut demander à ce que les utilisateurs s'authentifient afin de mieux contrôler ce que font les utilisateurs et de définir des politiques en se basant sur les rôles fonctionnels de chacun plutôt qu'en se basant sur le plan d'adressage.

Concernant les destinations, nous allons créer une nouvelle classe intitulée interdit en indiquant à squid-guard de lire la liste des domaines dans le fichier "interdit-domains.txt" précédemment créé.

Pour finir, nous devons configurer les ACLs. Celles-ci sont toujours composées d'un cas par défault. Nous aurons donc des ACLs en 3 parties:

  • Le groupe admin n'a aucune restriction (pass any)
  • Le groupe users, s'il consulte des sites identifiés dans good, mais pas dans interdit, alors pas de restriction. Sinon, redirection vers http://perdu.com.
  • Par défault, interdiction de naviguer sur internet et redirection systématique vers http://perdu.com.

Quand vous avez terminé, sauvegardez le fichier et redémarrez squid. Pour tester, vous pouvez tester ces scénarios et voir si vous obtenez le comportement attendu:

root@mi-target-router:~# curl -x 100.80.0.1:3128 -i example.com
# Obtention du contenu example.com

root@mi-target-dev:~# curl -x 100.80.0.1:3128 -i example.com
# Obtention du contenu de perdu.com

La configuration que nous utilisons est dite transparente. Cela signifie que nous ne sommes pas redirigé vers perdu.com mais bien que le proxy nous retourne le contenu de perdu.com comme s'il s'agissant du contenu de example.com. C'est pourquoi nous travaillons uniquement en HTTP. Vous pouvez remarquer qu'en requêtant des sites en HTTPS, squid génère une erreur 503. Je vous laisse deviner pourquoi.

Configuration du navigateur

Notre proxy est en place, nous allons maintenant l'utiliser dans un navigateur. Connectez-vous en mode graphique sur la machine du développeur (./mi-lxc.py display target-dev) puis ouvrez le navigateur. Tentez de vous rendre sur example.com et constatez qu'aucun filtrage ne vous interdit de vous rendre sur le site.

A présent, ouvrez les préférences de Firefox puis dans l'onglet General, cherchez la section Network Settings. Cochez Manuel proxy configuration et entrez les informations du proxy HTTP que nous venons d'installer: 100.80.0.1 sur le port 3128. Sauvegardez puis raffraîchissez la page. Le contenu devrait être réécrit.

Il se peut que le cache de Firefox vous joue des tours. N'hésitez pas à raffraichir plusieurs fois.

Généralement, cette configuration s'opère via un fichier PAC (Proxy Auto-Configuration) qui est stocké sur le serveur proxy et qui est configuré au travers du DHCP.

Cette configuration n'est pas très sécurisée. En effet, un utilisateur peut décider facilement de contourner la politique de sécurité en supprimant l'utilisation du proxy. Comment feriez-vous pour que l'utilisation de ce proxy ne soit pas contournable ?

Prelude-manager (concentrateur)

Prelude-manager est un concentrateur d'alertes. Il utilise le format d'alerte IDMEF et Suricata et OSSEC savent lui remonter leurs alertes. Le jumelage entre le manager et les sondes est réalisé via un échange TLS SRP géré par prelude-admin.

Lors du jumelage, chaque sonde conserve un profil local (/etc/preludes/profiles/<profile>/) contenant sa configuration et son matériel cryptographique (certificat, clés). Le manager, lui, a signé le certificat (avec sa clé privée) mais ne conserve pas de liste des sondes enregistrées. prelude-admin list -l permet de lister les profils actuellement configurés sur la machine locale.

Pour jumeler une sonde au manager, il faut :

  • côté manager (router) : prelude-admin registration-server prelude-manager
  • côté sonde : prelude-admin register <profile> "idmef:w" <IP manager> --uid 0 --gid 0, avec
    • <profile> : nom du profil, suricata pour Suricata et OSSEC-DMZ pour OSSEC
    • <IP manager> : l'IP du manager

Prewikka (interface web de visualisation)

Prewikka est une application web permettant la visualisation de l'état des sondes enregistrées ainsi que des alertes. Il est installé sur la machine target-router. Il doit être démarré avec prewikka-httpd et est ensuite accessible depuis le navigateur d'un poste de travail interne (par exemple target-admin) à l'URL http://router:8000. Le compte est admin/admin (bien sûr, la première étape dans un vrai déploiement est de changer cela...).

Il faut ensuite lancer prelude-manager (sur router) : service prelude-manager start.

Par défaut, la liste des agents (les sondes), accessible dans le menu en haut à gauche, est vide. Il faut ajouter Suricata (activer prelude dans la configuration suricata /etc/suricata/suricata.yaml en y cherchant la chaîne "prelude" puis service suricata restart) puis OSSEC (activer prelude dans la configuration OSSEC /var/ossec/etc/ossec.conf en y cherchant la chaîne "prelude" puis service ossec restart).

Vous pouvez ensuite visualiser des événements. Si tout n'apparaît pas, quelques restarts de services peuvent faire tomber en marche !

Prelude-correlator (corrélation)

Jumelage avec le manager : prelude-admin register prelude-correlator "idmef:rw" 127.0.0.1 --uid 0 --gid 0 (accès read/write cette fois-ci car la corrélation nécessite la lecture des alertes remontées et l'écriture de nouvelles alertes). Puis relancer le service prelude-correlator.

Une règle de corrélation est en fait un script python. Vous trouverez un exemple dans /usr/share/doc/prelude-correlator/examples. Pour l'installer, tapez :

  • python setup.py build
  • python setup.py install

Puis dans /etc/prelude-correlator/prelude-correlator.conf, ajoutez :

[MyPlugin]
disable=false

Enfin, relancez prelude-correlator. Une documentation plus complète est disponible ici. YOLO !

Crédits : certaines parties ont été inspirées de sujets de Guillaume Hiet