[BJDCTF2020]Easy MD5_WriteUP
打开网站
抓包发现了个线索,一个SQL语句,这里可以确定是SQL注入了,但是和MD5编码相关
select * from 'admin' where password=md5($pass,true)
md5(string,raw)
参数 | 描述 |
---|---|
string | 必需。要计算的字符串 |
raw | 可选。 默认不写为FALSE,32位16进制的字符串;TRUE,16位原始二进制格式的字符串。 |
md5(string,true)函数在指定了true的时候,是返回的原始 16 字符二进制格式。 这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。
content: ffifdyop
hex: 276f722736c95d99e921722cf9ed621c
raw: 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c
string: 'or'6]!r,b
这里32位的16进制的字符串,两个一组就是上面的16位二进制的字符串。比如27,这是16进制的,先要转化为10进制的,就是39,39在ASC码表里面就是 '
字符。6f就是对应 o
。
这不是普通的二进制字符串,而是’or’6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。这样的话就会和前面的形成闭合,构成万能密码。
select * from 'admin' where password=''or'6.......'
这就是永真的了,这就是一个万能密码了相当于1’ or 1=1#或1’ or 1#。接下来就是找到这样子的字符串。而上面的字符串 ffifdyop
就是其中一个payload,就可以直接用了
但是我们思考一下为什么6\xc9]\x99\xe9!r,\xf9\xedb\x1c的布尔值是true呢?
在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数(这类似于PHP的弱类型)。要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。这里不只是1开头,只要是数字开头都是可以的。当然如果只有数字的话,就不需要单引号,比如password=‘xxx’ or 1,那么返回值也是true。(xxx指代任意字符)
我们输入这个ffifdyop字符串以后出现以下的页面:
查看源码发现以下内容
代码的意思就是a,b两个参数要不相等,但是呢他们两个的MD5值需要相等。这里我想的是估计又是要利用PHP弱类型的缺陷绕过了。
md5()
$array1[] = array(
"foo" => "bar",
"bar" => "foo",
);
$array2 = array("foo", "bar", "hello", "world");
var_dump(md5($array1)==md5($array2)); //true
PHP 手册中的 md5()函数的描述是 string md5 ( string $str [, bool $raw_output = false ] )
,md5()
中的需要是一个 string 类型的参数。但是当你传递一个 array 时,md5()
不会报错,只是会无法正确地求出 array 的 md5 值,这样就会导致任意 2 个 array 的 md5 值都会相等。
以上内容是我在web篇总结的,正好用到此处,PHP内置函数的松散性,利用数组绕过。
这个题的payload估计是传递两个数组参数,虽然传递的数组内容值不一样,但是两个数组的md5值也会相等
成功到达下一步
看这一步的代码是用post方法传递数值,绕过方式和上一步一样,得到flag值