14 mai 2021

Manipulation d’adresse IP : Mauvaise implémentation ou RFC à revoir ?

python

Introduction

Ces dernières semaines, de nombreuses bibliothèques permettant de manipuler des adresses IP ont été signalées comme étant vulnérables à des attaques indéterminées comme des SSRF, des RFI, et des LFI.

Parmi les bibliothèques signalées, on retrouve le package nmp netmask (CVE-2021-28918), les modules ipaddress et netmask en Python (CVE-2021-29921), netmask pour Node.js (CVE-2021-29418) ainsi que des distributions Perl (Net-CIDR, Net-IPv4Addr, Net-CIDR-Lite et Net-IPAddress-Util). Ces bibliothèques sont utilisées par des millions de projets GitHub ainsi que de nombreux logiciels commerciaux.

Comment se présente une adresse IPv4 ?

La norme RFC3986 indique, dans sa section 3.2.2, que les adresses IPv4 doivent pouvoir être représentées textuellement sous la forme de quatre octets au format décimal séparés par des points. Les autres représentations étant à proscrire.

Une implémentation populaire du réseau IP se base sur la fonction inet_aton() de BSD. Cette implémentation fait office de référence officieuse.

Selon cette implémentation, les adresses IPv4 peuvent être de la forme :

a.b.c.dChaque partie est interprétée comme un octet de données et affectée, de gauche à droite, aux quatre octets d’une adresse Internet
a.b.cLa dernière partie est interprétée comme une quantité de 16 bits et placée dans les deux octets les plus à droite de l’adresse réseau
a.bLa dernière partie est interprétée comme une quantité de 24 bits et placée dans les trois octets les plus à droite de l’adresse réseau
aLa valeur est stockée directement dans l’adresse réseau sans réarrangement des octets

Il est également permis d’écrire les nombres dans des représentations hexadécimales et octales, en les préfixant respectivement avec 0x et 0.

Selon cette implémentation, les adresses IPv4 suivantes sont identiques et valides :

Représentation décimale : 104.40.229.241104.40.58865104.26803051747510769  Représentation octale : 0150.0050.0345.03610150.0050.01627610150.012162761015012162761  
Représentation hexadécimale : 0x68.0x28.0xe5.0xf10x68.0x28.0xe5f10x68.0x28e5f10x6828e5f1  Représentation « mixte » : 104.0050.0xe5f10150.0x28e5f10x68.2680305  

Explication de la vulnérabilité

Deux choix s’offrent donc aux développeurs :

  • Soit se baser sur la norme RFC3986 et considérer les représentations exotiques d’adresses IPv4 comme invalides.
  • Soit dans un souci d’interopérabilité, choisir de supporter les représentations exotiques d’adresses IPv4.

Les librairies vulnérables citées plus haut toléraient les adresses IPv4 contenant des représentations octales mais n’interprétaient pas correctement ces adresses. Les préfixes « 0 » (zéros) qui indiquent une représentation octale n’étaient pas pris en compte. En d’autres mots, l’adresse octale 010.010.010.010 n’était pas convertie en 8.8.8.8, mais en 10.10.10.10.

Figure 1 : L’adresse IPv4 010.010.010.010 correspond à l’adresse IPv4 8.8.8.8

Cette mauvaise interprétation de la représentation octale d’une adresse IPv4 peut permettre de contourner des mécanismes de filtrage basés sur l’adresse IP.

Correction de la vulnérabilité

Afin de corriger la vulnérabilité, les contributeurs de Python on fait le choix de considérer toute adresse IPv4 contenant un préfixe 0 comme invalide dans la version 3.9 de Python comme l’indique la RFC3986.

Conscients des problèmes d’interopérabilité que cela pourrait engendrer, les développeurs étudient un retour de la tolérance des représentations octales dans la version Python 3.10. Cette tolérance sera probablement à activer par le biais d’un argument spécifique.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *