Vous êtes sur la page 1sur 12

M4210

Infrastructures de sécurité
Sami Evangelista
IUT de Villetaneuse
Département Réseaux et Télécommunications
2019-2020
http://www.lipn.univ-paris13.fr/~evangelista/cours/M4210

Table des matières


TP 1 — Scan de réseaux avec nmap 2

TP 2 — Réalisation d’une DMZ avec iptables 4

TP 3 — Forger des paquets avec scapy 5

TP 4 — IDS et IPS 9

Ce document est mis à disposition selon les termes de la licence Creative Commons “Attribution - Pas
d’utilisation commerciale - Partage dans les mêmes conditions 4.0 International”.
TP 1 — S CAN DE RÉSEAUX AVEC NMAP 2019-2020 M4210 — I NFRASTRUCTURES DE SÉCURITÉ

TP 1 — Scan de réseaux avec nmap

L’objectif de ce TP est d’étudier les différentes possibilités de l’outil de balayage réseau nmap et le fonctionnement
des opérations de balayage usuels. Le TP se fera sous marionnet.

Exercice 1 — Création du réseau


Créer un réseau (10.0.0.0/24) composé de trois machines reliées à un switch :
— nmap (10.0.0.1) — la machine sur laquelle nous utiliserons nmap ;
— cible (10.0.0.2) — la machine qui sera scannée par nmap ;
— machin (10.0.0.3) — une machine qui servira uniquement à illustrer le fonctionnement de la découverte d’hôtes.
À la création de nmap, augmenter la mémoire disponible à 512 Mo, pour que wireshark s’exécute plus rapidement.
Pour nos tests de balayage nous utiliserons les ports 22 (ssh) et 80 (http) de la machine cible. Le premier sera ouvert
et le second fermé. Par conséquent, sur la machine cible, le service ssh devra être démarré et le service apache2 arrêté.
Pour rappel, pour arrêter, démarrer ou vérifier le statut d’un service :
# /etc/init.d/<nom-du-service> start
# /etc/init.d/<nom-du-service> stop
# /etc/init.d/<nom-du-service> status

(La commande systemctl n’est pas disponible sur les machines virtuelles de marionnet qui sont des debian utilisant le
système d’initialisation SysV init (plutôt que systemd qui est maintenant le système utilisé par la plupart des distributions).)
Dans la suite, tous les tests nmap devront être effectués en root. De plus, on utilisera systématiquement l’option -n qui
désactive la résolution inverse. Celle-ci permet en temps normal d’afficher les noms des machines plutôt que leurs IPs.
Comme la machine nmap n’a aucun moyen d’effectuer de résolution inverse, les tests nmap sont ralentis.

Exercice 2 — Découverte d’hôtes


L’objectif de cet exercice est d’étudier les possibilités de découverte d’hôte offerte par nmap. On utilisera toujours
dans cet exercice l’option -sP qui permet de sauter la deuxième étape de scan pour n’effectuer que la découverte (et éviter
de capturer trop de paquets).
1 Tout en capturant les paquets sur nmap, lancer le scan suivant :
# nmap -n -sP 10.0.0.0/24

Q. 2.1 Qu’affiche cette commande ?


Q. 2.2 En analysant le trafic capturé, expliquer le fonctionnement de cette méthode de découverte.
Q. 2.3 Pourquoi ICMP n’est-il pas utilisé dans ce cas ?
Q. 2.4 Cette méthode est la méthode par défaut pour découvrir les hôtes sur le même réseau local mais elle ne peut pas
être utilisée pour découvrir les hôtes d’un autre réseau. Pourquoi ?

Pour “simuler” une découverte sur un autre réseau nous utiliserons maintenant l’option --send-ip. Nmap fera alors
comme si les cibles ne sont pas sur son réseau.
2 Tout en capturant les paquets sur nmap, lancer les deux scans suivants :
# nmap -n -sP -PE --send-ip 10.0.0.2
# nmap -n -sP -PT1234 --send-ip 10.0.0.2

Q. 2.5 En analysant le trafic capturé, expliquer le fonctionnement de ces deux méthodes (-PE et -PT) de découverte.

Exercice 3 — Balayages SYN et connect


Lorsque nmap est lancé avec des droits permettant d’envoyer des paquets bruts (paquets créés de toute pièce avec des
champs IP, TCP, UDP, . . . , qui ne sont pas fixés par le système mais par le processus) sur le réseau (p.ex., par root), le
balayage par défaut est de type SYN (option -sS). Nous allons d’abord étudier le fonctionnement de ce type de balayage.
1 En root : lancer un balayage SYN sur le port 80 de la machine cible.
2 Refaire le test avec le port 22.
Q. 3.1 Expliquer le fonctionnement du balayage SYN et les résultats observés.

Si l’utilisateur ne possède pas ce droit (la possibilité d’envoyer des paquets bruts), c’est le balayage de type connect
(option -sT) qui est effectué par défaut.
3 Refaire les tests précédents en activant l’option -sT à la place de -sS.

Page 2 / 12
M4210 — I NFRASTRUCTURES DE SÉCURITÉ 2019-2020 TP 1 — S CAN DE RÉSEAUX AVEC NMAP

Q. 3.2 Quelle différence observe-t-on par rapport au balayage SYN dans le cas d’un port ouvert ?

Le balayage SYN ne respecte pas la phase de connexion TCP classique (poignée de mains en trois temps). Or,
lorsqu’un processus n’a pas le droit d’envoyer des paquets bruts, il doit faire appel à la primitive connect du système
d’exploitation (qui, elle, effectue une connexion propre, en trois temps) comme c’est le cas avec le balayage connect.
D’où la nécessité d’avoir ce droit avec le balayage SYN.

