LPCyber/tp2-idps.md
2021-10-23 13:17:02 +02:00

310 lines
22 KiB
Markdown

# TP 2 : IDPS
_François Lesueur ([francois.lesueur@univ-ubs.fr](mailto:francois.lesueur@univ-ubs.fr))_, avec des bouts récupérés de [Sébastien Mériot](https://github.com/PandiPanda69/edu-insa-srs/blob/main/tp3-ids.md)
Ce TP sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=a692402f-90c7-4882-a93e-7123842ca5ec). 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](https://github.com/flesueur/mi-lxc)
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), proxy HTTP 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, proxy HTTP 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 proxy HTTP (Squid) permet de contrôler les connexions HTTP sortantes
* 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](https://suricata.readthedocs.io/en/latest/rules/index.html). [`http_stat_code`](https://suricata.readthedocs.io/en/latest/rules/http-keywords.html#http-stat-code) (avec un _ et non un ., attention) permet par exemple de surveiller le code de retour HTTP et [`threshold`](https://suricata.readthedocs.io/en/latest/rules/thresholding.html) de gérér des seuils. <!-- \url{http://manual.snort.org/node32.html}) -->
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.](https://docs.mirantis.com/mcp/latest/mcp-security-best-practices/use-cases/idps-vnf/ips-mode/nfq.html))
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](https://ossec.github.io/docs/manual/syscheck/index.html) et cette réponse de [FAQ](https://www.ossec.net/docs/faq/syscheck.html#why-aren-t-new-files-creating-an-alert).
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](https://ossec.github.io/docs/manual/monitoring/index.html)
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".
```bash
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`](http://www.squid-cache.org/Doc/config/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:
```bash
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_](https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling/Proxy_Auto-Configuration_PAC_file)) 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](https://en.wikipedia.org/wiki/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
<!-- * `<UID>/<GID>` : l'uid et le gid de la sonde qui va remonter les alertes (ici 0/0 pour suricata, 1005/1005 pour OSSEC), utilisé pour poser les droits sur le matériel cryptographique généré lors du jumelage -->
Prewikka (interface web de visualisation) (non fonctionnel sur MI-LXC-v20211014, fonctionnel sur MI-LXC-v1.3.1)
-----------------------------------------
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](https://www.prelude-siem.org/projects/prelude/wiki/PreludeCorrelator). YOLO !
_Crédits : certaines parties ont été inspirées de sujets de [Guillaume Hiet](http://guillaume.hiet.fr/)_