MD5的弱类型比较和强碰撞and md5()函数的原始二进制数据探究
前言
关于PHP中== 和===的用法:
- ===是恒等计算符,同时检查表达式的值与类型; ==是比较运算符,不会检查条件表达式的类型。
- PHP使用==比较数字和字符串时,将字符串转换为数字后与数字进行比较:
1 | 字符串以数字开头:取前面的数字; |
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0.
所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
==比较
解法一
由于md5不能加密数组,在加密数组是会返回NULL,因此,我们可以传入两个数组进行md5缺陷绕过。
解法二
可以传入两个md5加密后是0e开头的字符串,这个0e开头的字符串,后面只能为纯数字,这样PHP在进行科学计算法时才会将它转化为0.
- 脚本
1 | <?php |
- 一些值
1 | QNKCDZO |
===比较
强类型比较,不仅比较值,还比较类型,0e会被当做字符串,所以不能用0e来进行。
解法一
也可以通过md5缺陷绕过传入两个数组来做,但不能在使用0e开头的字符串,因为===是md5的强碰撞,进行了严格的过滤。
解法二
使用md5加密后两个完全相等的字符串来绕过。
我们可以使用快速MD5碰撞生成器来构建两个MD5一样,但是内容完全不一样的字符。
程序:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip
源码:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5_source.zip
构造
创建一个文本文件,写入任意的文件内容,命名为ywj.txt (源文件)
运行fastcoll输出以下参数。-p 是源文件,-o是输出文件。
1 | fastcoll_v1.0.0.5.exe -p ywj.txt -o 1.txt 2.txt |
测试
对生产的1.txt和2.txt文件进行测试.
1 | <?php |
1 |
|
可以看到,1.txt和2.txt二进制md5加密后的结果完全相同。由于1.txt和2.txt文件中含有不可见字符,所以需要将其url编码后使用。可以看到url编码后的两个字符串不完全相同,满足我们输入两个不同参数的需要。
当题目限制不能传入数组,只能传入字符串时,就只能采用解法2.
原文传送门: https://blog.csdn.net/qq_38154820/article/details/113750318
例题
BUUCTF__[BJDCTF2020]Easy MD5
- 一开始进入看到查询框就还以为是SQL注入,输入万能密码、1、单引号啥的都没啥反应,明明在看到是get传参password嘛,还是没啥头绪,就翻一下wp,emmm 是藏在消息头里的SQL语句。
解题的关键还在于SQL语句password=md5($pass,true)的理解。
如下:
md5(string, raw) raw 可选,默认为false
true:返回16字符2进制格式
false:返回32字符16进制格式
简单来说就是 true将16进制的md5转化为字符了,如果某一字符串的md5恰好能够产生如’or ’之类的注入语句,就可以进行注入了。
提供一个字符串:ffifdyop
md5加密后的值为:276f722736c95d99e921722cf9ed621c
转成字符串后: ‘or’6 (关于这一步骤的具体内容会在本文章的最后作为补充。)
就是说password=md5($pass,true)返回的是字符串,而输入ffifdyop查询之后就会执行SQL语句:select * from ‘admin’ where password=’ ‘or ‘6’
- 之后返回如下页面,查看源码,知道是一个弱类型的比较,get方式构造payload绕过:**?a[]=1&b[]=2**
md5不能处理数组,遇到数组不报错但是会将其转变成NULL,null=null。所以采用md5缺陷绕过。
当然也可以采用上述的解法二运用0e开头的md5值相同的字符串进行传参。
如:
1 | ?a=QNKCDZO&b=240610708 |
- 得到一个新的页面,代码审计,POST方式,传param1和param2两个参数,这两个参数还不能相等,但是md5转换后的值还要相等(0e开头),md5碰撞的强类型比较,依然可以采用md5数组绕过,当然解法二中运用字符串也是可以的。
构造payload如下:param1[]=1¶m2[]=2
一些关于快速md5碰撞生成器的补充
使用fastcoll进行md5碰撞:
- 生成两个文件:
1 | fastcoll_v1.0.0.5.exe -p C:\windows\notepad.exe -o D:\notepad1.exe D:\notepad2.exe |
- 在winhex中对比发现文件内容不一样:
- 使用 certutil 命令查看一下md5;
- 发现文件虽然内容不一样,但是md5值是一样的,说明了用 md5 做文件校验并不安全。
两个程序文件的MD5一致,却又都能正常运行,并且可以做完全不同的事情:
1 | http://www.win.tue.nl/hashclash/SoftIntCodeSign/HelloWorld-colliding.exe |
这两个程序会在屏幕上打印出不同的字符,但是它们的MD5都是一致的。
使用领域
在安全领域,已经推荐sha256和sha512了,sha1已经倾向于不推荐,md5可以认为已经被破解。
目前MD5被广泛应用于数据完整性校验、数据(消息)摘要、数据加密等;
目前SHA1的应用较为广泛,主要应用于CA和数字证书中,另外在目前互联网中流行的BT软件中,也是使用SHA1来进行文件校验的。
- MD5、SHA1虽然被发现存在缺陷(碰撞),但在近几年内,仍然可以大量使用
- SHA256/384/512 的速度较慢,可以用于少量数据摘要,目前不适合用于大文件校验
写在最后
PHP中md5()函数如何对字符串进行加密
php的md5()具有输出原始二进制数据的特性。
md5()语法:
1 | md5(string, raw) raw 可选,默认为false |
通过使用php的md5(“ffifdyop”,true)输出其加密后的原始二进制数据得到目标字符串.
原始二进制数据不是指100111这些二进制数据,而是原始字符串转换成ascii码后组成的字符串。
使用md5(“ffifdyop”)进行加密
通过加密后将会得到之后的32位16进制字符串:276f722736c95d99e921722cf9ed621c将32位16进制字符串按照2个字符为一组切割成为16组16进制的字符串
切割成27,6f,72,27,36,c9,5d,99,e9,21,72,2c,f9,ed,62,1c将每一组16进制的数值转换成2进制 100111,1101111,1110010,100111,110110,11001001,1011101,10011001,11101001,100001,1110010,101100,11111001,11101101,1100010,11100
将每一组2进制数值转换称为10进制数值
39,111,114,39,54,201,93,153,233,33,114,44,249,237,98,28最后对照如下的ASCII码表即可翻译的出最终的原始二进制字符串.
以前四组为例39=>’,111=>o,114=>r,39=>’,最终的组成’or’这一个字符串.