[BJDCTF2020]Easy MD5

今天做的这道题很有意思,跟之前做的浙大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&param2=%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

原文地址:https://www.cnblogs.com/zzjdbk/p/13654193.html