Mysql报错注入原理分析(count()、rand()、group by)
0x00 疑问
一直在用mysql数据库报错注入方法,但为何会报错?
百度谷歌知乎了一番,(官网:www.fhadmin.org)发现大家都是把官网的结论发一下截图,然后执行sql语句证明一下结论,但是没有人去深入研究为什么rand不能和order by一起使用,也没彻底说明三者同时使用报错的原理。
0x01 位置问题?
select count(*),(floor(rand(0)*2))x from information_schema.tables group by x; 这是网上最常见的语句,目前位置看到的网上sql注入教程,floor 都是直接放count(*) 后面,为了排除干扰,我们直接对比了两个报错语句,如下图
由上面的图片,(官网:www.fhadmin.org)可以知道报错跟位置无关。
0x02 绝对报错还是相对报错?
是不是报错语句有了floor(rand(0)*2)以及其他几个条件就一定报错?其实并不是如此,我们先建建个表,新增一条记录看看,如下图:
确认表中只有一条记录后,再执行报错语句看看,如下图:
多次执行均未发现报错。
然后我们新增一条记录。
然后再测试下报错语句
多次执行并没有报错
OK 那我们再增加一条
执行报错语句
ok 成功报错
由此可证明floor(rand(0)*2)报错是有条件的,(官网:www.fhadmin.org)记录必须3条以上,而且在3条以上必定报错,到底为何?请继续往下看。
0x03 随机因子具有决定权么(rand()和rand(0))
为了更彻底的说明报错原因,直接把随机因子去掉,再来一遍看看,先看一条记录的时候,如下图:
一条记录的话 无论执行多少次也不报错
然后增加一条记录。
两条记录的话 结果就变成不确定性了
随机出现报错。
然后再插入一条
三条记录之后,也和2条记录一样进行随机报错。
由此可见报错和随机因子是有关联的,但有什么关联呢,为什么直接使用rand(),有两条记录的情况下就会报错,而且是有时候报错,有时候不报错,而rand(0)的时候在两条的时候不报错,在三条以上就绝对报错?我们继续往下看。
0x04 不确定性与确定性
前面说过,floor(rand(0)*2)报错的原理是恰恰是由于它的确定性,这到底是为什么呢?从0x03我们大致可以猜想到,因为floor(rand()*2)不加随机因子的时候是随机出错的,而在3条记录以上用floor(rand(0)*2)就一定报错,由此可猜想floor(rand()*2)是比较随机的,不具备确定性因素,而floor(rand(0)*2)具备某方面的确定性。
为了证明我们猜想,分别对floor(rand()*2)和floor(rand(0)*2)在多记录表中执行多次(记录选择10条以上),在有12条记录表中执行结果如下图:
连续3次查询,毫无规则,接下来看看select floor(rand(0)*2) from `T-Safe`;,如下图:
可以看到floor(rand(0)*2)是有规律的,而且是固定的,这个就是上面提到的由于是确定性才导致的报错,那为何会报错呢,我们接着往下看。
0x05 count与group by的虚拟表
使用select count(*) from `T-Safe` group by x;这种语句的时候我们经常可以看到下面类似的结果:
可以看出 test12的记录有5条(官网:www.fhadmin.org)
与count(*)的结果相符合,那么mysql在遇到select count(*) from TSafe group by x;这语句的时候到底做了哪些操作呢,我们果断猜测mysql遇到该语句时会建立一个虚拟表(实际上就是会建立虚拟表),那整个工作流程就会如下图所示:
- 先建立虚拟表,如下图(其中key是主键,不可重复):
2.开始查询数据,取数据库数据,然后查看虚拟表存在不,不存在则插入新记录,存在则count(*)字段直接加1,如下图:
由此看到 如果key存在的话就+1, 不存在的话就新建一个key。
那这个和报错有啥内在联系,我们直接往下来,其实到这里,结合前面的内容大家也能猜个一二了。
0x06 floor(rand(0)*2)报错
其实mysql官方有给过提示,就是查询的时候如果使用rand()的话,该值会被计算多次,那这个“被计算多次”到底是什么意思,就是在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,我们来看下floor(rand(0)*2)报错的过程就知道了,从0x04可以看到在一次多记录的查询过程中floor(rand(0)*2)的值是定性的,为011011…(记住这个顺序很重要),报错实际上就是floor(rand(0)*2)被计算多次导致的,具体看看select count(*) from TSafe group by floor(rand(0)*2);的查询过程:
1.查询前默认会建立空虚拟表如下图:
2.取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算),查询虚拟表,发现0的键值不存在,则floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表,这时第一条记录查询完毕,如下图:
3.查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算),查询虚表,发现1的键值存在,所以floor(rand(0)*2)不会被计算第二次,直接count(*)加1,第二条记录查询完毕,结果如下:
4.查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算),查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,作为虚表的主键,其值为1(第5次计算),然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候就直接报错了。
5.整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次,(官网:www.fhadmin.org)所以这就是为什么数据表中需要3条数据,使用该语句才会报错的原因。
0x07 floor(rand()*2)报错
由0x05我们可以同样推理出不加入随机因子的情况,由于没加入随机因子,所以floor(rand()*2)是不可测的,因此在两条数据的时候,只要出现下面情况,即可报错,如下图:
最重要的是前面几条记录查询后不能让虚表存在0,1键值,如果存在了,那无论多少条记录,也都没办法报错,因为floor(rand()*2)不会再被计算做为虚表的键值,这也就是为什么不加随机因子有时候会报错,有时候不会报错的原因。如图:
当前面记录让虚表长成这样子后,由于不管查询多少条记录,floor(rand()*2)的值在虚表中都能找到,所以不会被再次计算,只是简单的增加count(*)字段的数量,所以不会报错,比如floor(rand(1)*2),如图:
在前两条记录查询后,虚拟表已经存在0和1两个键值了,所以后面再怎么弄还是不会报错。
总之报错需要count(*),rand()、group by,三者缺一不可。
相关推荐
MySQL 报错注入是一种安全漏洞利用技术,当应用程序在处理用户输入时未能充分过滤或转义SQL语句,导致数据库因错误语法而返回错误信息,攻击者可以通过分析这些错误信息来获取敏感信息或执行恶意操作。以下是对MySQL...
通过实际操作,作者向读者展示了如何使用group by和concat()函数结合floor()和rand()函数来执行报错注入,以及如何分析错误信息来获取数据库相关的信息。 总之,文章通过实践和理论相结合的方式,详细介绍了floor...
从执行计划、SELECT语句、IN和EXIST语句、LIMIT语句、RAND函数、Order by、Group by、Distinct和Count等方面对MySQL数据库优化进行了详细的讲解。 一、执行计划 执行计划是MySQL数据库优化的重要步骤。执行计划...
手册还可能包含关于聚合函数(如GROUP BY和HAVING语句)、窗口函数(如LEAD()和LAG())以及各种其他高级用法的详细信息,帮助用户在实际操作中更好地处理数据。 此外,VZI版的MySQL函数手册可能会有额外的注解、...
AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT(USER(), FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x) a) ``` 2. `EXTRACTVALUE()` 函数:该函数尝试从XML字符串中提取值,如果提供的字符串...
这需要使用`GROUP BY`和`COUNT()`函数。示例如下: ```sql SELECT CONCAT('Deptno_', Deptno) AS Deptno_X, COUNT(*) AS cnt FROM emp GROUP BY Deptno; ``` 这将为每个部门创建一个新的列,并显示每个部门的...
MySQL数据库优化SQL篇学习教案旨在帮助读者学习和掌握 MySQL 数据库优化的相关知识,涵盖了 SELECT 语句优化、执行计划、IN 和 EXISTS 语句、LIMIT 语句、RAND 函数、Order、Group、Distinct 和 Count 等方面的知识...
- MySQL提供了`AVG()`(平均值)、`COUNT()`(计数)、`MAX()`(最大值)、`MIN()`(最小值)、`SUM()`(求和)等聚合函数,这些函数可以帮助我们统计分析数据。 12. **SQL语句关键字** - SQL的基本结构包括:`...
- **1.2.3.4.20 分组函数,group by子句** - 使用`GROUP BY`子句按指定列分组。 - **1.2.3.4.21 分组函数,having子句** - 使用`HAVING`子句在分组之后进一步过滤结果。 - **1.2.3.4.22 查询排序,order by子句...
- **1.9.1 groupby** - `GROUP BY column_name`用于对数据进行分组。 - **1.9.2 having** - `HAVING`用于过滤分组后的结果。 #### 九、连接查询 - **1.10 连接查询** - **1.10.1 SQL92语法** - SQL92标准提供...
- 为经常出现在ORDER BY或GROUP BY子句中的列建立索引。 - 尽量避免在更新频繁的列上建立索引。 - **BTREE索引与HASH索引:** - **BTREE索引**:适用于范围查询,例如使用BETWEEN、<、>等操作符的查询。 - **...
- **语法**: `SELECT species, COUNT(*) FROM pet GROUP BY species;` - **解释**: 统计`pet`表中不同种类的宠物数量。 - **知识点**: 类似上一知识点,这里是对不同种类进行分组计数。 #### 三、连接数据库与...
聚合函数通常与`GROUP BY`子句一起使用,在SQL查询中进行统计分析。 - **AVG(col)**:返回指定列的平均值。 - 示例:`SELECT AVG(price) FROM products;` - **COUNT(col)**:返回指定列中非NULL值的数量。 - 示例...
### MySQL常用函数详解 #### 数学函数 - **ABS(x)**: 返回参数`x`的绝对值。 - **BIN(x)**: 将十进制数字`x`转换为二进制字符串表示。 - **CEILING(x)**: 返回不小于`x`的最小整数值。 - **EXP(x)**: 返回`e`的`x`...
- 数据分组:使用GROUP BY对数据进行分组。 - 过滤分组:使用HAVING来过滤分组后的结果。 11. 子查询: - 利用子查询进行过滤:在WHERE子句中嵌套子查询。 - 作为计算字段使用子查询:在SELECT语句中使用子查询...
* 分组查询:SELECT * FROM 表名 GROUP BY 字段名; * 排序查询:SELECT * FROM 表名 ORDER BY 字段名; * 分页查询:SELECT * FROM 表名 LIMIT 起始行, 行数; 多表查询 多表查询用于查询多个表中的数据,包括内连接...
GROUP BY子句通常和COUNT()、SUM()等聚合函数一起使用。 如果有ORDER BY子句,就按照“属性名2”指定的字段进行排序。排序方式由ASC或DESC参数指定。默认的排序方式为ASC。 二、在单表上查询数据 2.1、查询所有字段...
首先,对于去除重复项,最基础的方法是使用`GROUP BY`和`HAVING`子句。例如,假设我们有一个名为`sentence`的表,其中包含`name`字段存在重复的情况。最初的SQL查询可能如下: ```sql SELECT `name`, COUNT(*) AS ...
例如,查询每个部门的平均工资:`SELECT AVG(e_wage) AS dept_avgWage FROM employee GROUP BY dept_id`。 - `COUNT()`:统计行数或特定列的非空值数目。如:`SELECT COUNT(*) FROM employee`将返回表中的总行数。 ...