sql注入--双查询报错注入原理探索

双查询报错注入原理探索

上一篇讲了双查询报错查询注入,后又参考了一些博客,今天来探究其原理

实际上该报错是由于rand(),count(),group by 三个语句联合使用造成的,缺一不可。

part 1 场景复现

首先我们新建一个数据库,并创建一个表用作实验:

mysql> CREATE DATABASE sql_test; mysql> USE sql_test; mysql> CREATE TABLE test(id int(2),name varchar(10));

1547704744034

接下来先插入一条数据测试:

mysql> INSERT INTO test VALUES("1","aaa");

下面看见已经插入了一条数据:

1547705572218

接下来我们构造一个报错条件,让其报错,显示出当前数据库名:

mysql> SELECT count(*),concat((SELECT database()),"~",floor(rand()*2))as a FROM test GROUP BY a;

查询的结果要么为sql_test~0,要么是sql_test~1,取决于随机数取整结果,不会触发报错。

1547705814418

1547705838535

接下来再在表中插入一条数据进行测试:

mysql> INSERT INTO test VALUES("2","bbb");

1547706027911

双查询语句与之前一样

运气很好,第一次就报错了,错误内容意思:group by 操作时主键 ‘sql_test~1’ 重复

1547706189543

还有其他正常执行不报错的情况:

1547706399949

可以看到,这里存在两条数据就可以引发报错,得到数据库信息。

part 2 形成原因

接下来我们再分析其报错的形成 原因:

先谈group by 函数:

在表中再插入两条数据,name值都为“bbb”:

mysql> INSERT INTO test VALUES("3","bbb"); mysql> INSERT INTO test VALUES("4","bbb");

成功后表如下:

1547706801693

这时候我们使用group by 语句时,MySQL会将查询结果分类汇总,重复的内容会合并为一项:

mysql> SELECT name FROM test GROUP BY name;

1547707005212

这时候再使用count()函数就可以对不同的条目计数:

mysql> SELECT count(*),name FROM test GROUP BY name;

如图:aaa有一条,bbb有3条

1547707132342

其背后的实现原理如下:

在执行group by name语句时,MySQL会在内部建立一个虚拟表,用来储存列的数据,表中会有一个group_key值作为表的主键,这里的主键就是用来分类的name列中获取,当查询数据时,取数据库数据,然后查看虚拟表中存在不,不存在则插入新记录

1547707392629

当读取到第一行数据时,aaa不存在,将aaa放入主键列中,1放在id列中

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsxgxd.html