MD5绕过
记录网站:【CTF_Web:php弱类型绕过与md5碰撞 - CSDN App】http://t.csdnimg.cn/A58wf
MD5函数漏洞
$str1 = $_GET[‘str1’];
$str2 = $_GET[‘str2’];
if (md5($str1) == md5($str2)){
die(‘OK’); }
php弱类型比较产生的漏洞
想要满足这个判断只需要构造出MD5值为0e开头的字符串,这样的话弱类型比较会认为是科学技术法,0的多少次方都是0,因此可以绕过MD5
编码后0e开头的字符串:
QNKCDZO(0e830400451993494058024219903391)
aabg7XSs(0e087386482136013740957780965295)
aaabEgHn(0e418636035810609803317995275027)
240610708
s878926199a
s155964671a
s214587387a
还有MD5和双MD5以后的值都是0e开头的
CbDLytmyGm2xQyaLNhWn
770hQgrBOjrcqftrlaZk
7r4lGXCH2Ksu2JNT3BYM
md5()数组绕过。
如果我们传入/?name[]=1,那$name的值就是一个数组,name[]=1,2也一样,两个数组进行比较的时候会比较数组内的元素,但md5编码就不一样了,md5()函数统一把数组当成字符串array,这也就导致只要两个都是数组,那他们的md5编码都一样,都为字符串array的md5编码。
PHP特性
$str1 = $_GET[‘str1’];
$str2 = $_GET[‘str2’];
if (md5($str1) === md5($str2)) {
die(‘OK’);
}
因为是强类型比较,用0e开头的字符串是没办法绕过的了,但是PHP自身的特性使得可以提交一个数组,
而md5函数传入数组的返回值都是NULL,这样就可以绕过强类型比较了。所以这里用GET传入?str1[]=1&str2[]=2就行了
补充:md5()或者sha1()之类的函数计算的是一个字符串的哈希值,对于数组则返回false,如果$str1和$str2都是数组则双双返回FALSE,
两个FALSE相等得以绕过
MD5碰撞
$str1 = (string)$_GET[‘str1’];
$str2 = (string)$_GET[‘str2’];
if (md5($str1) === md5($str2)) {
die(‘OK’);
}
由于强制类型转换,传数组就不可行了,这里就需要MD5碰撞,对于需要两个内容不同但是MD5值相同的文件,使用Fastcoll就可以了
绕过md5()来构造攻击语句
select * from ‘admin’ where password=md5($pass,true)
ffifdyop
这个点的原理是 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 ‘ or ‘6,
而 Mysql 刚好又会吧 hex 转成 ascii 解释,因此拼接之后的形式是select * from ‘admin’ where password=‘’ or ‘6xxxxx’。等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数
md5碰撞(最强解)
a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
$a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
$b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
以0e开头的原字符串md5后的密文还是以0e开头
0e215962017
超过精确度的弱类型问题
超过精确度的数字(小数点后超过17位)在进行弱类型比较时,会出 现相等的情况。例如var_dump(0.99999999999999999==1)的结果为 True。
in_arrray()函数
in_array()函数的基本格式为:in_array($search,Array()),表示搜索 $search是否为数组Array()的元素。in_array()函数实际上存在第三个参 数,该参数默认为false。如果第三个参数设置为true,则判断$search与 数组的值类型是否相同,即进行强类型比较;若第三个参数设置为 false,则in_array()函数进行判断的时候,会强制将$search的值转换为 数组的值类型,此时就是弱类型比较。
eregi()函数
eregi()函数用于在一个字符串中搜索指定模式的字符串,搜索时不区分 大小写。
关于eregi()函数的考点一般为:eregi()函数可以被%00截断(PHP5版 本,该函数在PHP7中被弃用)。
eregi(“111”.substr($input,0,1),“1114”) and substr($input,0,1) !=4
该语句要求$input的第一个字符不能为4,但同时要求字符串111与 $input的第一个字符拼接后的结果必须能够匹配字符串1114。按照常 理,这是相互矛盾的,此时可以使用%00来进行输入。请注意,%00在 此处表示一个字符,即\0。之所以会出现截断问题,是因为PHP的底层 是基于C语言实现的,而在C语言里,字符串是以\0作为结尾的。
md5长度限制强相等
总思路:传相同字符的不同数据类型
1 | <?php |
1.php浮点数常量NAN和INF:
在PHP中,NAN是一个特殊的浮点数值,表示非数值(Not-A-Number)。当一个运算无法计算结果时,比如零除以零,就会产生NAN。
PHP中的INF是一个特殊的浮点数值,表示无穷大(Infinity)。当数值超过PHP_FLOAT_MAX或者使用一些数学函数产生极大或极小的结果时,就会得到INF。
利用思路:
php浮点数常量NAN和INF:
使用浮点常量INF分别给ctf和dsb变量赋值,长度都为3,dsb是字符串类型,ctf是浮点型,由于MD5是以字符串形式进行加密的,所以他们的MD5值是相等的。这样就达到了绕过的目的。
2.dsb会被转化成字符串类型,但是ctf不会,所以可以利用不同类型的相同字符绕过。比如:
md5(‘123’)=md5(123)