zoukankan      html  css  js  c++  java
  • Mysql报错注入原理分析(count()、rand()、group by)

     

    报错需要count(*),rand()、group by,三者缺一不可
    前提:当行数大于等于3行时才会报错。
    原链接:https://www.cnblogs.com/xdans/p/5412468.html

    几个fool()原理解释:

    https://www.cnblogs.com/xdans/p/5412468.html
    https://www.cnblogs.com/litlife/p/8472323.html
    http://www.cnblogs.com/xishaonian/p/6227405.html

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

    首先看经典的floor注入语句:

    and select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)

    第一眼看起来有些懵逼,我们来从最基本的入手,最后在分析这个语句

    首先是floor()报错产生的条件:

    select count(*) ,floor(rand(0)*2)x from security.users group by x(自定义数据库的一张表)

    这里解释一下x是什么意思,可能有些同学不太熟悉sql语句,floor(rand(0)*2)x的x是为floor(rand(0)*2)添加了一个别名,就是x就等于floor(rand(0)*2),这样做的目的是

    让group by 和 floor(rand(0)*2)相遇(请原谅我这么解释),

     

    下一步我们在报错位置处加上我们想要的子查询,用concat()拼接:

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

    security就是我们想要的数据库名,1是上一步拼接的。

    但现在是不是就可以直接使用了呢?还有几个步骤,先看直接拼接到and 后会怎样:

    select * from security.users where id=1 and (select count(*) ,concat(database(),floor(rand(0)*2)x) from security.users group by x)

     

    报了一个错,百度一番发现引发这个错误的原因很多,这里我是觉得我们构建的select语句的结果是一个结果表,而and 需要一个布尔值,也就是0或非零的值,那我们在嵌套一个查询,前面说了select 的结果是一个结果表,那我们就可再从这个表执行查询,只不过这次select的值是非零数字:

    select 1 from (select count(*) ,concat(database(),floor(rand(0)*2))x from security.users group by x)a

    再啰嗦一句,最后这个a和之前解释的x的作用是一样的,是前面括号内容的别名,

    sql语句要求在查询结果的基础上再执行查询时,必须给定一个别名。

    嵌套进and后执行

    select * from security.users where id=1 and(select 1 from (select count(*) ,concat(database(),floor(rand(0)*2))x from security.users group by x)a)

     

    大功告成

    我们完成了刚开始引入的floo()注入语句

    floor()报错注入

    一 随机因子具有决定权(rand()和rand(0))

    随机因子指的是rand(x) x是否有。

    当插入一条记录时,不报错。

     

    增加一条记录,有时候报错。

     

     

    再增加一条记录也和2条记录一样进行随机报错。
    三条及以上和2条记录一样进行随机报错。

    分别对floor(rand()*2)和floor(rand(0)*2)在多记录表中执行多次(记录选择10条以上),在有12条记录表中执行结果如下图:

     

    连续3次查询,毫无规则,接下来看看select floor(rand(0)*2) from T-Safe;,如下图:

     

    可以看到floor(rand(0)*2)是有规律的,而且是固定的。

    二 count与group by的虚拟表

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

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

     

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

     

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

    三 floor(rand(0)*2)报错

    1.查询的时候如果使用rand()的话,该值会被计算多次,就是在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次,以此类推。

                   注:使用group by,即虚表存储是按照group by 计算的那一列来从上往下来计算,取一条记录判断虚表是否存在时会使函数执行一遍,当存入的时候(即表中key值无此值)会将原函数存入,但是存的内容是最终结果,即原函数会被再次执行结果存入虚表,当表中有此键值对,那么只需count+1,不用再存key,所以比较时会计算一次,存入时又会计算一次

    2.在使用count(*)时,如

          select count(*) from test group by x;  x=floor(rand(0)*2)

                    mysql执行此句时会创建一个虚表,虚表一共两个字段主键是x,另外一个字段是count(*)

    3.首先知道floor(rand(0)*2)的值为011011...,

    4.执行的过程floor(rand(0)*2)报错的原因):(插入之前是表面显示数据,实际比较时和存储时为表面数据计算之后的结果,这取决于数据库的一种存储机制,表面的sql语句会被审查,然后执行存入数据库,再回显数据库中存的内容,即结果)

    select count(*) from test group by floor(rand(0)*2) ;
    select count(*),floor(rand(0)*2) from test group by floor(rand(0)*2) ;
                (这个位置的floor(..))有没有无所谓用不到

      1).查询前默认会建立空虚拟表如下图:

       

       2).开始执行,查询第一条记录(即数据),在使用group by时 floor(rand(0)*2)执行一次,结果为0,即x=0(第一次执行),然后发现虚表中没有key=0的键值对记录,则floor(rand(0)*2)会被存入虚表,存入时会被计算为实际的值,即会被再执行一次(第二次执行),结果为1插入虚表,同时count由0变1。

      

       3)取第二条记录,floor(rand(0)*2)执行一次,结果为1(第三次执行),查询虚表,发现虚表中有1,则直接count+1,不用再存key,所以floor(rand(0)*2)不会再被计算。

     

      4).取第三条记录,floor(rand(0)*2)执行一次,结果为0,发现虚表中没有key=0,那么floor(rand(0)*2)会再次执行并存入虚表,此次计算结果为1(第五次执行),与已有的key冲突了,所以插入时报错。

           5).整个查询过程floor(rand(0)*2)被计算了5次,查询原数据表3次,所以这就是为什么数据表中需要3条数据,使用该语句才会报错的原因。

    四 floor(rand()*2)报错

    由此我们可以同样推理出不加入随机因子的情况,由于没加入随机因子,所以floor(rand()*2)是不可测的,因此在两条数据的时候,只要出现下面情况,即可报错,如下图:

     

    最重要的是前面几条记录查询后不能让虚表存在0,1键值,如果存在了,那无论多少条记录,也都没办法报错,因为floor(rand()*2)不会再被计算做为虚表的键值,这也就是为什么不加随机因子有时候会报错,有时候不会报错的原因。如图:

     

    当前面记录让虚表长成这样子后,由于不管查询多少条记录,floor(rand()2)的值在虚表中都能找到,所以不会被再次计算,只是简单的增加count()字段的数量,所以不会报错,比如floor(rand(1)*2),如图:

     

    在前两条记录查询后,虚拟表已经存在01两个键值了,所以后面再怎么弄还是不会报错。

    总之报错需要count(*),rand()、group by,三者缺一不可

  • 相关阅读:
    AS将一个项目导入到另一个项目中
    Android Studio出现:Cause: unable to find valid certification path to requested target
    小米手机Toast带app名称
    PopupWindow 点击外部区域无法关闭的问题
    EditText inputType类型整理
    Fragment通过接口回调向父Activity传值
    Android selector一些坑
    Installation failed with message Failed to commit install session 634765663 with command cmd package
    旷视上海研究院机器人方向招聘
    语义SLAM的数据关联和语义定位(四)多目标测量概率模型
  • 原文地址:https://www.cnblogs.com/forforever/p/12864814.html
Copyright © 2011-2022 走看看