PHP的hash比较缺陷

漏洞

我们比较 hash 字符串的时候,常常用到 等于(==)、不等于(!=) 来进行比较。
但是hash 的值如果是以0e 开头,并且后面全是数字的话, 在与数字进行比较的时候, 就会被解析成0 × \times × 10n,则会判断和0相等,造成一些漏洞

例如: 240610708 的hash值就是 0e + 数字的

<?php
// 假设用户设置的密码为这个数字240610708,在数据库为 md5(“240610708”)
$password = "0e462097431906509019562988736854";

$userpwd = $_GET['userpwd']; // 假设用户输入了314282422居然登陆成功了

// 用户输入为0时也会登陆成功, 原因就是两个密码都是以0e开头,判断为相等
if(md5($userpwd ) == $password) {
    echo "登陆成功";
}else {
    echo "密码不正确";
}

解决方案

使用 hash_equals() 方法来进行hash值得比较。
hash_equals 是在5.6版本以上, 系统低于5.6 建议自行实现该函数

<?php
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成 0e 开头的一些字符串

240610708 
0e462097431906509019562988736854

314282422 
0e990995504821699494520356953734

571579406 
0e972379832854295224118025748221

903251147 
0e174510503823932942361353209384
1110242161 
0e435874558488625891324861198103

1320830526 
0e912095958985483346995414060832

1586264293 
0e622743671155995737639662718498

2302756269 
0e250566888497473798724426794462

2427435592 
0e067696952328669732475498472343

2653531602 
0e877487522341544758028810610885

3293867441 
0e471001201303602543921144570260

3295421201 
0e703870333002232681239618856220

3465814713 
0e258631645650999664521705537122

3524854780 
0e507419062489887827087815735195

3908336290 
0e807624498959190415881248245271

4011627063 
0e485805687034439905938362701775

4775635065 
0e998212089946640967599450361168

4790555361 
0e643442214660994430134492464512

5432453531 
0e512318699085881630861890526097

5579679820 
0e877622011730221803461740184915

5585393579 
0e664357355382305805992765337023

6376552501 
0e165886706997482187870215578015

7124129977 
0e500007361044747804682122060876

7197546197 
0e915188576072469101457315675502

7656486157 
0e451569119711843337267091732412

QLTHNDT 
0e405967825401955372549139051580

QNKCDZO 
0e830400451993494058024219903391

EEIZDOI 
0e782601363539291779881938479162

TUFEPMC 
0e839407194569345277863905212547

UTIPEZQ 
0e382098788231234954670291303879

UYXFLOI 
0e552539585246568817348686838809

IHKFRNS 
0e256160682445802696926137988570

PJNPDWY 
0e291529052894702774557631701704

ABJIHVY 
0e755264355178451322893275696586

DQWRASX 
0e742373665639232907775599582643

DYAXWCA 
0e424759758842488633464374063001

GEGHBXL 
0e248776895502908863709684713578

GGHMVOE 
0e362766013028313274586933780773

GZECLQZ 
0e537612333747236407713628225676

NWWKITQ 
0e763082070976038347657360817689

NOOPCJF 
0e818888003657176127862245791911

MAUXXQC 
0e478478466848439040434801845361

MMHUWUV 
0e701732711630150438129209816536


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值