这里说一下做题的时候看了些wp都是直接告诉输入ffifdyop就行 完全不明白为啥 看了些wp后。整体综合了一下
打开靶场后只有一个查询框
一顿输入后无果 只能通过url看到是get传参 用burp抓包看看
关于md5($pass,true)的注入
这里的篇幅会有点长 因为这块比较重要 这块明白后后面的非常简单
发现了提示 select * from `admin` where password=md5($pass,true)
也就是通过注入来进行绕过 这里先看下php MD5函数的用法
32位16进制字符串的意思是:将MD5加密得到的128 位长度的"指纹信息",以每4位为一组,分为32组,每组以转换为16进制,进行转换得到一个32位的字符串。
总的来说就是我们平时看到的MD5加密的结果
16位原始二进制格式的字符串的意思是:将128 位长度的"指纹信息"分组转化为16位的一个字符串,然后两个字符为一组,依照ACILL码转化为字符串。
也就是说,就是当md5函数的第二个参数为true时,该函数的输出是原始二进制格式,会被作为字符串处理。
这里进行绕过就是需要构造一个语句使sql语句永恒为真
例如这样:select * from `admin` where password=’’or’xxx 当or后面的值为true时即可完成注入
思路来了
要达到注入。首先要有一个字符串,这个字符串经过md5得到的16位原始二进制的字符串能帮我们实现sql注入。首先or这个字符串是必要的,因为需要构造永恒为真的语句。同时为了配对原先sql语句里面有的单引号进行闭合
所以我们需要的字符串的原始二进制格式的字符串里要包含 ‘or’ , ‘or’ 对应的16进制是 276f7227 ,所以我们的目标就是要找一个字符串取32位16进制的md5值里带有276f7227这个字段的,接着就是要看关键的数字部分了,在276f7227这个字段后面紧跟一个数字,除了0,1-9,对应的asc码值是49-57,转化为16进制就是31-39,也就是我们需要有276f7227+(31-39)这个字段,就可以满足要求
这里32位的16进制的字符串,两个一组就是上面的16位二进制的字符串。比如27,这是16进制的,先要转化为10进制的,就是39,39在ASC码表里面就是’ ' ‘字符。6f就是对应‘ o ’。
这里引用一下原文章 链接在下面
这里需要注意的是,当raw项为true时,返回的这个原始二进制不是普通的二进制(0,1),而是 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c 这种。
上面的’ffifdyop‘字符串对应的16位原始二进制的字符串就是” 'or'6\xc9]\x99\xe9!r,\xf9\xedb\x1c “ 。 ' \ '后面的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),是数字开头的。当然不能以0开头。(我不知道在数据库里面查询的时候,�这种会不会显示)
这里引用一篇文章,连接在下面,里面的原话“a string starting with a 1 is cast as an integer when used as a boolean.“
在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。当然在我后来测试中发现,不只是1开头,只要是数字开头都是可以的。
这里贴上一个链接 对sql注入:md5($password,true) 讲解非常详细
sql注入:md5($password,true)_md5($pass,true)_March97的博客-CSDN博客
看完这个文章后就可以明白为啥ffifdyop就是答案,因为ffifdyop的md5的原始二进制字符串里面有‘or’6这一部分的字符 得到这个字符后插入sql语句就使其为真就可以对其进行注入了
这里看下ffifdyop的效果
代码如下
<?php
$str = "ffifdyop";
echo "The string: ".$str."<br>";
echo "TRUE - Raw 16 character binary format:如下所示: ".md5($str, TRUE)."<br>";
echo "FALSE - 32 character hex number: ".md5($str)."<br>";
?>
运行后的结果如下所示
这里可以使用ASCII码在线转换器看效果
将ffifdyop传入 即可到达第二个页面 这里开始就很简单了
MD5弱比较
查看页面源代码发现需要传入两个参数
满足a与b的参数不同且两者的MD5相同就会返回正确的值
注意这里是弱比较==
这里有两种方法 第一种采用数组传参 数组传参方式格式为num[]=w num为参数(例如本题的a) w为传入的值 最终传入的值如下
?a[]=1&b[]=2 因为md5不能处理数组,md5 函数哈希数组会返回 NULL。从而达到两者相等进行绕过。
第二种方法,php 0e开头的数字会当做科学计数法解析,因此只要构造两组md5值开头为0e的值即可绕过。
原理是PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
例如
QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
这些网上有很多 这里就例举一个 伙伴们可以自行百度
题外话
有的题目是传参参数为字母和数字的MD5比较 用的也是弱类型比较 也可以采用这种方法
这里贴一个链接 讲解php弱类型的比较
https://www.cnblogs.com/Mrsm1th/p/6745532.html
输入数组后就跳转到了下一个页面
MD5强比较
还是一样的,只不过是post传参 且这里是强类型比较===
=是赋值 ==是弱比较 ===强比较(数值与类型都要相同)
这里只能使用数组传参了 之前的那个页面由于是弱比较 所以有两种方法可以进行MD5绕过
这里是强比较所以只能使用数组 不过这道题 数组可以通杀绕过这两层的MD5
Payload如下 post传参
param1[]=2¶m2[]=3