md5常见问题及绕过
字数 1143 2025-08-11 17:40:08
MD5安全漏洞与绕过技术详解
1. MD5基础与常见应用场景
MD5(Message-Digest Algorithm 5)是一种广泛使用的密码散列函数,产生128位(16字节)的散列值。在CTF比赛和Web安全中,MD5经常被用于密码存储、数据完整性校验等场景。
2. MD5常见攻击类型
2.1 MD5爆破攻击
场景:当系统只验证MD5值的部分片段时,可以通过暴力破解找到匹配的值。
示例代码:
substr(md5(captcha), -6, 6) == "5bcba3"
爆破脚本:
<?php
for($i=0;$i<10000;$i++){
if(substr(md5($i),-6,6)=="5bcba3"){
echo $i;
break;
}
}
?>
防御建议:避免只验证部分哈希值,使用完整的哈希比较。
2.2 MD5弱比较绕过
形式:
if($a != $b && md5($a) == md5($b))
2.2.1 0e绕过技术
原理:PHP的弱类型比较会将"0e"开头的字符串视为科学计数法(0的任意次方都是0)。
已知0e开头的MD5值:
- 240610708: md5值为"0e462097431906509019562988736854"
- QNKCDZO: md5值为"0e830400451993494058024219903391"
2.2.2 数组绕过技术
原理:对数组进行MD5运算会返回NULL,NULL == NULL为true。
示例:
a[]=a&b[]=b
2.3 MD5强比较绕过
形式:
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2']))
绕过方法:
- 0e绕过在强比较中失效(因为===会严格比较类型和值)
- 数组绕过仍然有效
2.4 MD5强碰撞攻击
形式:
if((string)$_POST['a']!==(string)$_POST['b'] && md5($_POST['a'])===md5($_POST['b']))
特点:
- 强制转换为字符串,禁用数组绕过
- 需要使用真实的MD5碰撞
实现方法:
- 使用工具如fastcoll生成碰撞文件
- 示例:
$a = file_get_contents("a_msg1.txt");
$b = file_get_contents("a_msg2.txt");
// $a !== $b 但 md5($a) === md5($b)
2.5 加密后弱相等
形式:
if ($md5==md5($md5))
绕过方法:寻找0e开头且MD5后仍为0e开头的字符串,如"0e215962017"。
2.6 MD5特殊字符问题
原理:PHP的md5()函数有两个参数:
md5(string $string, bool $binary = false): string
区别:
md5($str, false):返回32字符十六进制数(默认)md5($str, true):返回16字节原始二进制数据,可能包含特殊字符
SQL注入应用:
select * from 'admin' where password=md5($pass,true)
利用方法:寻找MD5二进制结果中包含'or'等SQL关键字的值。
3. 防御建议
- 避免使用MD5进行密码存储,改用bcrypt、Argon2等现代哈希算法
- 始终使用严格比较(===)而非弱比较(==)
- 对用户输入进行严格过滤和类型检查
- 考虑使用HMAC加盐方案增强安全性
- 对于关键系统,考虑使用多重哈希方案
4. 相关CTF题目
- 攻防世界-SSRF Me
- buu-easy_web
- 涉及MD5特殊字符的题目
5. 扩展知识
- MD5碰撞原理:王小云教授提出的MD5碰撞攻击方法
- 彩虹表攻击与防御
- 加盐哈希的最佳实践
- 密码哈希竞赛(PHC)推荐的算法
通过理解这些MD5相关的漏洞和绕过技术,安全人员可以更好地评估系统安全性并设计更强大的防御机制。