今天做的这道题很有意思,跟之前做的浙大oj上的题目很类似,都是考了md5(string,raw)这个函数,所以这里我要记录一下
题目
拿到题目,是一个框
分析
先随便输入一个数值,抓包看看
发现返回包中有这么一条查询语句
select * from 'admin' where password=md5($pass,true)
然后查了下md5(string,raw)函数
这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 'or'6xc9]x99xe9!r,xf9xedbx1c 这种。
content: ffifdyop
hex: 276f722736c95d99e921722cf9ed621c
raw: 'or'6xc9]x99xe9!r,xf9xedbx1c
string: 'or'6]!r,b
上面的’ffifdyop‘字符串对应的16位原始二进制的字符串就是” 'or'6xc9]x99xe9!r,xf9xedbx1c “ 。 ' '后面的3个字符连同' '算一个字符,比如’ xc9 ‘,所以上述一共16个。当然,像’ xc9 ‘这种字符会显示乱码。
这里32位的16进制的字符串,两个一组就是上面的16位二进制的字符串。比如27,这是16进制的,先要转化为10进制的,就是39,39在ASC码表里面就是’ ' ‘字符。6f就是对应‘ o ’。
然后我们得到的sql语句就是 SELECT * FROM admin WHERE username = 'admin' and password = ''or'6 ] !r, b'
为什么password = ''or'6 ] !r, b'的返回值会是true呢,因为or后面的单引号里面的字符串(6 ] !r, b),是数字开头的。
在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。当然在我后来测试中发现,不只是1开头,只要是数字开头都是可以的。
当然如果只有数字的话,就不需要单引号,比如password=‘xxx’ or 1,那么返回值也是true。(xxx指代任意字符)
我们这里做了几个测试
然后只要输入的字符串通过md5函数返回的原始16位的二进制字符串能够成功拼接sql语句就ok了
还没完,接着我们访问./levels91.php
查看源码
很简单的md5比较,这里用数组就可以绕过
payload:
?a[]=1&b[]=2
然后就跳转到了一下界面
一看就是md5强类型碰撞
param1=%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¶m2=%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
拿到flag