PHP MD5函数漏洞

PHP MD5函数漏洞

0x01 MD5算法

首先还是说一下什么是MD5算法,MD5全名消息摘要算法(Message-Digest Algorithm 5),是一种密码散列函数,可以产生一个128位(16字节)的哈希值(hash value),用于确保信息传输的完整一致性,它的基础原理就是将数据预算变为另一固定长度的值

0x02 PHP中MD5函数的安全问题

1.PHP的比较运算符

这里主要说一下PHP中的=====
因为这两者所产生的问题利用方法并不相同
下面是文档中对于 ==、!=、===、!==的解释

例子 名称 结果
$a == $b 等于 TRUE,如果类型转换后 $a 等于 $b。
$a === $b 全等 TRUE,如果 $a 等于 $b,并且它们的类型也相同。
$a != $b 不等 TRUE,如果类型转换后 $a 不等于 $b。
$a !== $b 不全等 TRUE,如果 $a 不等于 $b,或者它们的类型不同。

=== 在进行比较的时候,会先判断两种字符串的类型是否相等,再比较

== 在进行比较的时候,会先将字符串类型转化成相同,再比较

如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
var_dump("admin"==0); 比较的时候,会将admin转化成数值,强制转化,由于admin是字符串,转化的结果是0自然和0相等
var_dump("0e123456"=="0e456789");相互比较的时候,会将0e这类字符串识别为科学技术法的数字,0的无论多少次方都是零,所以相等

PHP手册中

当一个字符串欸当作一个数值来取值,其结果和类型如下:如果该字符串没有包含’.’,’e’,’E’并且其数值值在整形的范围之内
该字符串被当作int来取值,其他所有情况下都被作为float来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为0。
所以就解释了"admin1"==1 =>False 的原因

2.PHP MD5中的函数漏洞

使用0E ByPass

文档MD5函数定义

1
md5 ( string $str [, bool $raw_output = FALSE ] ) : string

例子

1
2
3
4
5
6
7
8
9
10
11
<?php
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if($v1 != $v2 && md5($v1) == md5($v2)){
echo "Sucess";
echo '<br>';
}
}
highlight_file(__FILE__);
?>

PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。

经过以上特性我们得知

使用==时,由于e(科学记数法),每个都会转换为数字表示,因此每个都变为0 0 == 0是真的。

所以当部分字母哈希后开头以0E开头,PHP会认为他们相等

所以

1
var_dump(md5('240610708') == md5('QNKCDZO'));

输出为True

使用数组 ByPass

1
2
3
4
5
6
7
<?php
if($_GET['a']!==$_GET['b'] && md5($_GET['a'])===md5($_GET['b'])){
echo 'yes';
}else{
echo 'no';
}
?>

当满足上面的条件时,由于PHP中MD5函数的特性,可以使用数组绕过

1
md5([1,2]) == md5([3,4]) == NULL

故只要GET方法传入?a[]=1&b[]=2执行echo


PHP MD5函数漏洞
https://chrrr1y.github.io/2022/05/26/PHP MD5/
作者
Chrrr1y
发布于
2022年5月26日
更新于
2023年11月29日
许可协议