渗透培训笔记:Hash比较缺陷

admin 2023年11月16日08:48:39评论13 views字数 1247阅读4分9秒阅读模式
开发人员在对比Hash字符串的时候常用到等于(==)、不等于(!=)进行比较。如果Hash值以0e开头,后面都是数字,当与数字进行比较时,就会被解析成0 × 10n,会被判断与0相等,使攻击者可以绕过某些系统逻辑。

Hash一般翻译成“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射,pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。
var_dump('0e123456789'== 0);    //bool(true)var_dump('0e123456789'== '0');  //bool(true)var_dump('0e1234abcde'== '0');  //bool(false)

当密码经过散列计算后可能会以0e开头。下面代码在进行密码判断时可以绕过登录逻辑。

<?php  $username = $_POST['username'];  $password = $_POST['password'];  $userInfo = getUserPass($username);  //当userInfo中的密码以0e开头时,随意构造password即可登录系统。  if($userInfo['password']==md5($password)){ //Hash比较缺陷       echo '登录成功';  }else{       echo '登录失败';  }

使用hash_equals()函数比较Hash值,可以避免对比被恶意绕过。hash_equals()函数要求提供的两个参数必须是相同长度的字符串,如果所提供的字符串长度不同,会立即返回false。上面的代码应修改如下。

<?php  $username = $_POST['username'];  $password = $_POST['password'];  $userInfo = getUserPass($username);  //当userInfo中的密码以0e开头时,随意构造password即可登录系统。  if(hash_equals($userInfo['password']),md5($password))){ //Hash比较缺陷       echo '登录成功';  }else{       echo '登录失败';  }

hash_equals()函数在PHP5.6中得到支持,如果PHP版本号低于5.6,自己写个这样的函数就可以了,代码如下:

if(!function_exists('hash_equals')){    function hash_equals($a,$b){        if(!is_string($a)||!is_string($b)){            return false;        }        $len = strlen($a);        if($len !== strlen($b)){            return false;        }        $status = 0;        for($i = 0; $i<$len; $i++){            $status |= ord($a[i]) ^ ord($b[$i]);        }        return $status === 0;    }}

原文始发于微信公众号(衡阳信安):渗透培训笔记:Hash比较缺陷

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年11月16日08:48:39
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   渗透培训笔记:Hash比较缺陷http://cn-sec.com/archives/2209619.html

发表评论

匿名网友 填写信息