# Simuler une attaque MITM
+++ sommaire
## Introduction
Ce document décrit un environnement à mettre en place en classe pour simuler une attaque type ['**M**an **I**n **T**he **M**iddle'](https://fr.wikipedia.org/wiki/Attaque_de_l%27homme_du_milieu).
<span style="color:red">Le contenu de ce document est bien entendu à utiliser dans un cadre et but **pédagogique**.</span>
Ce document est initialement créé pour le programme de 1ère NSI. Rappel du programme officiel :
|Contenu|Capacités attendues|Commentaire|
|---|---|---|
|- Interaction client-serveur<br>- Requêtes HTTP<br>- Réponses du serveur|- Distinguer ce qui est exécuté sur le client ou sur le serveur et dans quel ordre<br>- Distinguer ce qui est mémorisé dans le client et retransmis au serveur<br>- Reconnaître quand et pourquoi la transmission est chiffrée|Il s’agit de faire le lien avec ce qui a été vu en classe de seconde et d’expliquer comment on peut passer des paramètres à un site grâce au protocole HTTP|
|- Formulaire d’une page Web|- Analyser le fonctionnement d’un formulaire simple<br>- Distinguer les transmissions de paramètres par les requêtes POST ou GET|Discuter les deux types de requêtes selon le type des valeurs à transmettre et/ou leur confidentialité
- [source](https://cache.media.eduscol.education.fr/file/SP1-MEN-22-1-2019/26/8/spe633_annexe_1063268.pdf)
- Cette simulation couvre toutes les capacités attendues du programme hormis la partie concernant les formulaires type GET
## Pré-requis
### Côté apprenants
Vos apprenants doivent avoir un accès à un ordinateur. Certains ordinateurs seront utilisés comme serveur, ce qui implique qu'il faut installer dessus :
- python v3.8 et +
- un navigateur web à jour
### Côté enseignant
J'ai testé et détaillé les pré-requis pour deux OS ; débian (linux) et windows 10. Concernant les distributions linux type débian (comme ubuntu) fonctionnent tout autant avec les manipulations ci-dessous.
#### Installer un renifleur de paquet
Sur votre ordinateur, vous devez installer un renifleur de paquet (packet sniffer). Mon choix s'est porté sur l'application **tshark**.
**tshark** permet d'afficher sur un terminal les données des packets échangés sur le réseau. Il existe **wireshark**, plus connu, qui repose sur le même moteur que **tshark** mais propose en plus une interface graphique. Cependant, je préfère tshark dans la mesure où je peux épurer un maximum le output afin de ne faire sortir que les données pertinentes dans le cadre de cette simulation.
La procédure pour installer **tshark** :
+++ diagramme
graph TD
0[[ordinateur de l'enseignant]]
0 --> 00{OS}
00 --> |debian| 000[fa:fa-external-link-alt Installer le package tshark]
00 --> |windows 10| 001(ouvrir le powershell en admin)
001 --> 002(fa:fa-external-link-alt installer le gestionnaire de paquet 'Chocolatey')
click 002 "https://chocolatey.org/install" _blank
002 --> 003(fermer le powershell et le ré-ouvrir)
003 --> 004(fa:fa-external-link-alt installer wireshark)
click 003 "https://chocolatey.org/packages/wireshark" _blank
004 --> 005(fa:fa-external-link-alt télécharger et installer 'Npcap installer')
click 004 "https://nmap.org/npcap/" _blank
005 --> 006(tshark se trouve dans 'C:\Program Files\Wireshark')
click 000 "https://tshark.dev/setup/install/" _blank
+++
#### Générer un certificat auto-signé
Le serveur en mode 'https' a besoin d'un fichier "certificat" pour fonctionner. Vous pouvez le genérer en amont, et ensuite le donner aux apprenants pendant la simulation.
Il suffit d'exécuter la commande `openssl req -new -x509 -keyout serverhttps.pem -out server.pem -days 36500 -nodes`
**note** : Sur **windows**, vous devez en amont installer le [package openssl via chocolatey](https://chocolatey.org/packages/openssl)
Le fichier `server.pem` est créé dans le dossier dans lequel vous vous trouvez dans votre terminal.
## Simulation de l'attaque
### Choix du scénario
Il est possible de simuler une attaque **MITM** sous différents scénarios :
+++ diagramme
graph TD
0[Vos apprenants ont accès à des ordinateurs équipés de carte wifi ?];
0 --> |Oui| 00[Scénario avec 'hotspot WIFI']
style 00 color:blue
0 --> |Non| 01[Scénario avec un réseaux LAN éthernet]
style 01 color:green
+++
#### [.text-blue] Scénario avec 'hotspot WIFI'
La configuration <span style="color:blue">'hotspot WIFI'</span> implique que votre ordinateur ainsi que ceux des apprenants possedent tous des cartes wifi
Sur votre ordinateur, vous devez démarrer le mode hotspot.
Besoin d'aide pour démarrer un hotspot ? vous pouvez vous aider de [cet article](https://vitux.com/make-debian-a-wireless-access-point/) pour **débian**, ou de [cet article](https://www.pcastuces.com/pratique/astuces/4805.htm) pour **windows**. Si vous rencontrez un problème, vérifiez que votre carte wifi à les derniers pilotes à jour.
Demandez ensuite à vos apprenants de se connecter avec leur ordinateur sur votre hotspot wifi.
#### [.text-green] Scénario avec un réseaux LAN éthernet
À creuser !
### Démarrer tshark
Pour collecter seulement les paquets http, utiliser la commande avec les paramètre suivants :
**Sur débian :**
En wifi avec comme nom d'interface 'wlp1s0'. Ce nom peut varier, pour le trouver vous pouvez utiliser les commandes `cat /proc/net/wireless` ou encore `sudo iwconfig`
```
tshark -i wlp1s0 -Y 'http' -Tfields -e _ws.col.Protocol -e http.request.method -e ip.src -e ip.dst -e text
```
**Sur windows :**
En wifi avec comme nom d'interface 'Wi-Fi'. Pour connaitre le nom des interfaces disponibles, ouvrez l'application wireshark, elles sont listées sur la page d'accueil
```
.\tshark.exe -i 'Wi-Fi' -Y 'http' -Tfields -e _ws.col.Protocol -e http.request.method -e ip.src -e ip.dst -e text
```
`-Y 'http'` : ne filtre que les paquets http (les https sont automatiquement assimilés comme étant des paquets 'TCP', logique)
`-Tfields` : permet d'afficher un résultat en fonction de collone déterminées (les '-e')
Une photo <span style="font-size:0.7em">dégueulasse</span> d'un exemple d'output de tshark (j'affiche les paquets TCP et HTTP pendant des échanges client/serveur via http)
![dd](https://i.ibb.co/8rpsJH1/IMG-20201231-161659292.jpg)
## Déroulement de la séance : réflexions
Je décris ici en grandes lignes le déroulement d'une séance. Vous pouvez bien sur faire tout autrement. Une ou plusieurs séances d'ailleurs ? à vous de voir !
Les apprenants doivent connaître un nombre conséquents de concepts :
- l'architecture client/serveur, l'existance des ports, les différentes couches réseaux (au moins TCP et HTTP, car pour rappel les paquets HTTP**S** sont assimilés comme étant des paquets TCP), les ip, ...
- les protocoles http et https, les requêtes type GET et POST, la création de formulaire HTML, ...
- l'analyse d'un package exécuté depuis un terminal (ici tshark)
- ...
Comme certains concepts sont relativement abstraits, il me semble judicieux de ne pas trop plonger les apprenants dans des détails techniques afin qu'ils se concentrent avant tout sur la bonne compréhension générale. C'est la raison pour laquelle je préfère fournir le code du serveur python aux apprenants. Le code ci-dessous :
```python
# fait en python v3.8
from http.server import BaseHTTPRequestHandler, HTTPServer
import ssl
class ServerHandler(BaseHTTPRequestHandler):
def _set_response(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
# Ici sont gérées les requêtes de type GET
def do_GET(self):
# ignore request to favicon
if self.path.endswith('favicon.ico'):
return
clientIp = str(self.client_address[0])
clientInformations = str(self.headers)
print("SERVEUR : [GET]")
print(f" - j'ai reçu une requête de type GET de la part de {clientIp}")
print(f" - de cette requête GET, je reçois automatiquement les informations suivantes : \n{clientInformations}")
print(" - je construis maintenant une page HTML que j'enverrai ensuite au client...attention c'est très rapide !")
formFile = open('formulaire.html')
formContentHTML = formFile.read()
print(f" - FINI ! j'ai construit la page HTML de mon côté (côté serveur donc) et je l'envoie au client {clientIp}\n\n")
self.wfile.write(formContentHTML.encode("utf-8"))
# Ici sont gérées les requêtes de type POST
def do_POST(self):
clientIp = str(self.client_address[0])
postData = self.rfile.read(int(self.headers['Content-Length'])).decode('utf-8') # <--- Gets the data itself
print("SERVEUR : [POST]")
print(f" - j'ai reçu une requête de type POST de la part de {clientIp}")
print(f" - cette requête POST contient des données de formulaire, ces données sont : \n{postData}\n")
print(f" - je confirme la bonne réception du message transmis par {clientIp}")
print(f" - je construis maintenant une page HTML contenant un simple message et je l'envoie à {clientIp}")
simpleMessage = "Le message a bien été transmis ! le contenu est visible sur le serveur..."
self.wfile.write(simpleMessage.encode('utf-8'))
def serverStart(useProtocolHTTPS):
if(useProtocolHTTPS):
# pour un navigateur web, saisir https://adresseDuSite:443 est pareil que https://adresseDuSite
# le port 443 est, par convention, le port utilisé par le protocole HTTPS
port = 443
else:
# pour un navigateur web, saisir https://adresseDuSite:80 est pareil que http://adresseDuSite
# le port 80 est, par convention, le port utilisé par le protocole HTTP
port = 80
server_address = ('', port)
httpd = HTTPServer(server_address, ServerHandler)
if(useProtocolHTTPS):
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True)
print("serveur : je suis démarré, je suis à l'écoute d'éventuelles requêtes ! \n")
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass
print("serveur : je me stope\n")
httpd.server_close()
# valeur de la variable à modifier selon si on souhaite utiliser le protocole HTTPS ou HTTPs
useProtocolHTTPS = False
serverStart(useProtocolHTTPS)
```
Afin que ce code soit, un minimum, compris par les apprenants (et donc utilisable/modifiable/bidouillable) doivent être au minimum au point sur l'utilisation des variables et des fonctions (entré/sortie). Les plus aguéris pourront passer du temps sur la classe ServerHandler.
Simuler une attaque informatique (#hacking) sera une bonne source de motivation pour nos informaticiens en herbe. Il sera par contre important de sensibiliser sur la pratique illégale de ce type de piratage et de rapeller qu'ici nous utilisons **notre** réseau et les données de **nos** formulaires.
Les apprenants n'auront pas la main sur l'ordinateur faisant tourner le `paquet sniffer tool`, je n'en vois pas la pertinence vis à vis des attendus du programme.
Par contre, il faudra afficher sur grand écran les transit des paquets dans le réseaux. (les apprenants jouerons au ping pong avec les paquets ;) )
Une fois l'environnement technique OK (ex : un hotspot, les apprenants connectés dessus, tshark qui tourne...). Le but du jeu pour les apprenants sera de démarrer des serveurs et de créer un formulaire html. Le serveur sera accessible via n'importe quel appareil 'client' (ordinateur, smartphone, ...). Ils constateront le transit des données du formulaire 'en clair' et devront modifier le code du serveur afin qu'il fonctionne avec le protocole https. À ce moment-là, vos apprenants pourront constater l'absence des données en clair sur le réseau en analysant le output de tshark.
Vous pourrez également par la suite modifier la commande tshark afin d'afficher tous les paquets http et tcp du réseaux et constater avec les apprenants que les paquets initialement en http sont tous devenus des paquets tcp 'chiffrés'.