Création de paquets avec Scapy

CybersécuritéBeginner
Pratiquer maintenant

Introduction

Scapy est un programme et une bibliothèque puissants et interactifs de manipulation de paquets, écrits en Python. Il vous permet de forger ou de décoder des paquets pour un grand nombre de protocoles, de les envoyer sur le réseau, de les capturer et de faire correspondre les requêtes aux réponses.

Ce qui rend Scapy unique, c'est qu'il vous permet de travailler au niveau de la couche de construction des paquets, plutôt que de vous limiter à la couche socket ou application. Cela signifie que vous pouvez contrôler explicitement les en-têtes, les drapeaux (flags), les champs et les combinaisons de protocoles d'une manière que les bibliothèques client ordinaires masquent généralement.

Dans ce laboratoire, vous apprendrez les bases de la création de paquets avec Scapy. Vous commencerez par importer les modules nécessaires, puis vous passerez à la forge de paquets ICMP (ping) et TCP couche par couche. Enfin, vous enverrez ces paquets personnalisés et analyserez les réponses réseau. Cette expérience pratique vous donnera une compréhension plus profonde du fonctionnement interne des protocoles réseau et de la manière dont les professionnels de la sécurité testent les défenses réseau.

Importer les modules Scapy

Dans cette étape, vous allez configurer votre environnement Python et importer les modules Scapy nécessaires. Bien que Scapy puisse être utilisé comme une console interactive, l'écriture de scripts vous permet de sauvegarder, modifier et réutiliser facilement votre logique de création de paquets.

Il s'agit d'un changement de paradigme : au lieu d'utiliser des protocoles existants, vous les construisez. Au lieu de demander simplement à une application existante d'envoyer du trafic pour vous, vous définissez vous-même à quoi ce trafic doit ressembler.

Tout d'abord, assurez-vous d'être dans votre répertoire de travail par défaut. Vous pouvez utiliser la commande pwd pour le vérifier, mais vous devriez déjà être dans ~/project.

Créez un nouveau fichier Python nommé packet_crafter.py à l'aide de l'éditeur de texte nano.

nano packet_crafter.py

Dans ce fichier, vous devez importer la bibliothèque Scapy. La méthode standard pour utiliser Scapy dans des scripts consiste à importer toutes les fonctions du module scapy.all. Ajoutez les lignes suivantes à votre script :

from scapy.all import *

print("Scapy modules imported successfully.")

Enregistrez le fichier avec Ctrl+O et Enter. Si vous souhaitez continuer à construire le script avant de le tester, vous pouvez rester dans nano. Utilisez Ctrl+X lorsque vous êtes prêt à revenir au terminal.

Maintenant, exécutez votre script avec Python pour vous assurer qu'il n'y a pas d'erreurs de syntaxe et que la bibliothèque Scapy se charge correctement. Comme la création de paquets réseau bruts nécessite des privilèges élevés, vous devez exécuter le script avec sudo.

sudo python3 packet_crafter.py

Vous devriez voir une sortie similaire à la suivante, indiquant que l'opération a réussi :

Scapy modules imported successfully.

Dans certains environnements de laboratoire, Scapy peut afficher un avertissement supplémentaire provenant de paquets Python optionnels tels que matplotlib avant le message de succès. Si vous voyez toujours Scapy modules imported successfully., vous pouvez passer à l'étape suivante.

Forger une requête ICMP Echo

Dans cette étape, vous allez forger un paquet ICMP Echo Request, communément appelé "ping". Les paquets réseau sont construits en couches, suivant le modèle OSI. Dans Scapy, vous pouvez empiler ces couches en utilisant l'opérateur /.

La superposition est l'un des concepts les plus importants à assimiler ici. Chaque couche ajoute ses propres champs et responsabilités. Scapy reflète directement ce modèle, c'est pourquoi sa syntaxe rend la structure des paquets plus facile à appréhender.

Un ping ICMP nécessite une couche IP (couche réseau) pour spécifier les adresses source et destination, et une couche ICMP pour définir le type de message.

Si packet_crafter.py est toujours ouvert dans nano, continuez à le modifier. Sinon, rouvrez-le :

nano packet_crafter.py

Ajoutez le code suivant à la fin de votre script. Ce code crée un objet IP ciblant le serveur DNS public de Google (8.8.8.8), crée un objet ICMP et les empile ensemble. La méthode show() affichera une ventilation détaillée de la structure du paquet.

## Create an IP layer targeting Google's DNS
ip_layer = IP(dst="8.8.8.8")

## Create an ICMP layer (Echo Request)
icmp_layer = ICMP()

## Stack the layers to form the final packet
icmp_packet = ip_layer / icmp_layer

print("\n--- ICMP Packet Structure ---")
icmp_packet.show()

Enregistrez le fichier avec Ctrl+O et Enter. Vous pouvez rester dans nano et passer à l'étape suivante si vous souhaitez terminer le script avant de l'exécuter.

Exécutez votre script mis à jour pour voir la structure du paquet que vous venez de forger.

sudo python3 packet_crafter.py

Vous verrez une sortie détaillée montrant les valeurs par défaut que Scapy a automatiquement remplies pour vous, telles que la version du protocole, le TTL (Time To Live) et le type ICMP.

--- ICMP Packet Structure ---
###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     =
  frag      = 0
  ttl       = 64
  proto     = icmp
  chksum    = None
  src       = 10.0.2.15
  dst       = 8.8.8.8
  \options   \
###[ ICMP ]###
     type      = echo-request
     code      = 0
     chksum    = None
     id        = 0x0
     seq       = 0x0
     unused    = ''