Q. 3.3 Quel avantage il y-a-t-il pour un attaquant d’utiliser le balayage SYN (par rapport au balayage connect) ?

Exercice 4 — Balayages Xmas, Fin et Null


Ces trois types de balayages, très similiaires dans leur fonctionnement requièrent également le droit d’envoyer des
paquets bruts. Ils jouent sur les différents bits de contrôle TCP (SYN, ACK, FIN, . . . ) et exploitent une faille de conception
de TCP (dans la RFC793, voir le manuel de nmap).
Tester les trois balayages (option -sX pour Xmas, -sF pour FIN, -sN pour Null) sur les ports 22 et 80 de la cible.

Q. 4.1 Expliquer le fonctionnement du balayage Xmas (bien observer, avec wireshark, les différents bits de contrôle
activés par nmap) et les différents états de port constatés par nmap (selon l’état du port balayé).
Q. 4.2 Même question pour le balayage Fin.
Q. 4.3 Même question pour le balayage NULL.
Q. 4.4 Quels sont les avantages et désavantages de ces trois types de balayage par rapport aux balayages Syn et connect ?

Exercice 5 — Détection de versions


Le scan de détection de version (option -sV) permet de détecter les versions des services rendus par la cible. Pour
cela, nmap va effectuer un certain nombre de tests indiqués dans le fichier nmap-service-probes (probe = sonder) qui
se trouve généralement dans le répertoire /usr/share/nmap/.
1 Lancer un scan pour trouver la version du service ssh s’exécutant sur la machine cible en activant, pour avoir un
détail des opérations effecutées, l’option --version-trace. Nmap étant alors très bavard, sauvegarder le résultat de la
commande, à l’aide d’une redirection, vers un fichier quelconque que nous nommerons truc dans la suite.
2 Rechercher dans le fichier truc une ligne de la forme
Service scan match ( Probe <TEST > matched with <M > line <N >) blablabla

<TEST> correspond alors au nom du test dans le fichier nmap-service-probes qui a fonctionné. <N> est le numéro de
la ligne dans ce même fichier qui correspond à la réponse envoyée par le service cible en réponse à ce test.

Q. 5.1 Quel est le nom du test qui a permis de déterminer la version du service ssh ? Décrire en quoi consiste ce test.

3 Démarrer le service apache2 sur la machine cible.


4 Suivre à nouveau les instructions 1 et 2 mais, cette fois-ci, pour le port 80.

Q. 5.2 Quel est le nom du test qui a été positif pour déterminer la version du service http ? Décrire en quoi consiste ce
test. Retrouver pour cela dans le fichier nmap-service-probes la ligne commençant par Probe TCP <TEST>
avec <TEST> à remplacer par le nom du test trouvé dans le fichier truc.

Exercice 6 — Balayage ACK


Ce type de balayage (option -sA) peut fournir des informations sur un éventuel pare-feu bloquant le trafic entre la
cible et la machine de scan.
1 Lancer un balayage ACK vers le port 22 de la cible.

Q. 6.1 Quel état nmap associe-t-il alors au port ?

2 En modifiant la politique par défaut adéquate, faire en sorte que la cible bloque tous les paquets qui lui sont destinés.
3 Relancer un balayage ACK vers le port 22 de la cible.

Q. 6.2 Quel état nmap associe-t-il maintenant au port ?


Q. 6.3 En recherchant sur internet, expliquer le fonctionnement de ce type de balayage.

Page 3 / 12
TP 2 — R ÉALISATION D ’ UNE DMZ AVEC IPTABLES 2019-2020 M4210 — I NFRASTRUCTURES DE SÉCURITÉ

TP 2 — Réalisation d’une DMZ avec iptables

L’objectif du TP est de réaliser avec marionnet un réseau local (10.0.0.0/8) décomposé en deux sous-réseaux :
— une DMZ de serveurs (10.2.0.0/16) ;
— et un réseau d’utilisateurs (10.1.0.0/16).
On supposera pour simplifier qu’il n’y a qu’un serveur et qu’un utilisateur.
Les deux sous-réseaux sont interconnectés par le routeur Ri et reliés au réseau externe (ou public) par le routeur Re.
Le réseau externe est simulé par la machine pub. Il a pour adresse 1.2.3.0/24. Ci-dessous la figure de ces réseaux :

Voici le cahier des charges.


— Les machines des utilisateurs sont des clients qui peuvent communiquer sans restriction avec le réseau externe et avec
les serveurs de la DMZ.
— Par contre, tout échange initié depuis la DMZ vers le réseau des utilisateurs est proscrit.
— Le réseau local offre au réseau externe des services http et https rendus par www sur les ports standard (80 et 443).
— www peut uniquement envoyer et recevoir des paquets de ces deux protocoles et répondre aux pings du réseau local.
— Re bloque tous les paquets venant de l’extérieur qui lui sont destinés.
— À l’intérieur du réseau local, Re et Ri sont configurables à distance par ssh (depuis le réseau des utilisateurs uniquement)
et peuvent envoyer/recevoir des messages ICMP. Tout autre message reçu par Re et Ri doit être bloqué et la source
informée par un message ICMP.
— L’adresse publique du réseau local (i.e., associée à l’interface eth1 de Re) est 1.2.3.1.

