Introduction
En apparence, la fonction str.lower() de Python semble simple et inoffensive. Pourtant, dans certaines situations spécifiques, elle peut introduire une vulnérabilité de sécurité sérieuse. Pour comprendre comment, nous devons plonger dans les spécificités des standards Internet et de l'Unicode.
Contexte et Normes Internet
De nombreux standards Internet ne supportent que les caractères ASCII, alors que le monde utilise bien plus que l'alphabet latin. Pour résoudre ce problème, une conversion de l'Unicode vers l'ASCII pour les noms de domaine est nécessaire. C'est ici qu'intervient NamePrep, défini dans la RFC 3491, une composante essentielle de l'internationalisation des noms de domaine dans les applications, connue sous le nom de "IDNA 2003".
Le Rôle de StringPrep et IDNA
L'algorithme StringPrep, défini dans la RFC 3454, est crucial dans ce processus. StringPrep inclut une étape de "case folding" (une forme de mise en minuscules/majuscules de codepoints), permettant des comparaisons insensibles à la casse des chaînes de caractères. En Python, cette étape est réalisée dans le module stringprep de la bibliothèque standard.
Le Problème avec str.lower()
Le cœur du problème réside dans l'utilisation de str.lower() dans l'implémentation de StringPrep en Python. Cette fonction utilise les données Unicode de la version spécifique de l'interpréteur Python, ce qui peut entraîner des incohérences avec les règles de conversion définies dans la RFC 3454 utilisant Unicode 3.2.0.
Exemple de Vulnérabilité
Prenons l'exemple du caractère 'Ꭰ' (U+13A0) :
- Valeur conforme à la RFC 3454 :
"ᎠᎠ".encode("idna")donne 'xn--58da' - Valeur utilisant le case-folding d'Unicode 17.0.0 :
"ᎠᎠ".encode("idna")donne 'xn--kz9aa'
Cette différence peut avoir des conséquences surprenantes et potentiellement dangereuses dans des applications critiques.
Comment Corriger le Tir
Pour éviter cette vulnérabilité, il est crucial d'utiliser les règles de conversion Unicode 3.2.0 et non les plus récentes. Heureusement, Python fournit un accès à la base de données Unicode 3.2.0 via unicodedata.ucd_3_2_0, ce qui permet de s'aligner avec la spécification de la RFC 3454.
Conclusion
La gestion des caractères et des normes Unicode est un aspect complexe mais essentiel pour garantir la sécurité et la compatibilité des applications. En comprenant les spécificités de l'implémentation de str.lower(), les développeurs peuvent éviter des pièges potentiels.
Discutons de ton projet en 15 minutes.