Créer un paquet TCP SYN personnalisé

Dans cette étape, vous allez créer un paquet TCP SYN. Ce type de paquet spécifique est fréquemment utilisé dans le scan réseau (comme le scan furtif de Nmap) pour vérifier si un port spécifique est ouvert sur une machine cible sans établir complètement une connexion.

C'est un bon exemple de la façon dont de petits changements dans l'en-tête produisent des comportements réseau très différents. Vous ne modifiez pas l'hôte ou le port de destination, seulement les drapeaux et les champs de protocole, mais ces détails définissent la signification du paquet et la façon dont la cible l'interprétera.

Tout comme pour le paquet ICMP, un paquet TCP nécessite une couche IP sous-jacente. Par-dessus, vous ajouterez une couche TCP où vous pourrez spécifier le port de destination et les drapeaux TCP. Le drapeau S signifie SYN (Synchronize).

Si vous êtes toujours dans la même session nano, continuez à modifier packet_crafter.py. Sinon, rouvrez-le :

nano packet_crafter.py

Ajoutez le code suivant à votre script. Nous réutiliserons le ip_layer créé à l'étape précédente et empilerons une nouvelle couche TCP par-dessus, ciblant le port 80 (HTTP).

## Create a TCP layer targeting port 80 with the SYN flag
tcp_layer = TCP(dport=80, flags="S")

## Stack the IP and TCP layers
tcp_packet = ip_layer / tcp_layer

print("\n--- TCP SYN Packet Structure ---")
tcp_packet.show()

Enregistrez le fichier avec Ctrl+O et Enter. Quittez avec Ctrl+X uniquement lorsque vous souhaitez exécuter le script depuis le terminal, ou continuez à modifier pour passer à l'étape finale.

Exécutez à nouveau le script pour inspecter la structure de votre nouveau paquet TCP SYN.

sudo python3 packet_crafter.py

La sortie inclura désormais les détails de la couche TCP, montrant le port de destination réglé sur http (port 80) et les drapeaux réglés sur S.

--- TCP SYN Packet Structure ---
###[ IP ]###
  version   = 4
  ihl       = None
  tos       = 0x0
  len       = None
  id        = 1
  flags     =
  frag      = 0
  ttl       = 64
  proto     = tcp
  chksum    = None
  src       = 10.0.2.15
  dst       = 8.8.8.8
  \options   \
###[ TCP ]###
     sport     = ftp_data
     dport     = http
     seq       = 0
     ack       = 0
     dataofs   = None
     reserved  = 0
     flags     = S
     window    = 8192
     chksum    = None
     urgptr    = 0
     options   = []

Envoyer et analyser la réponse réseau

Dans cette dernière étape, vous allez réellement envoyer le paquet ICMP que vous avez forgé sur le réseau et capturer la réponse.

L'envoi du paquet complète le modèle mental : définir les couches, construire le paquet, le transmettre, puis interpréter la réponse. C'est la même boucle de haut niveau qui se cache derrière de nombreux outils de test réseau personnalisés.

Scapy fournit plusieurs fonctions pour envoyer des paquets. La fonction sr1() est particulièrement utile car elle envoie un paquet et attend de renvoyer la toute première réponse reçue. Le "s" signifie send (envoyer), "r" pour receive (recevoir) et "1" pour un paquet.

Si vous avez gardé le fichier ouvert, continuez à le modifier. Sinon, rouvrez packet_crafter.py :

nano packet_crafter.py

Ajoutez le code suivant pour envoyer le icmp_packet et analyser la réponse. Nous incluons un paramètre timeout afin que le script ne reste pas bloqué indéfiniment si le paquet est perdu ou bloqué.

print("\n--- Sending ICMP Packet ---")
## Send the packet and wait for 1 response, with a timeout of 2 seconds
## verbose=0 hides the default Scapy sending output for cleaner results
response = sr1(icmp_packet, timeout=2, verbose=0)

if response:
    print(f"Response received from: {response[IP].src}")
    print("\n--- Response Packet Structure ---")
    response.show()
else:
    print("No response received. The packet might have been dropped.")

Enregistrez le fichier et quittez l'éditeur.

Exécutez votre script pour envoyer le paquet sur Internet et attendre que le serveur DNS de Google réponde.

sudo python3 packet_crafter.py

Si le réseau autorise la requête ICMP, vous verrez la structure du paquet de réponse. Notez que le type ICMP dans la réponse est echo-reply.

--- Sending ICMP Packet ---
Response received from: 8.8.8.8

--- Response Packet Structure ---
###[ IP ]###
  version   = 4
  ihl       = 5
  tos       = 0x0
  len       = 28
  id        = 0
  flags     =
  frag      = 0
  ttl       = 114
  proto     = icmp
  chksum    = 0x67d8
  src       = 8.8.8.8
  dst       = 10.0.2.15
  \options   \
###[ ICMP ]###
     type      = echo-reply
     code      = 0
     chksum    = 0xffff
     id        = 0x0
     seq       = 0x0
     unused    = ''
###[ Padding ]###
        load      = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

Résumé

Vous avez appris à configurer un script Python avec Scapy, à forger manuellement des paquets ICMP et TCP couche par couche en utilisant l'opérateur /, et à envoyer ces paquets sur le réseau pour analyser les réponses brutes. Ces connaissances fondamentales sont cruciales pour comprendre le fonctionnement des protocoles réseau, effectuer des évaluations de sécurité et développer des outils d'analyse réseau personnalisés.