Indications :
— Dans un premier temps, créer le réseau (ne pas oublier de configurer Re et Ri avec deux interfaces), attribuer des IPs à
toutes les interfaces et configurer les tables de routage pour que toutes les machines puissent communiquer entre elles.
— Sur www, Re et Ri, placer toutes les commandes iptables dans un script fw.sh. Mettre dans le début du script des
commandes iptables permettant de vider la table filter (et nat pour Re) et de fixer les politiques par défaut.
— Ensuite mettre en place les règles de filtrage sur www, Ri et Re (par ordre de difficulté).
— Enfin, mettre en place les règles de translation d’adresses et de redirection sur Re.
— Effectuer des tests permettant de vérifier que toutes les contraintes de l’énoncé sont respectées : ce qui est autorisé
fonctionne bien et, plus important, ce qui est interdit ne fonctionne pas. Pour simuler une attaque sur la DMZ, vous
pourrez ajouter une machine pirate sur celle-ci afin de vérifier que le réseau des utilisateurs reste protégé.
Quelques rappels :
— pour activer le routage :
# sysctl net.ipv4.ip_forward=1

— pour afficher la table de routage :


# route -n

— pour ajouter une route par défaut :


# route add default gw @ip-de-la-passerelle

— pour ajouter une route vers un réseau :


# route add -net @ip-du-réseau netmask masque-du-réseau gw @ip-de-la-passerelle

— pour supprimer une route : refaire la commande qui l’a ajoutée en remplaçant add par del

En bonus, en vous aidant d’internet, apporter les modifications suivantes :


— Faire en sorte que les scans de type Xmas, Fin et Null venant du réseau public soient enregistrées dans le journal.
— Pour limiter les possibilités d’attaque de type force brute ou SYN flood sur le serveur web, faire en sorte que Re laisse
entrer au maximum 10 connexions http par seconde. Pour tester, écrire, sur la machine pub, un script qui va envoyer
avec wget une centaine de requêtes http vers 1.2.3.1, ce qui devra prendre au moins une dizaine de secondes.
— Placer un serveur syslog (voir TP de supervision) sur la DMZ et faire en sorte que www envoie un message syslog de
gravité 3 (Error) s’il reçoit un paquet non désiré.

Page 4 / 12
M4210 — I NFRASTRUCTURES DE SÉCURITÉ 2019-2020 TP 3 — F ORGER DES PAQUETS AVEC SCAPY

TP 3 — Forger des paquets avec scapy

