一、简介
报错注入有12种,分别是:floor报错、ExtractValue报错、UpdateXml报错、NAME_CONST报错、join报错、exp报错、GeometryCollection报错、polygon报错、multipoint报错、multlinestring报错、multpolygon报错、linestring报错。本文将探究基于floor的sql报错注入,介绍其原理及利用方法。
二、相关函数
在讲原理之前我们需要先了解一下相关sql语句以及几个sql函数的知识,然后对才能对原理理解。
1、floor函数
本篇主要是围绕floor报错注入进行论述,所以我们先来了解一下什么是floor?floor在这指的是sql中的floor函数,floor(value)函数返回小于或等于指定值(value)的最小整数,如:
floor(555.5)=555;floor(555.4)=555
floor函数不仅在sql中存在,在Excel、c语言、python、JavaScript中也有广泛应用。
2、rand函数
对与rand函数,有过编程基础的应该知道,这是随机数函数,sql中的rand函数用于产生0到1之间的随机数,例如执行语句:
select rand();
可得到下面的结果:
+------------------+
| RAND( ) |
+------------------+
| 0.79257156412541 |
+------------------+
当然它并非无参数,默认情况就是这样,如果给它一个参数即随机数种子,可以生成一个伪随机序列。结合前面的floor,我们可以构造语句:
floor(rand(0)*2)
由于加了随机因子0,所以每次执行语句都会产生伪随机序列0 1 1 0 1 1… 。
3、count与group by函数
COUNT() 函数返回匹配指定条件的行数,COUNT(*) 函数返回表中的记录数,GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组。这里不再举例。
三、原理
floor报错的原理,其实关键在于floor(rand(0)*2)语句的多次执行,造成虚拟表中主键的重复,导致报错。具体的sql语句如下:
select count(*),(floor(rand(0)*2)) x from users group by x
让我们来详细解读一下这句话的意思。
首先,我们来看一下语句执行的过程。在执行以上语句时,mysql会先建立一个虚拟表,然后开始查询数据,取数据库中的数据,如果虚拟表中没有相等的键值,就会添加对应的记录,如果找到相应的键值,就会count(*)++。这也就是这条语句执行的基本过程。这个过程对接下来的介绍非常重要。
除了使用count与group函数,还用到了floor(rand(0)*2),让我们来看看,这个语句与上面的查询过程有何联系,与就是整条语句执行的过程是什么样的。
首先,建立虚拟表(空表),开始查询。执行floor(rand(0)*2)
结果为0(伪随机序列),与第一条记录比较,发现不存在与之相等的键值,然后再次执行floor(rand(0)*2)
结果为1,讲1添加至虚拟表中,生成第一条记录。继续查询,再次计算floor(rand(0)*2)
结果为1,查询虚拟表,发现与之相等的键值,于是执行count(*)++。到这里,虽然floor语句没有按照我们的想法去执行,但结果还是正常的,未发生报错,我们接着往下看。
继续查询,执行floor(rand(0)*2)
结果为0,查询虚拟表,未发现键值为零,再次执行floor(rand(0)*2)
结果为1,插入虚拟表中,但是此时虚拟表中已经存在键值为一的主键,所以造成了主键的重复导致了报错。
从以上语句执行过程中我们可以看出导致这条语句报错的原因也就是刚开始说的那句话:floor(rand(0)*2)
语句的多次执行。
这就是基于floor的报错原理,准确的来说是floor(rand(0)*2)
报错的原理,因为我们还没有讨论floor(rand()*2)
导致的报错。看了以上语句执行的过程,其实我们已经知道,令floor(rand()*2)
报错的条件就是虚拟表中不能同时存在1与0,由于rand(0)会生成伪随机序列,所以我们可以确定当使用rand(0)时,只要数据记录大于三条就一定会报错,而rand()不一定会报错,因为没有随机因子,所以它是随机出错的。
四、利用
理解了上面的原理后,你可能会有些许疑惑:报错是出来了,它怎么用呢?接下来就让我们看看它的利用。
首先,让我们来看看常用的payload:
and select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)
database()处即为语句执行处,上面我们已经说到了,为何会报错。报错后会提示错误信息,如下:
ERROR 1062 (23000): Duplicate entry 'myemployees1' for key 'group_key'
可以看到,虽然报错了,但是database()语句也成功执行了,所以可以利用此处的语句执行来得到我们想要的数据信息等。