SQL注入之双查询注入
前言
在做sqlilabs时,了解到的东西,写一下,把学到的总结一下,以后方便看
子查询
在说双查询之前,先介绍一下子查询。
查询:任何SQL语句都是查询。但此术语一般指SELECT语句。
SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询。
举个简单的例子,Select concat((select database()));
执行的时候,先从子查询进行。因此执行select database()这个语句就会把当前的数据库的名称查出来,然后把结果传入到concat函数。这个函数是用来连接的。比如数据库名字叫’a’和’b’,那么concat(‘a’,’b’)后,结果就是ab了。
介绍几个函数和语句:
rand()函数 //返回0~1间的小数。
floor()函数 //向下取整。向上取整:ceiling()
count()函数 //返回匹配指定条件的行数。
group by子句 //根据一个或多个列对结果集进行分组。
双查询注入原理
当在一个聚合函数,比如count()函数后面如果使用分组语句就会把查询的一部分以错误的形式显示出来。
select floor(rand()*2)
rand()返回0~1间的数,*2之后向下取整后不是0就是1
用concat_ws()将子查询的结果连接,select concat((select database()),floor(rand()\*2))
可以看到返回结果中有数据库名,注意数据库的名字并不是叫security1和security0,而是数据库名连接的select floor(rand()*2)
生成的0或1.
如果在这条语句后面加上from一个表名,那么会返回security0或security1的一个集合,数目是由表本身有几条结果决定的: select concat((select database()),floor(rand()\*2)) from users;
这样看来,如果是从information_schema.schemata里,这个表包含了mysql的所有数据库名,则会返回数据库数个结果。
我们使用information_schema.tables或者information_schema.columns两个表来查询想要的信息。
把concat((select database()),floor(rand()\*2))
这个结果取了一个别名a,然后使用它进行分组。这样相同的security0分到一组,security1分到一组,就剩下两个结果了
这里的database()可以替换成任何想查的函数,比如version(),user()等。
最后一步,使报错中显示想要查询的结果:
分别查看database(),version(),user()
select count(\*),concat((select database()),floor(rand()\*2)) as a from information_schema.tables group by a;
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;