PHP弱类型hash比较缺陷
目录
0x00 漏洞原因
0x01 利用方法
0x02 [BJDCTF2020]Easy MD5 1
利用md5($password,true)实现SQL注入
PHP md5弱类型比较
数组绕过
0x00 漏洞原因
1、==在进行比较的时候,会先将两边的变量类型转化成相同的,再进行比较
2、0e在比较的时候会将其认为是科学计数法,所以无论0e后面是啥,0的次方都等于0
0x01 利用方法
我们可以理解为只要让我们输入的密码在经过函数加密之后是以0e开头即可
以下是一些从其他作者文档里看到的一些经过md5加密后是以0e开头的值:
ej0D ek06 el08 eo0n ey0M ey0O ez0s e006 e10l eU3Z eW3vfSoL fToh fTo1 fUoU fYou fapF fbpf fdpF fnpZ fppr fqpa frpj fwpD fyp5 f1p2 f4pN f7pu fDpQ fHpP fIp4 fJpX fLpv fOpi fQp3 fTpi fVpz feqN fjqN fvq1 fyqy fAqJ fEqk fFqg fFqi fHqX fIqF fKqh fLq6 fQq6 fQqA fRql fUq4 fUqA fXq0 farg farJ ftrT f7rm fCrB fErY fIrt QNKCDZO s878926199a s155964671a s214587387a s214587387a s878926199a
若是===判断,则可以通过数组返回NULL的方法来绕过
这里PHP的一些特性
md5(array()) = null
sha1(array()) = null
ereg(pattern,array()) = null vs preg_match(pattern,array) = false
strcmp(array(), "abc") = null
strpos(array(),"abc") = null
0x02 [BJDCTF2020]Easy MD5 1
当我们进入网页,看到的是一个表单提交,很像sql注入
试了试很多的注入方式,均没有反应,查看一下响应头
确实存在sql注入,但这里进行了md5加密
利用md5($password,true)实现SQL注入
我们先来看看md5函数的用法:
md5(string,binary)
string:要计算的字符串
binary:如果可选的binary被设置为true,那么md5摘要1讲义16字符长度的原始二进制格式返回;若为false,则默认以32位十六进制数返回
也就是说在这里我们可以利用md5值经过hex转成的字符串为'or'+123456这样的字符串,就可以拼接后台sql语句为:
select * from admin where password=' ' or 123456
那么这里,当or后面的值为true时,那不就是万能密码了嘛
这里需要知道一个MySQL的特性:
在mysql里,在用作布尔型判断时,以1开头的字符串会被当做整型数,但需要注意的是这种情况必须要有单引号括起来
password=‘xxx’ or ‘1xxx’ ——> password=‘xxx’ or 1 ——> password=‘xxx’ or true
那么返回值也就是true
那么我们这里的突破点就是,只要or后面的字符串为一个非零数字开头都会返回true
这里提供一个最常用的:ffifdyop,哈希值为:276f722736c95d99e921722cf9ed621c('or'6<trash>)
所以我们这里输入ffifdyop,后端SQL语句就会变为
select * from admin where password=' ' or '6<strash>'
成功进入下一关
PHP md5弱类型比较
我们可以看到检查源代码
这里通过get传参,要求a和b的明文不同,但md5值要相同
注意,这里比较时用的是==,弱类型比较,所以我们可以利用这个点突破,寻找两个明文不同但md5值为0e开头的字符串,参考上面的内容
a=QNKCDZO&b=s214587387a
成功绕过,进入下一关
数组绕过
依旧是md5值比较,但不同于第二关,这是===强相等
因为md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就相等了
param1[]=1¶m2[]=2
获得flag!