De man 3 memcmp
:
N'utilisez pas
memcmp()
pour comparer les données critiques pour la sécurité, telles que les secrets cryptographiques, car le temps CPU requis dépend du nombre d'octets égaux. Au lieu de cela, une fonction qui effectue des comparaisons en temps constant est requise.
Pourquoi est-ce si? Je pense que si quelqu'un a accès à la machine qui traite ces "données critiques pour la sécurité", ces secrets sont déjà compromis car cette personne peut les extraire de la RAM. Ou, si cette personne n'a pas accès à la machine, elle ne peut de toute façon pas mesurer avec précision le temps CPU.
L'exploitation des informations de synchronisation est une attaque possible contre des choses comme les systèmes d'authentification par mot de passe.
Conceptuellement, memcmp()
fonctionne en comparant deux ensembles de données binaires octet par octet (en réalité, les processeurs peuvent comparer plusieurs octets à la fois, selon les optimisations, mais les mêmes principes ci-dessous s'appliqueront). La fonction démarre au début des données, compare chaque octet séquentiellement et se termine dès qu'elle trouve une différence. Si aucune différence n'est trouvée, la fonction renvoie un code indiquant que les données correspondent.
Parce que la fonction revient dès qu'elle trouve une différence, un attaquant avec une horloge suffisamment précise peut déduire des informations secrètes. Ils peuvent induire des appels à memcmp()
avec différentes entrées et en mesurant quelles entrées prennent plus de temps, ils peuvent déduire ce que pourrait être un secret stocké.
Exemple:
Considérons un système de hachage de mot de passe classique. Supposons que votre mot de passe soit stocké sous forme de hachage secret, par exemple Ek8fAMjPhBo
. (Ce hachage a été généré à l'aide du schéma DES fourni par la fonction Linux crypt()
avec un sel de na
et un mot de passe de secret
. Notez que cette fonction n'est pas sécurisée et que vous ne devez pas l'utiliser dans des systèmes réels.)
Dans un système de mot de passe fort, votre hachage Ek8fAMjPhBo
Est stocké, mais votre mot de passe ( n'est pas stocké. Lorsque vous êtes invité à vous authentifier, le système prendra votre mot de passe, le hachera, puis comparera les deux hachages l'un à l'autre. Si les hachages résultants correspondent, vous avez accès au système, si les hachages ne correspondent pas, votre mot de passe est rejeté. Cela permet au système de vérifier si vous connaissez ou non votre mot de passe sans réellement le stocker lui-même.
Comment un attaquant peut utiliser le timing pour attaquer ce système:
Pour attaquer ce système, un adversaire n'a vraiment besoin que de savoir quel mot de passe hache le hachage stocké. Normalement, le hachage stocké est gardé secret, mais l'adversaire peut utiliser des informations de synchronisation pour déduire ce que le hachage stocké pourrait être. Une fois que l'adversaire a déduit le hachage stocké, il est vulnérable à des attaques beaucoup plus rapides et hors ligne Rainbow table, ainsi qu'à contourner les mesures de sécurité en ligne comme les limites de nouvelle tentative de mot de passe.
Le système de mot de passe ci-dessus doit comparer un hachage candidat avec le hachage stocké afin de fonctionner correctement. Supposons qu'il faut 10 nanosecondes pour comparer chaque octet du hachage candidat au hachage stocké secret. Si aucun octet ne correspond (une comparaison), memcmp()
prendra environ 10ns. Si un octet correspond (deux comparaisons), memcmp()
prendra environ 20ns. Votre attaquant génère quelques mots de passe et les exécute à travers le système, enregistrant la durée de chacun. Supposons que les premières comparaisons de hachage prennent environ 10 ns chacune, puis reviennent, indiquant qu'aucun des octets du hachage candidat ne correspond au hachage stocké. Après quelques essais, l'une des comparaisons de hachage prend 20 ns, ce qui indique que le premier octet du hachage candidat correspond au hachage stocké. Dans l'exemple ci-dessus, cela indique que l'attaquant a déduit que le premier octet du hachage Ek8fAMjPhBo
Est E
.
Les hachages par conception ont la propriété que vous ne pouvez pas prédire quel hachage correspondra à quel mot de passe, donc par exemple ceci ne le fait pas indique à l'attaquant que le mot de passe commence par s
. Cependant, l'attaquant pourrait avoir une grande table de hachages pré-calculés (a Table arc-en-ciel) afin qu'ils puissent rechercher d'autres mots de passe qui hachent une chaîne commençant par E
. Après avoir essayé suffisamment de hachages, ils obtiendront finalement une entrée qui fera prendre à memcmp()
30ns, ce qui indique que les deux premiers octets correspondent, et ils ont déduit que les deux premiers octets du hachage sont Ek
. Ils répètent ce processus encore et encore jusqu'à ce qu'ils déduisent la totalité ou la majeure partie du hachage. À ce stade, ils connaissent le mot de passe ou peuvent le forcer brutalement avec une attaque de table Rainbow traditionnelle.
C'est un peu hypothétique, mais vous pouvez trouver de nombreuses informations pratiques sur le timing des attaques ailleurs sur le net, par exemple:
https://research.kudelskisecurity.com/2013/12/13/timing-attacks-part-1/
Le problème n'est pas vraiment de faire valoir qu'une attaque latérale est pratique dans n'importe quelle application que vous avez en tête pour votre système .
Un meilleur argument à faire est que
Les attaques par canal latéral ont tendance à être possibles dans plus de situations que la plupart des développeurs ne peuvent penser de manière spontanée.
Dans toute situation donnée, de manière fiable se convaincre qu'il y a non possibilité de chronométrer les attaques est beaucoup plus de travail au moment du développement que d'utiliser simplement une méthode de comparaison sécurisée comme SOP. Plus de travail signifie à la fois plus de coûts et un risque plus élevé de se tromper.
Autrement dit, ce sont des fruits à faible pendaison. Avoir une politique de "ne jamais utiliser memcmp
sur les données critiques pour la sécurité", est supérieur à une politique de "bien utiliser memcmp
quand cela est sûr" sur presque tous les paramètres que je peux imaginer.
Si, extraordinairement, vous êtes dans une situation où le rasage d'une fraction de microseconde de temps CPU sur chaque comparaison non correspondante (ce qui est généralement le cas non courant en premier lieu!) vous fera économiser suffisamment d'argent pour que cela vaille la peine de consacrer des efforts à une analyse de sécurité appropriée, puis vous aurez beaucoup de documents commerciaux prouvant ce fait.
(Et même ainsi, le simple fait de lire des bandes dessinées pendant le temps qu'il vous faudrait pour faire cette analyse pendant que vous laissez la loi de Moore faire le travail pour vous vous permettra probablement d'économiser également ces microsecondes CPU).
Il appartient à une catégorie des attaques par canal latéral (mêmes exigences que pour RSA, le temps d'exécution avec la clé privée doit être constant). De plus, ce n'est pas nécessairement que RAM est compromis, les opérations peuvent être exécutées sur TEE (environnement d'exécution de confiance).