0x00 前言
之前在做sqli-labs 第五第六题的时候是利用盲注来进行做的 中途操作过程非常繁杂每个信息都要使用脚本来进行拆解 就算我用python编了相应的脚本 仍然感觉麻烦 所以昨天再去看了看 好像题目的本意不是让我们用盲注的方法来实现的 题目是想让我们使用报错注入 (双查询注入)来进行获取数据库的一些信息
0x01 原理分析
首先需要知道的一些知识
为什么叫做报错注入 原因就是我们是通过反馈出来的错误来获取到我们所需要的信息的 那么这是如何报错的呢? 在数据表中由于主键是不可重复的 所以我们利用一些函数来使得主键重复从而报错 Duplicate entry
其实报错注入的种类是非常多的 但是由于本人实力有限只接触到了主键方面的报错 后续接触到了别的会陆续补充
在利用这种报错注入的过程中我们需要使用几个函数 rand() floor() count() 这三个函数 现在我先简单的解释一些这三个函数 rand()函数就是生成一个 0,1 floor()函数是一个取整函数 count()函数就是一个进行统计函数 效果如下
这是一个rand函数的效果
然后我们再来看一下 rand(0) 和rand() 有什么区别 我先说明一下 rand(0) 在超过三条之后就会有规律 我们来看图片 这样会更加的清晰
count 就是统计记录的个数 话不多说直接上图
通过前面的 rand(0)的规律 我们再乘2来看看 然后我们可以发现出来的0,1也是有规律的
然后也是看网上的文章说道 当 group by() 结合rand() count(*) 会出现报错 这也就是为什么叫做报错注入 所以我们可以利用concat 将我们的查询语句和 floor(rand(0)*2)放置到一起这样就会在报错里面输出我们想要的结果 看到这里坑定会比较迷茫吧 为什么这样会报错 先不急 我们先来看一下结果 然后后面我们就会将原理进行讲解 先把语句展示出来
?id=1" union select 1,count(),concat(0x3a,0x3a,(version()),0x3a,0x3a,floor(rand(0)2))a from information_schema.tables group by a %23
效果如下 可以看出来我们成功获取到了数据库的版本信息
原理讲解
好那么让我们现在来研究为什么 在和聚合函数组合的时候会出现错误 那么执行 select count(*) from information_schema.tables group by floor(rand(0)*)的时候会发生什么呢 根据一些资料上看到 mysql 在遇到 这个语句的时候会创建一个虚拟表 所以说流程是这样的
前面已经提到了 rand(0) * 2 在数据超过三条以上的时候 出现的数字是由规律的 类似 我们就拿前五个来说明 前五个分别是 0 1 1 0 1 在正式说明之前 有一个很关键的地方需要知道 就是 floor(rand(0)*2) 是会重复进行运算的 在插入记录的时候又会进行一次 计算
第一步
select count(*) from information_schema.tables group by floor(rand(0)*) 的时候 会创建一个虚拟表 这个虚拟表有两个字段 一个是 key也就是主键这是不可以重复的 还有一个count(*) 这个是记数的 然后第一次的数值是 0 系统发现 虚拟表中没有 0 所以会进行插入 但是在插入的时候 又会进行一次 floor(rand(0)*2) 这时候 计算结果是 1 然后将 1 插入到表中 计数为 1
第二步
之前其实已经进行了两次运算了 然后继续执行 再下一次是 1 检查虚拟表 嗯很好 1 已经存在好 那么计数加一 继续执行 根据011 011 后面那次也就是 第四次了 第四次打数字是 0 系统检查虚拟表里面是没有 0 的所以执行插入操作 然后在插入操作的时候还是会进行一次运算的 也就是说在插入的时候会进行第五次运算 所以这时候运算结果是 1 想要插入 这时候发现 虚拟表里面已经有1 由于主键不能重复 所以就报错了
所以报错注入 的 version() 可以换成别的 注入语句都是可以的
select 1,count(),concat(0x3a,0x3a,(version()),0x3a,0x3a,floor(rand(0)2))a from information_schema.tables group by a %23
参考文章链接
https://mochazz.github.io/2017/09/23/Double_%20SQL_Injection/
评论