直接获取access、SQL Server等数据库数据
Author: Mix
PST,
Ph4nt0m Security Team
当使用SQL注入access的时候,经常会遇到密码为中文、猜不到关键字段名这样的问题。使用本技术就能够很快速的解决这样的问题。本技术最低要求有两条:
1.使用access数据库的系统存在SQL注入漏洞;mssql数据库也支持这个技术
2.需要知道欲爆数据所在的表的表名以及这个表下的一个字段名,一般都是id字段
使用本技术显而易见的优势在于:
1.可以不需要'引号,过滤'引号对本技术没有影响
2.可以快速的知道敏感数据的内容,而不必像以往一样慢慢的猜解,中文、特殊字符等等都通杀
3.在SQL Server屏蔽了错误信息之后仍然可以快速得到敏感数据内容
4.可以在不知道关键(欲知数据的)字段名的情况下仍然能够获取到欲知数据
咋一看可能这个技术很难,其实很简单。一共有两个难点,一般的第一个难点在看到结果以后都很容易想到,但是第二个难点却的确有点点麻烦。
首先看一个表格,是union的语法。这也是爆出数据的主要原理。如下图所示:
当我们使用SQL Inject技术插入union语句以后,只要两个select查询得到的列数相同,那么整条SQL语句执行完成以后,得到的查询结果就变成了union后面select得到的数据。所以就有可能将我们所需要的数据爆出来。来看一个简单的例子:
这是一个SQL Server的服务器,关闭了错误信息的回报,所以不能够按照以往的方法直接得到敏感数据。通过SQL Inject插入union语句以后,可以大胆的猜测到所执行的SQL语句变成了:
select * from Soft where SoftID=3903 union select username,password,1,1,1 from admin
那么在正常情况下显示Soft第1、2个字段值得地方就会显示admin的username和password字段,后面的3个1也是同理替代了。按照这个特性,我们当然也可以直接得到Admin_UserInfo表里面的username和password字段。构造的语句如下所示:
以上就是简单的利用union来实现对敏感数据的获取,而不通过复杂的暴力拆解。为了实现在不知道字段名同样能够得到其中的数据这个目的的时候,我们当然就应该想到使用*来代替字段名。这样只要*所代表的字段再加上几个1的数目和脚本中的select查询表中的字段数目相同,那么就同样可以得到不知道字段名的数据了。
考虑到这样一种情况,有这样一条语句:select id,hit,softname,softURL from soft where id=10。其中能够在网页中正常显示出来的字段是softname和softURL,那么我们在使用union的时候就应该调整*所在的位置,一般admin表中结构为id username password,那么在注入上面这条假设的语句的时候就应该这样构造SQL语句:select 1,* from admin。使*所代替的username和pssword字段处于softname和softURL两个字段的位置上,这样网页才能够将我们想要得username和password字段乖乖的交出来。当然这里只是最简单的一个例子来说明,有很多时候一个表里面可能有十几个字段,我遇到最长的是四十三个字段。那么脚本中使用select *来做查询的话,我们在构造union select就应该用1凑数到四十三个字段。其中当然是会有一些字段不被网页显示出来,这就需要考虑union select后面的*号所在的位置了。相信这个应该不用我多说了。
上面说的语法完全符合SQL Server。但是Access和SQL Server相比较,真的是小巫见大巫了。在SQL Server里面,当我们使用select *,1,1,1 from admin语句查询得到的记录集合分别是:* 1 1 1。但是在access当中上面的这条语句查询的结果是1 1 1 *,也就是说无论你将*号处于这群1中间的什么位置上,*所代表的数据总是处于查询结果的最后面。用一个复杂点的例子作说明:
这个站点使用的是access数据库,可以看到能够正常显示出来的字段是2、3、7、8、10、11,而后面的字段却不会显示出来,去掉14,15,16换上*号,页面同样显示出数字,也就是说admin中的字段数是三个,肯定是id username password这种结构,但是除了id字段其他的字段都不能够被猜测出名字。按照在上面SQL Server中所使用的方法移动*号的位置以求能够将敏感数据爆出来,在access中是不可行的。原因是access始终将*好所代替的字段放在查询数据集的最后面。Access查询出来的结果永远都是:1,2,3,4,5,6,7,8,9,10,11,12,13,*这个样子。为了将*好所代替的字段表示出来,我们必须将*所代替的字段移动到其他位置上。先看结果:
通过这样构造的语句的执行,最终查询得到的数据形式是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1,a.id a.name a.pwd b.id b.name b.pwd c.id c.name c.pwd d.id d.name d.pwd e.id e.name e.pwd
其中第3和第7个字段正好就是我们想要得username和password字段的值。这里我使用的是join语法,将两个表连接(相加)起来从而构造得到这样的一个满足我们要求的查询结果。
Join分为全部连接、左连接和右连接,具体区别可以去查看SQL语法。在这里,access中我们不管选择哪一种连接方式效果都等同于全部连接。看一个简单的join语法
SELECT *
FROM (表1 INNER JOIN 表2 ON 表1.序号=表2.序号)
INNER JOIN 表3
ON 表1.序号=表3.序号
转换为实例就是:
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 c.id=b.id)
inner join admin as d on d.id=c.id
按照这种格式就可以把上面的那个url真正执行的SQL语句解出来,无非就是不断的使用join连接数据表admin,然后通过1来补齐前面的字段数目。只要语句构建得当,那么不知道字段名的数据全部都能够在页面中显示出来。这就是这个技术的难点所在了。
好了,全部都介绍完了。如果想把这个技术写成程序的话,也是很有可能的。只不过在语句结构构造的时候最好还是使用人脑吧~~~呵呵