Dans PHP, la fonction HASH_EQUALS est une fonction utilisée pour comparer en toute sécurité si deux chaînes de hachage sont égales. Sa conception d'origine est d'éviter les attaques de temps, c'est-à-dire que les pirates utilisent de légères différences dans le temps de réponse du programme pour déduire si le mot de passe est correct. Cependant, dans une utilisation réelle, les développeurs font souvent des erreurs courantes, ce qui fait que la fonction HASH_EQUALS ne parvient pas à réaliser l'effet de sécurité attendu. Cet article traite de ces erreurs en détail et fournit des solutions.
Le but de HASH_EQUALS est d'empêcher la fuite d'informations sur le mot de passe par le décalage horaire par rapport aux chaînes. Contrairement à l'opérateur traditionnel == ou === , HASH_EQUAL ne dépend pas de la longueur ou du contenu de la chaîne pendant la comparaison, de sorte que les attaques temporelles peuvent être évitées.
L'une des erreurs courantes est confuse Hash_equals avec les opérations de comparaison de chaînes régulières. Par exemple:
<span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$password</span></span><span> == </span><span><span class="hljs-variable">$storedPasswordHash</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is correct!"</span></span><span>;
}
</span></span>
Ici, bien qu'il compare les valeurs de hachage, PHP utilise == OR == pour les opérations de comparaison ordinaires, qui peuvent faire différentes optimisations en fonction du contenu ou de la longueur de la valeur de hachage, entraînant une fuite de temps.
Solution:
Utilisez toujours Hash_Equals pour la comparaison de hachage:
<span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">hash_equals</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$storedPasswordHash</span></span><span>)) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is correct!"</span></span><span>;
}
</span></span>
Une autre erreur courante consiste à utiliser Hash_Equals lors de la comparaison du mot de passe d'origine à la valeur de hachage stockée. Il s'agit d'une idée fausse commune que les développeurs peuvent penser peuvent comparer directement le mot de passe en clair aux valeurs de hachage.
<span><span><span class="hljs-comment">// Démonstration d'erreur</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">hash_equals</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-title function_ invoke__">password_hash</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, PASSWORD_BCRYPT))) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is correct!"</span></span><span>;
}
</span></span>
Ce code est faux car Password_hash renvoie une valeur de hachage, et Hash_Equals ne peut être utilisé que pour comparer deux chaînes de hachage, et ne peut pas comparer directement le texte en clair et le hachage.
Solution:
Le mot de passe Effacer le texte et la valeur de hachage doivent être vérifiés d'abord en utilisant une fonction appropriée (telle que Password_verify ). Password_verify est une fonction conçue à cet effet:
<span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">password_verify</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$storedPasswordHash</span></span><span>)) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is correct!"</span></span><span>;
}
</span></span>
Lors de la comparaison , en plus de comparer le contenu de la valeur de hachage lui-même, il vérifie également si les longueurs des deux valeurs de hachage sont les mêmes. Si la longueur est incohérente, Hash_Equals reviendra immédiatement faux pour éviter de continuer à effectuer des calculs inutiles. Par conséquent, les développeurs peuvent ne pas réaliser dans certains cas que les valeurs de hachage entrantes diffèrent en longueur, provoquant des erreurs.
Par exemple, si vous effectuez un certain traitement sur le hachage (comme la troncature ou le formatage) lors du stockage, la longueur du hachage peut changer, provoquant l'échec de la comparaison.
Solution:
Assurez-vous d'utiliser un format cohérent lors du stockage et de la comparaison des hachages, en évitant les modifications inutiles. La fonction Password_Hash renvoie un format de hachage standard et essayez d'éviter le fonctionnement manuel.
Hash_Equals ne peut être utilisé que pour comparer les valeurs de hachage du même type. Si un algorithme différent est utilisé lors du hachage du mot de passe (par exemple en utilisant MD5 et Sha256 ), la comparaison HASH_EQUALS échoue car elle ne peut pas gérer les comparaisons entre différents algorithmes de hachage.
<span><span><span class="hljs-comment">// Démonstration d'erreur:md5 et sha256 Comparaison de hachage</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">hash_equals</span></span><span>(</span><span><span class="hljs-title function_ invoke__">md5</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>), </span><span><span class="hljs-title function_ invoke__">sha256</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>))) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is correct!"</span></span><span>;
}
</span></span>
Solution:
Le stockage et la comparaison du mot de passe sont utilisés en utilisant le même algorithme de hachage. Si vous utilisez la fonction Password_Hash pour générer des valeurs de hachage, il utilisera l'algorithme de hachage approprié (généralement Bcrypt ou Argon2), il vous suffit de le vérifier via Password_verify .
Hash_Equals renvoie une valeur booléenne indiquant si les deux valeurs de hachage sont égales. Si le développeur ignore le traitement correct de la valeur, cela peut entraîner des jugements logiques incorrects.
<span><span><span class="hljs-comment">// Démonstration d'erreur:Aucune valeur de retour traitée</span></span><span>
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">hash_equals</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$storedPasswordHash</span></span><span>)) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is correct!"</span></span><span>;
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is incorrect!"</span></span><span>;
}
</span></span>
L'erreur ici n'est pas Hash_Equals , mais plutôt le manque de traitement correct des processus dans des conditions d'erreur. Pour garantir la sécurité du processus de vérification du mot de passe, il est nécessaire de s'assurer que les commentaires sont corrects, que le mot de passe soit correct ou non.
Solution:
Assurez-vous de porter des jugements appropriés en fonction de la valeur de retour de Hash_Equals :
<span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">hash_equals</span></span><span>(</span><span><span class="hljs-variable">$password</span></span><span>, </span><span><span class="hljs-variable">$storedPasswordHash</span></span><span>)) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Password is correct!"</span></span><span>;
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-comment">// Manipulation d'erreurs plus sûre,Comme l'exploitation forestière</span></span><span>
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"Invalid password!"</span></span><span>;
}
</span></span>
Hash_Equals est une fonction PHP très importante pour éviter les attaques temporelles, mais elle n'est pas omnipotente, et une utilisation incorrecte peut entraîner des vulnérabilités de sécurité dans le programme. Les erreurs courantes incluent des comparaisons de hachage confuse, en comparant mal les mots de passe en texte clair avec les valeurs de hachage, la longueur de hachage incohérente, en utilisant différents algorithmes de hachage et en ignorant la valeur de retour. La clé pour résoudre ces erreurs est de comprendre les scénarios d'utilisation de Hash_Equals et d'utiliser Password_verify dans les scénarios appropriés pour vérifier l'exactitude du mot de passe.
Grâce à la mise en œuvre correcte et aux meilleures pratiques, la sécurité dans le processus de vérification du mot de passe peut être considérablement améliorée et les risques d'attaque potentiels peuvent être évités.