Scapy (https://scapy.net/) est un module python de manipulation de paquets. Il permet en particulier de forger
des paquets, d’en envoyer, et de capturer le trafic réseau. C’est donc un outil qui peut être utilisé pour réaliser des tests
d’intrusion (ou pentest, penetration test) visant à auditer la sécurité d’un réseau en simulant des attaques et en observant
la réaction du réseau.
Nous réaliserons ce TP sous marionnet. Vous fournirez, en guise de compte-rendu, un PDF contenant les scripts
demandés, les réponses aux questions de l’énoncé ainsi que les copies d’écran des manipulations effectuées pour tester
vos scripts.

Exercice 1 — Travail préliminaire


1 Créer un réseau avec 3 machines (max, mary et scapy) et une passerelle vers Internet. Vérifier que le service DHCP est
bien activé sur la passerelle. Augmenter la mémoire disponible sur scapy : passer à 512M. Le réseau sera le suivant :

2 Demander des baux DHCP sur les 3 machines :


# dhclient eth0

Scapy est disponible sur les dépôts debian et nous pourrions l’installer avec aptitude mais l’opération est très lente.
Nous allons plutôt l’installer directement depuis une archive.
3 Sur la machine scapy, télécharger une archive de la version 2.0.0.10 de scapy :
# wget --no-check-certificate https://github.com/secdev/scapy/archive/v2.0.0.10.tar.gz

4 Décompresser l’archive :
# tar xvzf v2.0.0.10.tar.gz

5 Aller dans le répertoire scapy-2.0.0.10.


6 La table de routage des machines virtuelles de marionnet (contenue dans le fichier /proc/net/route) contient une
ligne vide, ce qui est inhabituel et a la facheuse conséquence de faire planter scapy. Nous allons donc ajouter la ligne
suivante après la boucle for à la ligne 159 du fichier scapy/arch/linux.py :
if len(l. split () ) != 11: continue

Ce qui signifie : si la ligne du fichier ne contient pas 11 colonnes (comme c’est le cas pour les lignes du fichier route),
on l’ignore et on passe à la suivante. Pour vérifier votre modification vous devriez voir le résultat suivant :
# head -161 scapy/arch/linux.py | tail -3
for l in f. readlines () [1:]:
if len (l. split () ) != 11: continue
iff ,dst ,gw , flags ,x ,x ,x ,msk ,x ,x ,x = l. split ()

7 Lancer l’installation de scapy (en root) :


# python setup.py install

Comme nous utiliserons scapy pour envoyer des paquets bruts il sera nécessaire d’exécuter nos scripts scapy avec le
compte root (comme nous le faisions avec certains scans nmap).

Exercice 2 — Prise en main de scapy


Pour se familiariser avec scapy, le plus simple est d’utiliser l’interpréteur python.
Une fois l’interpréteur lancé, on peut charger tout le contenu du module avec un import :
>>> from scapy.all import *

(Le message d’erreur qui peut alors s’afficher concernant l’absence de route IPv6 par défaut n’a pas de conséquence dans
la suite et peut être ignoré.)

Page 5 / 12
TP 3 — F ORGER DES PAQUETS AVEC SCAPY 2019-2020 M4210 — I NFRASTRUCTURES DE SÉCURITÉ

Forger des paquets Scapy prend en charge les protocoles indispensables des couches 1 à 4 et il comprend également
certains protocoles applicatifs. La liste complète peut être affichée en appelant la fonction ls. À chaque protocole
correspond une classe scapy. On peut alors forger un PDU d’un protocole donné avec le constructeur de la classe
correspondante. Par exemple, pour forger un PDU IP :
>>> p = IP()

Le PDU forgé contient des valeurs par défaut fixé par scapy. Sa méthode show nous permet de voir son contenu détaillé :
>>> p.show()
###[ IP ]###
version = 4
ihl = None
tos = 0 x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = hopopt
chksum = None
src = 127.0.0.1
dst = 127.0.0.1
\ options \

On retouve les champs IP et on voit comment scapy les nomme ainsi que les valeurs par défaut qu’il leur donne.
Les différents champs d’en-tête d’un PDU sont des attributs de classe. On peut donc y accéder avec la notation pointée.
On peut aussi initialiser leurs valeurs à la construction de l’objet. Par exemple :
>>> p = IP()
>>> p.dst = "192.168.0.4"
>>> p.ttl = 20
>>> p = IP(src="10.0.0.1", dst="10.0.0.254", ttl=10)

À noter qu’il est inutile de fixer la valeur de certains champs de l’en-tête comme len (longueur du paquet) ou chksum
(code correcteur d’erreur). Scapy (ou l’OS) s’en chargera automatiquement si le paquet est envoyé sur le réseau.
L’opérateur / permet d’encapsuler des PDUs. Par exemple, pour forger une demande de connexion TCP vers le port
80 de l’hôte 10.0.0.100 :
>>> p = IP(dst="10.0.0.100")/TCP(flags="S",dport=80)

On peut tester qu’un paquet contient bien un PDU d’un protocole donné à l’aide de l’opérateur in :
>>> p = IP(dst="10.0.0.100")/TCP(flags="S",dport=80)
>>> "IP" in p
True
>>> "TCP" in p
True
>>> "ICMP" in p
False

De même, on peut accéder au champ d’un en-tête particulier en manipulant le paquet comme un dictionnaire :
>>> p = IP(dst="10.0.0.100")/TCP(flags="S",dport=80)
>>> p["IP"].dst
"10.0.0.100"
>>> p["TCP"].dport
80
>>> p["ICMP"].type
AttributeError : ’ NoneType ’ object has no attribute ’type ’

La dernière expression a levé une exception, le paquet ne contenant pas d’en-tête ICMP.

Envoyer et recevoir des paquets Une fois le paquet forgé, on peut l’envoyer avec la fonction send. Scapy se charge
alors de l’encapsuler dans une trame Ethernet et de l’envoyer sur le réseau au bon destinataire (via, éventuellement, l’envoi
préalable d’une requête ARP). On parle alors d’envoi de niveau 3.
>>> p = IP(dst="10.0.0.100")/TCP(flags="S",dport=80)
>>> send(p)
.
Sent 1 packets .

Si le paquet contient déjà un en-tête Ethernet on utilise sendp qui effectue un envoi de niveau 2 :
>>> p = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(dst="10.0.2.16")/TCP()
>>> sendp(p)
.
Sent 1 packets .

Page 6 / 12
M4210 — I NFRASTRUCTURES DE SÉCURITÉ 2019-2020 TP 3 — F ORGER DES PAQUETS AVEC SCAPY

Les fonctions send et sendp ne permettent pas de récupérer le paquet éventuellement reçu en réponse à un paquet
envoyé. On utilise pour cela la fonction sr1 (send and receive) qui permet d’envoyer un paquet et de réceptionner sa
réponse. Si aucune réponse n’est reçue, sr1 retournera None. Sinon, elle renverra la réponse qui est un paquet scapy
que l’on peut manipuler comme ceux qui sont forgés. Le paramètre optionnel timeout permet de spécifier le temps
d’attente maximal de la réponse. Passé ce délai, sr1 retournera None. La fonction sr1 opère au niveau 3. La fonction
d’envoi/réception équivalente pour le niveau 2 est srp1.
Toutes les fonctions d’envoi et d’envoi/réception ont un paramètre optionnel verbose que l’on peut fixer à False pour
éviter que scapy n’affiche des messages d’information (comme Sent 1 packets. dans le dernier exemple).
Écrire un script python test-scapy.py réalisant les opérations suivantes :
1 envoyer un ping à la machine mary
2 envoyer un ping à la machine mary et afficher un message indiquant si mary a bien répondu au ping (on mettra un temps
d’attente maximal de 5 secondes)
3 envoyer un ping à la machine mary en usurpant l’IP de max
4 envoyer une requête ARP pour connaître l’adresse MAC de max
5 envoyer une requête ARP pour connaître l’adresse MAC de max puis afficher cette adresse
Pensez à utiliser la méthode show sur les différents PDU forgés pour voir les noms des champs à modifier.

Exercice 3 — Simulation d’une attaque d’empoisonnement de cache ARP


Scapy a une fonction arpcachepoison qui réalise l’attaque d’empoisonnement de cache ARP. Elle prend deux
arguments : l’IP de la cible (C) et l’IP de la victime (V), le but étant que V associe l’adresse IP de C à l’adresse MAC de
l’attaquant (scapy dans notre cas).
1 Lancer des pings en continu de max vers mary.
2 Tout en capturant le trafic sur scapy, exécuter le code suivant dans l’interpréteur python :
>>> arpcachepoison("IPdeMary", "IPdeMax")

Q. 3.1 Qu’observe-t-on ?
Q. 3.2 En vous basant sur l’analyse des trames capturées, expliquer précisèment le fonctionnement de cette attaque.

3 Écrire un script arp-poison.py qui effectue l’attaque d’empoisonnement de cache ARP (sans, bien entendu, utiliser
la fonction arpcachepoison). Ce script prendra deux arguments : l’IP de la cible et l’IP de la victime.
Pour rappel, il faut importer le module sys pour pouvoir récupérer les arguments passés à un script en ligne de commandes.
sys.argv contient la liste de ces arguments. sys.argv[1] est donc équivalent à $1 en bash.

Exercice 4 — Balayages NMAP


On peut, grâce à scapy, réaliser de nombreuses opérations de balayage réseau comme celles effectuées par nmap.
Écrire un script scan.py qui prend trois arguments
— un code de balayage à effectuer (A pour ACK, ou S pour SYN) ;
— l’adresse IP d’un hôte cible ;
— et un numéro de port à scanner.
Le script effectuera le balayage indiqué par le premier argument sur le port de l’hôte cible puis affichera le résultat de
l’opération. Par exemple :
$ ./scan.py A 10.0.0.2 80
le port 22 de 10.0.0.2 est non filtr é
$ ./scan.py A 10.0.0.2 22
le port 22 de 10.0.0.2 est filtr é
$ ./scan.py S 10.0.0.2 80
le port 80 de 10.0.0.2 est ouvert
$ ./scan.py S 10.0.0.2 22
le port 22 de 10.0.0.2 est filtr é
$ ./scan.py S 10.0.0.2 20
le port 20 de 10.0.0.2 est ferm é

L’attribut flags d’un PDU TCP est une combinaison binaire des différents drapeaux activés dans le paquet. Les
valeurs associées aux drapeaux sont données dans le tableau ci-dessous :

FIN = 0x01
SYN = 0x02
RST = 0x04
PSH = 0x08
ACK = 0x10
URG = 0x20

Page 7 / 12
TP 3 — F ORGER DES PAQUETS AVEC SCAPY 2019-2020 M4210 — I NFRASTRUCTURES DE SÉCURITÉ

(Le préfixe 0x signifie que la constante est exprimée en hexadécimal.)


Pour tester les drapeaux TCP d’un PDU, le plus simple est donc de tester si le bit correspondant au drapeau est à 1 en
utilisant un ET logique (opérateur python &). Par exemple :
>>> p = TCP(flags="SRU")
>>> 0x02 & p.flags != 0 # SYN
True
>>> 0x10 & p.flags != 0 # ACK
False

Exercice 5 — Création d’un IDS (très) simplifié


La fonction sniff permet de capturer le trafic réseau. Elle prend de nombreux arguments optionnels mais nous n’en
utiliserons qu’un : timeout qui est la durée (en secondes) de la capture. Par défaut timeout vaut None, ce qui signifie que
la capture ne s’arrête pas. sniff renvoie la liste des paquets capturés. Voici un exemple d’utilisation de cette fonction :
>>> paquets = sniff(timeout=10)
>>> print("en 10 secondes j’ai capturé {} paquets".format(len(paquets)))
en 10 secondes j ’ ai captur é 19 paquets

Nous allons utiliser cette fonction pour réaliser un IDS très basique. Un IDS (Intrusion Detection System) est un outil
de sécurité qui écoute le trafic réseau, et essaie de détecter les attaques en se basant sur une base de données d’attaques
connues. Les attaques détectées sont ensuite rapportées par l’IDS via l’envoi d’un mail à l’administrateur, d’un message
syslog, d’une notification SNMP. . . L’outil snort que nous verrons dans un TP ultérieur est un exemple d’IDS.
Écrire un script ids.py qui va effectuer le traitement suivant :
— capturer les paquets pendant dix secondes
— analyser les paquets reçus pour détecter :
— les balayages de type XMAS
— les attaques de type SYN FLOOD
On considèrera qu’une attaque SYN FLOOD a eu lieu si le nombre de paquets SYN capturés pendant les dix secondes
est supérieur à 100.
— signaler les attaques détectées en écrivant dans le fichier /var/log/ids.log une ligne décrivant le problème. Pour les
scan XMAS, la ligne devra contenir la source du scan. Pour les SYN FLOOD, elle contiendra le nombre de paquets
SYN reçus.
En bonus, vous pourrez améliorer votre script de façon à :
— Détecter les pings de la mort.
— Utiliser le module python syslog (voir la documentation en ligne) pour générer un message syslog de gravité 3 (Error)
à chaque détection d’une attaque. On pourra alors supprimer l’écriture dans le fichier /var/log/ids.log.
— (plus compliqué) Envoyer une notification SNMPv2c (vers une IP fictive et en utilisant la communauté trapcomm)
lorsqu’une attaque est détectée. On imaginera que la branche d’entreprise 1.3.6.1.4.1.10000 a été attribuée à notre
IDS. L’OID de la notification sera 1.3.6.1.4.1.10000.1. Elle contiendra également l’objet 1.3.6.1.4.1.10000.2 ayant
pour valeur un message décrivant l’attaque détectée.
Scapy peut forger des paquets SNMP. Vous trouverez quelques exemples sur cette page :

https://www.packetlevel.ch/html/scapy/scapychw.html

Page 8 / 12
M4210 — I NFRASTRUCTURES DE SÉCURITÉ 2019-2020 TP 4 — IDS ET IPS

TP 4 — IDS et IPS

L’objectif de ce TP est de se familiariser avec deux logiciels libres pouvant être utilisés comme IDS et IPS : snort et
fail2ban ; et de mettre en place une solution de filtrage dynamique utilisant ces deux outils.

Exercice 1 — Création du réseau et installation des paquets


1 Créer le réseau ci-dessous :

Remarques :
— H est un hub.
— Vérifier que le service DHCP est bien activé sur la passerelle.
2 Demander des baux DHCP sur fw(eth0), snort et www.
3 Attribuer des IPs à pirate et fw(eth1) sur le réseau 1.2.3.0/24.
4 Sur pirate : ajouter une route par défaut.
5 Sur www et snort : ajouter une route vers le réseau 1.2.3.0/24.
6 Sur fw : modifier le paramètre système net.ipv4.ip_forward pour que fw accepte de router les paquets.
7 Vérifier que les pings passent entre toutes les machines.
8 Sur pirate : installer scapy en suivant la procédure du TP 3.
9 Sur snort : installer l’outil snort depuis le script disponible à cette adresse :

https://lipn.univ-paris13.fr/~evangelista/cours/M4210/fichiers/install-snort

10 Sur fw : installer l’outil fail2ban depuis le script disponible à cette adresse :

https://lipn.univ-paris13.fr/~evangelista/cours/M4210/fichiers/install-fail2ban

(Les 2 scripts d’installation téléchargent et installent les paquets nécessaires. L’opération peut être très longue. . . )

Exercice 2 — Prise en main de snort


Nous allons tout d’abord configurer le module de sortie de snort pour qu’il émette des alertes vers le serveur rsyslog
local. Nous allons pour cela éditer le fichier de configuration principal de snort qui est /etc/snort/snort.conf.
1 Décommenter la ligne commençant par # output alert_syslog dans le fichier de configuration. Cette ligne définit
également la catégorie et la niveau des messages syslog générés par snort.
2 Démarrer le service rsyslog sur snort.
3 En analysant le fichier de configuration du service rsyslog, trouver le fichier dans lequel seront rangées les alertes
envoyées par snort.
4 Sur pirate : envoyer, avec nmap, un balayage XMAS vers le port 20 de www. (snort est installé avec de nombreuses
règles qui permettent, entre autres, de détecter certains balayages.)
5 Vérifier que l’alerte est bien présente dans le fichier de journal.
Le répertoire /etc/snort/rules contient les fichiers de signatures données sous la forme de règles snort. Pour nous
familiariser avec ces règles nous allons forger et envoyer avec scapy des paquets permettant de générer des alertes.
6 Pour chaque identifiant de signature dans la liste ci-dessous, retrouver la règle correspondante dans le répertoire
/etc/snort/rules (i.e., celle contenant le champ sid:ID;) puis forger et envoyer avec scapy un paquet permettant
de déclencher l’alerte. Vérifier ensuite dans le journal que l’alerte est bien présente. La liste des identifiants : 228, 312,
222 et 2050. Remarques :

Page 9 / 12
TP 4 — IDS ET IPS 2019-2020 M4210 — I NFRASTRUCTURES DE SÉCURITÉ

— Ces règles utilisent certaines variables (p.ex., $EXTERNAL_NET) qui peuvent être initialisées dans snort.conf mais,
par défaut, valent any.
— La dernière règle contient une condition de la forme content: "|04|";, ce qui signifie 1 octet dont la valeur
hexadécimale est 04. On peut en python générer le caractère à partir de sa représentation hexadécimale en utilisant
le préfixe \x. Par exemple :
>>> print(’\x73\x61\x6c\x75\x74’)
salut

Ces règles sont définies pour ICMP et UDP. Pour tester les règles TCP nous allons maintenant utiliser l’outil nc qui
permet, entre autres, d’établir une connexion TCP avec un serveur. À titre d’exemple nous allons prendre la règle suivante
qui correspond à une attaque sur un serveur Web via le langage PHP :
1 alert tcp $EXTERNAL_NET any - > $HTTP_SERVERS $HTTP_PORTS ( \
2 msg :" WEB-PHP PhpGedView PGV base directory manipulation "; \
3 flow : to_server , established ; \
4 uricontent :" _conf . php "; nocase ; \
5 content :" PGV_BASE_DIRECTORY "; nocase ; \
6 reference : bugtraq ,9368; classtype : web-application-attack ; sid :2926; rev :1; \
7 )

La ligne 3 indique que seuls les paquets de l’extérieur ($EXTERNAL_NET) vers notre serveur web ($HTTP_SERVERS) faisant
partie d’une connexion TCP (par la ligne 1) établie sont examinés pour cette règle.
Les lignes 4 et 5 indiquent que les chaînes de caractères _conf.php. et PGV_BASE_DIRECTORY doivent être présentes
dans l’URI de la ressource demandée et dans la charge du paquet respectivement. Dans les deux cas la recherche est
insensible à la casse (option nocase;).
Pour tester cette règle nous allons créer une requête HTTP que nous allons sauvegarder dans un fichier req.txt :
GET / chemin / vers / rep / _conf . php HTTP /1.1
file : blablaPGV_bASE_DIRECTORYblabla

(Insérer une ligne vide en fin de fichier pour que la requête soit bien formée.)
On peut ensuite envoyer cette requête avec nc :
# cat req.txt | nc @ip-de-www 80

7 Démarrer le service apache2 sur www.


8 Faire le test et vérifier que le journal de snort contient bien une nouvelle ligne contenant le message Web-PHP ....
9 Faire des tests permettant de générer des alertes pour les identifiants de signature d’attaque sur HTTP ci-dessous :
— 100000691
— 1171 — Cette règle est, par défaut, commentée. Il faut donc la décommenter et redémarrer snort.
— en bonus : 1817 — Celle-ci est un peu plus compliquée car elle utilise un expression régulière (option pcre). Cette
expression contient un caractère codé en hexadécimal (3a). On peut en bash afficher un caractère à partir de son
code hexadécimal en préfixant ce code par \x et en passant l’option -e à la commande echo. Par exemple :
# echo -e ’\x73\x61\x6c\x75\x74’
salut

Exercice 3 — Prise en main de fail2ban


fail2ban est un outil pouvant servir à la fois d’IDS et d’IPS. C’est un logiciel libre écrit en python. Il examine
périodiquement les journaux, recherche dans ceux-ci des motifs particuliers (p.ex., la chaîne authentification failed)
et, si la recherche est fructueuse, exécute une action comme, par exemple, envoyer un mail ou une notification SNMP
(fonction d’IDS), bloquer une adresse IP ou un port (fonction d’IPS). Mais, plus généralement, l’action peut-être n’importe
quelle commande. L’application d’une action particulière quand un motif est trouvé est appelé banissement par fail2ban.

Test de l’outil Pour nous familiariser avec l’outil nous allons voir comment il peut automatiquement bloquer l’IP d’un
hôte qui tente successivement plusieurs connexions SSH avec un login ou un mot de passe incorrect en ajoutant des règles
de filtrage iptables.
1 Arrêter le service fail2ban sur fw.
2 Démarrer les service ssh et rsyslog sur fw.
3 Afficher le contenu de la table filter sur fw. Les chaînes devraient normalement être vides avec une politique par défaut
fixée à ACCEPT. Modifier, si ce n’est pas le cas, leurs contenus pour obtenir ce résultat.
4 Démarrer le service fail2ban sur fw.

Page 10 / 12
M4210 — I NFRASTRUCTURES DE SÉCURITÉ 2019-2020 TP 4 — IDS ET IPS

5 Afficher de nouveau le contenu de la table filter sur fw. Une nouvelle chaîne (fail2ban-ssh) devrait apparaître. On
voit que la chaîne INPUT y redirige les paquets ssh (i.e., avec un port destination de 22). Cette nouvelle chaîne contient
une unique règle avec l’action RETURN, qui a pour effet de sortir de la chaîne (et donc de revenir dans la chaîne
INPUT). Elle n’a donc, pour l’instant, aucun effet.
6 Sur pirate : lancer successivement 6 tentatives de connexion ssh sur fw avec un login ou un mot de passe incorrect. Lors
de la 6ème tentative, ssh devrait se bloquer car fail2ban aura alors bloqué l’adresse IP de pirate.
7 Vérifier, sur fw, qu’une règle iptables a bien été ajoutée dans la chaîne créée par fail2ban.
8 Dans 10 minutes vous vérifierez que la règle a été retirée par fail2ban.

Fichiers de configurations Le répertoire /etc/fail2ban contient (entre autres) les fichiers et répertoires suivants :
— filter.d — Chaque fichier de ce répertoire contient les motifs à chercher pour une application et un type d’erreur
particuliers. Par exemple, sshd.conf contient des motifs indiquant une erreur d’authentification SSH.
— action.d — Ce répertoire contient les définitions des actions que fail2ban peut effectuer. Par exemple iptables.conf
contient des règles iptables à exécuter dans différents contextes.
— jail.conf — Ce fichier contient la définition des geôles. Une geôle décrit les opérations de banissement effectuées
par fail2ban pour un type d’application. Une geôle peut être vue comme un triplet (fichier, motifs, action) qui
s’interprète ainsi : Rechercher dans le fichier des lignes ayant un des motifs précisés. Si un motif est trouvé, l’action
est appliquée.

Fonctionnement des fichiers Nous allons regarder les fichiers de configuration de plus près pour comprendre ce qui
s’est passé durant le test.
Tout d’abord le fichier /etc/fail2ban/jail.conf contient une section [DEFAULT] qui définit un certain nombre de
variables qui peuvent être ensuite redéfinies dans les geôles. Cette section contient en particulier la ligne suivante :
banaction = iptables - multiport

Ce qui signifie que l’action de banissement par défaut à exécuter quand un motif sera trouvé dans un journal est l’action
iptables-multiport (“multiport” car fail2ban pourra fermer plusieurs ports simultanément).
On y trouve également, plus bas, la définition de la geôle ssh :
1 [ ssh ]
2 enabled = true
3 port = ssh
4 filter = sshd
5 logpath = / var / log / auth . log
6 maxretry = 6

Nous allons la détailler ligne par ligne :


— l. 1 : le nom de la geôle : ssh
— l. 2 : enabled étant fixé à true, la geôle est activée.
— l. 3 : fixe la valeur du paramètre port dans le fichier de l’action (voir plus bas)
— l. 4 : Le fichier /etc/fail2ban/filter.d/sshd.conf contient les motifs à rechercher.
— l. 5 : Les motifs doivent être recherchés dans le fichier /var/log/auth.log. (Ceci doit normalement correspondre
avec le chemin du fichier contenant les erreurs de la catégorie AUTH défini dans le fichier de configuration de rsyslog.)
— l. 6 : La commande de banissement est exécutée si fail2ban trouve (dans le fichier /var/log/auth.log) 6 occurences
d’un des motifs enumérés dans le fichier sshd.conf.
banaction n’étant pas redéfini dans cette geôle, c’est l’action par défaut (iptables-multiport) qui s’applique.
Le fichier /etc/fail2ban/action.d/iptables-multiport.conf décrit cette action. La section [Definition]
définit certaines variables. Chacune contient la liste des commandes à exécuter dans un contexte particulier et pour chaque
geôle utilisant cette action :
— actionstart — commandes à exécuter une seule fois au démarrage de fail2ban
— actionstop — commandes à exécuter une seule fois à l’arrêt de fail2ban
— actionban — commande de banissement à exécuter quand un motif a été trouvé dans les journaux
— actionunban — commandes à exécuter lorsque la période de banissement d’un hôte a expiré (voir plus bas)
Voici, par exemple, le contenu de la variable actionstart :
actionstart = iptables -N fail2ban -< name >
iptables -A fail2ban -< name > -j RETURN
iptables -I <chain > -p < protocol > -m multiport -- dports <port > -j fail2ban -< name >

On remarque que les commandes sont paramétrées (avec des noms de paramètres entre chevrons). Les valeurs de
ces paramètres sont automatiquement fixées dans les fichiers de geôle ou, à défaut, dans la section [Init] du fichier
iptables-multiport.conf.
Par exemple, si l’on revient sur la déclaration de la geôle ssh, on en déduit les paramètres suivants :
— l. 1 : <name> est remplacé par ssh
— l. 3 : <port> est remplacé par ssh

Page 11 / 12
TP 4 — IDS ET IPS 2019-2020 M4210 — I NFRASTRUCTURES DE SÉCURITÉ

Pour les paramètres qui ne sont pas définis dans cette geôle (protocol, chain), il faudra, comme dit précédemment,
regarder la section [Init] du fichier iptables-multiport.conf pour trouver leurs valeurs.
Les fichiers du répertoire filter.d, comme sshd.conf, doivent définir une variable failregex qui est une liste
d’expressions régulières des motifs à rechercher (et dont la reconnaissance entrainera éventuellement un banissement).

Paramètres temporels Trois paramètres influent sur le déclenchement du banissement et sa durée : findtime, bantime
et maxretry. À chaque seconde (période non paramétrable) fail2ban inspectera les journaux. Il analysera toutes les lignes
dont la date d’écriture remonte à au plus findtime secondes. Si le nombre d’occurences d’un motif à rechercher est
supérieur ou égal à maxretry, il enclenchera le bannissement (actionban dans le fichier de l’action). Passé un délai
de bantime secondes, il enclenchera l’opération inverse (actionunban dans le fichier de l’action). Si bantime < 0 le
banissement est perpétuel.
Q. 3.1 En consultant les fichiers jail.conf et iptables-multiport.conf donner la liste des commandes exécutees
pour la geôle ssh au démarrage de fail2ban en remplaçant les paramètres par leurs valeurs effectives. Décrire
l’effet de ces commandes.
Q. 3.2 Même question pour le bannissement un hôte d’IP A.B.C.D.
Q. 3.3 Même question pour la sortie d’un hôte d’IP A.B.C.D de la gêole.
Q. 3.4 En analysant le fichier des motifs de la geôle ssh, trouver, dans le journal, les lignes qui ont mené au banissement.

Exercice 4 — Filtrage dynamique


L’objectif de cet exercice est de mettre en œuvre une solution combinant snort, fail2ban et rsyslog pour bloquer
dynamiquement des attaques du réseau externe (1.2.3.0/24) sur le serveur web.
Voici une description du problème :
Le protocole HTTP définit la méthode DELETE qui permet de supprimer une ressource. Généralement ces
requêtes sont rejetées par le serveur web, ce qui est le cas avec la configuration par défaut d’apache. Notre
serveur web contient un répertoire /upload/files dans lequel sont stockés des fichiers déposés par des
utilisateurs. Les fichiers de ce répertoire sont parfois ciblées par des requêtes DELETE. Même si apache les
rejette on souhaite tout de même que les attaquants ne puissent plus accéder au serveur web par la suite. Par
exemple, si pirate envoie une telle requête vers www, fw refusera par la suite de router vers le réseau interne
(celui de snort et www) tout paquet en provenance de pirate et destiné au port 80.
Pour parvenir à ce résultat nous mettrons en œuvre la solution suivante :
— snort va communiquer au serveur rsyslog qui s’exécute sur sa machine les requêtes DELETE sur les fichiers du
répertoire /upload/files de www.
— Ce serveur va lui même remonter ces messages syslog au serveur rsyslog qui s’exécute sur fw.
— Enfin, fail2ban sera configuré pour rechercher des messages indiquant une telle attaque dans le fichier de journal
adéquat et ajoutera dynamiquement une règle de filtrage.
Voici la démarche à suivre (donnée à titre indicatif, vous pouvez procéder comme bon vous semble pour parvenir au
résultat attendu) :
1 Sur snort : ajouter dans le fichier /etc/snort/local.rules une règle permettant de lever une alerte en cas de requête
DELETE sur un fichier du répertoire /upload/files. Vous utiliserez un message (propriété msg de votre règle snort)
permettant de décrire précisèment l’attaque afin qu’il puisse être facilement reconnu par fail2ban. Vous donnerez à votre
signature un identifiant (propriété sid) compris entre 106 et 108 . Cet intervalle est celui dans lequel les utilisateurs de
snort peuvent choisir leurs identifiants.
2 Sur pirate : envoyer (avec nc) une requête permettant de générer l’alerte et vérifier qu’une alerte a effectivement été
générée. Retester avec un chemin différent mais désignant la même URI (p.ex. : /upload/../upload/files/machin
ou /./upload/./files/machin). Le préprocesseur http de snort devrait normalement retransformer un tel chemin
pour obtenir /upload/files/machin (et l’alerte devrait toujours être générée).
3 Sur snort : configurer le serveur rsyslog afin qu’il redirige les messages d’alerte vers le serveur rsyslog de fw.
4 Sur fw : activer la réception de messages syslog sur fw.
5 Sur fw : créer un fichier /etc/fail2ban/filter.d/delete_files.conf dont le contenu sera le suivant :
[ Definition ]
failregex = ...

Vous remplacerez les points de suspension par une expression permettant de reconnaître les messages du journal
signalant l’attaque. Inspirez vous pour cela du contenu du fichier /etc/fail2ban/filter.d/sshd.conf.
6 Sur fw : créer une geôle [delete_files] dans le fichier /etc/fail2ban/jail.local répondant à notre besoin. Tout
attaquant sera banni à perpétuité.
7 Sur pirate : envoyer une requête vers www menant au banissement de pirate.
8 Vérifier que pirate ne peut plus accéder au serveur web de www.

Page 12 / 12

Vous aimerez peut-être aussi