【web安全】——floor报错注入

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
作者名Demo不是emo
主页面链接 主页传送门
创作初心 舞台再大你不上台永远是观众没人会关心你努不努力摔的痛不痛他们只会看你最后站在什么位置然后羡慕或鄙夷
座右铭 不要让时代的悲哀成为你的悲哀
专研方向 web安全后渗透技术
每日emo 树是生活埋的是我看花就好别看我的落魄
今天给大家讲解的是SQL注入中的floor报错注入这个注入平时我没怎么用上次看别人面试时遇到了就再来深究一下研究其中的原理利用方式等等

一、漏洞的简介

floor()报错注入的原因group by在向临时表插入数据时由于 rand()多次计算导致插入临时表时主键重复从而报错又因为报错前 concat()中的SQL语句或函数被执行所以该语句报错且被抛出的主键是SQL语句或数执行后的结果。

乍一看是不是听不懂没关系我们来详细讲解一下首先介绍一下原理中涉及到的函数如下

二、涉及的函数

floor()函数对传入的值进行向下取整操作并返回结果如floor(1.999),则返回1.

rand()函数返回随机数

rand(x)函数x在这里代表参数当rand()函数有了参数后生成的就是伪随机数什么意思呢比如你使用rand(0)产生的第一个随机数产生的随机数相同也就是当rand(x)这个参数x已知的时候我们就能知道如下

同样的刚才我们说的是使用rand(0)产生的第一个随机数都相同产生的第n个随机数其实都相同但是这n个随机数之间可能不相同这样能懂吗如下

也就是我user表里有三个数据所以这个rand(0)执行了三次可以看到rand(0)在不同的地方执行的前三次的数据都是相同的

简单来说就是rand()函数有参数即rand(x)时rand(x)产生的就是伪随机的一个数组数组中元素的值由x决定就是你使用rand(x)产生的第n次数据与我使用rand(x)产生的第n次数据是相同的

count(*)函数返回值的条目与count()的区别在于其不排除NULLcount()如果统计到NULL,返回的结果即为NULL返回列数。如下就是统计user表的内容条数

group by语句 分组的意思如下

这里的意思就是以username字段来分组,会统计出users表中存在username字段的数据条数但是当有多条数据的username相同时我们统计出来的数据就不同比如我们把上面其中四条数据的username都改为admin如下

此时我们再以username字段来分组效果如下

可以看到刚才统计了13条数据现在只统计到了9条说明以username来分组代表着统计username字段不同的数据而经过我们刚才的修改将5条数据的username都改为admin所以它只识别到了其中一条而且是第一条数据所以此时以username来分组来分出来9条数据这个意思可以理解吧

group by语句和count(*)函数结合 这样就可以统计指定字段的条数如下

再这样就可以统计所有的username字段以及数据条数

floor报错注入的究极原因就是出在这两个函数混用时的运行原理中如下

当count(*)和group by一起用在执行的时候会创建一个类似于下面这样的虚拟表

其中的key就是主键存放的也就是我们指定的字段数据count(*)就作为值

当该命令运行后会 遍历指定表中的数据将数据中的指定字段带去虚拟表中查询若虚拟表中存在该数据则在对应的count(*)位置+1若虚拟表中不存在则将新的字段数据添加到主键位置初始count(*)为1.例如有如下表

此时虚拟表为空先遍历第一条数据将指定的username字段数据带入虚拟表中查询也就是Dumb因为此时虚拟表为空自然是查不到的所以就在虚拟表中添加在这条数据此时虚拟表如下

接着遍历第二条数据以此类推就是没有数据就添加数据有数据就添加count(*)的值以此达到统计指定字段数据的目的

三、原理的剖析

上面我们已经知道了涉及的函数这里就给大家讲讲floor报错注入的语句以及为什么会报错首先来看看下面这个语句

select count(*),floor(rand(0)*2) from users group by floor(rand(0)*2)

执行结果如下

可以看到出现报错信息提示“1”这个主键重复这是为什么呢在讲解之前我们首先要了解一个特性就是rand()函数的一个特性

这个特性就是 rand()函数的执行速度要比 group by查询并插入key值的速度更快

首先我们讲了当group by和count(*)一起用时会生成一个虚拟表记录key和count(*)在上面的演示中我们用的是group by username也就是以username字段作为key来统计数据但是在这个报错的语句中我们使用的是group by floor(rand(0)*2),而floor(rand(0)*2)的执行结果我们上面也已经知道了就是下面这一串

按照group by语句的流程

1、首先将floor(rand(0)*2)的第一次执行结果也就是0带入虚拟表的key中查询是否存在

2、此时不存在所以会将此时的floor(rand(0)*2)的结果插入虚拟表中

3、但是不要忘了rand()函数的特性 rand()函数执行是比group by语句查询并插入key值更快的也就是floor(rand(0)*2)执行了一次后就被带去查询此时floor(rand(0)*2)仍在执行等查询完确认虚拟表中没有0这个key后就将floor(rand(0)*2)此时的结果插入虚拟表

4、但此时floor(rand(0)*2)已经执行完第二遍了结果为1就导致了 带去查询的数据为0但插入的数据却为1对应的count(*)也为1此时虚拟表如下
5、接着 floor(rand(0)*2)第三次执行结果为1group by也遍历到了第三个结果也就把1带入虚拟表中的key值去查发现存在“1”这个key值所以直接在该key值对应的count(*)加1也就是计数注意这里并不需要插入操作所以floor(rand(0)*2)的第四次执行还没有完成

6、接着 floor(rand(0)*2)第四次执行完成结果为0group by语句带0进入虚拟表key中查询发现没有这个key值所以将此时的floor(rand(0)*2)结果插入虚拟表但是因为rand()函数的特性插入还没完成之前floor(rand(0)*2)第五次执行结果已经完成结果为1所以导致带入查询的数据为0插入的数据却为1此时虚拟表如下

这样就导致出现了上面报错信息中的问题——主键重复

四、漏洞的利用

上面的讲解我们已经明白了为什么会提示“1”这个主键重复那我们应该怎样利用呢

既然是报错那我们当然就要利用它的报错信息来入手提示“1”这个主键重复“1”这个主键是怎么来的是不是我们的floor(rand(0)*2)执行出来的那我们可不可以加入我们的恶意语句让他在报错时进行执行首先看看下面的语句

select count(*),concat(user(),floor(rand(0)*2)) from users group by concat(user(),floor(rand(0)*2))

我们在floor(rand(0)*2)旁边用concat()函数连接我们的恶意语句试试看执行结果如下

成功执行我们的恶意语句并回显说明我们的想法没问题在floor(rand(0)*2)旁边连接上我们的恶意语句即可这样就达到了floor报错注入的目的将上面的恶意语句user()换成database()再试试如下

同样达到效果

五、利用的拓展

上面我们已经弄懂了floor报错注入但是每次修改语句都都要前后都修改比较麻烦有没有什么更好的方式那自然是有的就是下面要介绍的——别名

别名的格式如下

(语句)x

这里的x随便定义用啥都行

来看看这个语句

select count(*),(concat(database(),floor(rand(0)*2)))x from users group by x;

既然后面的语句和中间的语句相同所以上面语句中将中间语句加别名后面直接用x代替这样每次就只需要修改一个地方的语句就可以了

到这里floor报错注入漏洞就全部给大家介绍完了有什么问题随时私信和评论都可以哦希望能帮到你们
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6