J'ai récemment lu la documentation sur la langue Rust et j'ai vu this :
Par défaut, HashMap utilise une fonction de hachage cryptographiquement sécurisée qui peut offrir une résistance aux attaques par déni de service (DoS). Ce n'est pas l'algorithme de hachage le plus rapide disponible, mais le compromis pour une meilleure sécurité qui accompagne la baisse des performances en vaut la peine.
En tant que personne sans expérience en langage système, je n'ai jamais entendu parler d'attaques en mémoire basées sur le mauvais algorithme de hachage. J'ai donc eu quelques questions:
Comment l'algorithme de hachage sécurisé empêche-t-il un DoS ou toute autre attaque?
Quand devrais-je opter pour un hachage plus sécurisé plutôt que plus rapide?
Parfois, les applications utilisent des données non fiables comme clé dans une carte de hachage. Une implémentation simple peut permettre aux données non fiables de provoquer une attaque par déni de service.
Les cartes de hachage sont rapides - O(1) - dans le meilleur des cas, mais lentes - O(n) - dans le pire des cas. En effet, les clés sont normalement dans des compartiments séparés, mais certaines valeurs peuvent entraîner le même hachage - une collision - qui est géré par une liste chaînée plus lente. Avec des données aléatoires, les collisions seront rares. Cependant, certaines implémentations ont une vulnérabilité où les données malveillantes peuvent provoquer de nombreuses collisions, ce qui rend la carte de hachage lente. Il y a quelques années, il y avait un Linux kernel DoS à cause de cela.
La cause première de la vulnérabilité Linux était que le hachage était prévisible. Il a été corrigé en introduisant une clé dans la fonction de hachage qu'un utilisateur distant ne connaîtrait pas. Je ne sais pas exactement comment fonctionnent les cartes de hachage Rust, mais je m'attends à ce qu'elles utilisent un type similaire de hachage à clé.
Vous devez opter pour un hachage plus sécurisé chaque fois que vous utilisez des données non fiables comme clé.
Les opérations d'insertion, de recherche et de suppression sur les tables de hachage ont un comportement dans le pire des cas O(n). Si un attaquant peut choisir des clés à insérer dans une table de hachage et calculer lui-même la fonction de hachage, alors ce qui crée une possibilité de déni de service. Il leur suffit de choisir des clés mappant vers le même compartiment.
La citation suggère que l'utilisation d'un algorithme de hachage cryptographique (SHA, MD5, Blake, Skein, etc.) résout le problème. Cette interprétation est totalement incorrecte . L'algorithme utilisé par HashMap de Rust est appelé SipHash . Il s'agit d'un algorithme de hachage. Et c'est un algorithme cryptographique. Mais ce n'est pas un fonction de hachage cryptographique . Le terme correct pour SipHash dans le monde de la cryptographie est PRF .
La principale différence est que (en cryptographie) tous les détails d'une fonction de hachage peuvent être connus du public. Un PRF, d'autre part, nécessite une clé secrète. Sans les informations secrètes, il n'y a aucun moyen d'anticiper, quelle que soit l'entrée, la sortie. (Tous les autres détails sont publics.)
Quelque chose comme SHA-2 n'empêchera pas le déni de service. Il sera totalement non biaisé pour les intrants non contradictoires. (Parce que les fonctions de hachage cryptographiques peuvent être modélisées comme oracles aléatoires .) Cependant, n'importe qui peut évaluer le SHA-2 ordinaire, afin que quelqu'un puisse trouver les collisions de tables de hachage par force brute.
Le fait qu'une fonction de hachage cryptographique soit résistante aux collisions (avec une sortie d'au moins 256 bits) ne se traduit pas par un manque de collisions dans le cas des tables de hachage. En fin de compte, votre fonction de hachage, pour une table avec des compartiments n, sera réduite à l'une des valeurs possibles n. Par essais et erreurs, vous pouvez trouver une entrée qui correspond à un compartiment spécifique environ une fois tous les n essais. Aucune table de hachage n'utilise suffisamment de compartiments pour rendre cela impossible.
L'utilisation d'une fonction de hachage sans clé est intrinsèquement vulnérable au déni de service, quelle que soit la qualité de la fonction de hachage. Le fait que l'attaquant et server-with-a-hash-map interrogent tous les deux Oracle permet à un DOSer d'utiliser des entrées spécifiquement choisies pour bloquer votre CPU.
Les PRF comme SipHash n'ont pas cette vulnérabilité s'ils sont utilisés correctement. Le serveur utilise un Oracle/fonction choisi dans un pool de 2128 fonctions possibles. Pour exploiter une fonction de hachage basée sur PRF (table de hachage), l'attaquant doit deviner lequel des 2128 fonctions qu'il devrait utiliser (une "récupération de clé") ou pour trouver un biais dans le PRF indépendant de la clé (un moyen de distinguer le PRF d'un Oracle aléatoire).
Enfin, il existe des nuances plus confuses impliquant des algorithmes de hachage. Mais résumé simplement:
Je suis d'accord, c'est un peu vague et cela dépendra fortement de la façon dont les hashmaps sont utilisés.
Voici ma supposition: disons que vous acceptez les commentaires des utilisateurs, dites [Firstname.Lastname]
et en l'utilisant comme valeur de recherche dans votre table de hachage. Supposons que vous construisez votre table de hachage à l'aide de la fonction de hachage simple qui prend les initiales afin que [Firstname.Lastname] --> FL
alors il serait facile pour un attaquant de soumettre des charges de valeurs qui hachent toutes la même chose. Cela transformerait essentiellement votre table de hachage en une liste qui annule tous les gains de performances liés à l'utilisation d'une table de hachage. Recherches lentes = déni de service.
AA -> [ ]
AB -> [ ]
...
FK -> [ ]
FL -> [First.Last, F1.F2, F1.F2, Fanotheu.Lonteuh, ...]
FM -> [ ]
...
ZZ -> [ ]
Les fonctions de hachage cryptographique sont spécialement conçues pour éviter cela car il est très difficile de construire deux entrées différentes qui ont la même valeur de hachage (appelées collisions).
Quand devrais-je opter pour un hachage plus sécurisé plutôt que plus rapide?
La réponse est simple: optez pour un hachage cryptographique chaque fois que la valeur de recherche est fournie par les utilisateurs et pourrait être conçue de manière malveillante. Si les valeurs de recherche proviennent d'une source interne que vous approuvez comme non malveillante et répartie uniformément, vous pouvez utiliser un hachage plus rapide.