微软JET引擎中Msrd3x代码执行漏洞分析
字数 1690 2025-08-29 08:31:42
Microsoft JET引擎Msrd3x代码执行漏洞(CVE-2019-0538)分析教学文档
漏洞概述
- 漏洞编号: CVE-2019-0538
- 影响组件: Windows JET引擎中的Msrd3x40.dll
- 影响范围: Windows 7至Windows 10所有版本
- 漏洞类型: 远程代码执行
- 发现者: Fortinet的FortiGuard实验室研究员Honggang Ren
- 披露时间: 2018年9月报告,2019年1月微软发布补丁
漏洞触发机制
触发方式
-
通过Excel触发:
- 在Excel中使用OLEDB外部数据源加载精心构造的MDB文件
- 文件可放置于本地或SMB共享中
-
通过脚本触发:
- 在Windows 10中执行命令:
cscript.exe trigger.vbs
- 在Windows 10中执行命令:
崩溃表现
- 崩溃发生在
msrd3x40!free函数中 - 内存处于
MEM_RESERVE状态 - 无效堆地址被释放导致崩溃
漏洞技术分析
正常流程与异常流程对比
| 正常MDB文件 | 恶意构造的MDB文件 |
|---|---|
| 头版本字段为1 | 头版本字段为0 |
| 在msjet40.dll中完成标头解密 | 跳过标头解密操作 |
| 不调用msrd3x40.dll | 调用msrd3x40.dll!ErrIsamOpenDatabase |
关键漏洞点分析
-
版本字段欺骗:
- 恶意MDB文件将版本字段设为0而非正常的1
- 导致程序跳过msjet40.dll中的标头解密操作
- 错误地调用msrd3x40.dll中的函数
-
RC4解密后的关键数据变化:
- 偏移量0x42处的数据初始为0x86
- 解密后变为0
- 导致程序进入错误的分支路径
-
乘法因子生成:
Database::AssignUserNumber函数生成错误的密钥乘法因子0x100- 正常情况不应产生如此大的值
-
无效堆地址生成:
- 乘法因子0x100导致目标堆地址的低位字被1覆盖
- 生成无效的堆指针
- 后续尝试释放该无效指针导致崩溃
漏洞利用链
- 构造特殊MDB文件(版本字段=0)
- 触发错误的分支路径(调用msrd3x40.dll)
- RC4解密后关键偏移量变为0
- 生成错误的乘法因子0x100
- 覆盖堆指针低位字
- 生成无效堆地址
- 释放无效地址导致崩溃
- 精心构造可实现代码执行
防护建议
-
官方补丁:
- 安装微软2019年1月发布的安全更新
-
Fortinet防护:
- 自2018年10月12日起,Fortinet IPS解决方案已提供防护签名:
MS.JET.Database.Engine.Msrd3x.Remote.Code.Execution
- 自2018年10月12日起,Fortinet IPS解决方案已提供防护签名:
-
通用防护措施:
- 限制不可信MDB文件的处理
- 监控异常Excel/OLE DB行为
- 实施最小权限原则
逆向工程关键点
-
关键函数:
msjet40!ErrOpenForeignDatabase+0x65msrd3x40.dll!ErrIsamOpenDatabaseDatabase::AssignUserNumberDatabase::MarkCorrupt
-
关键内存操作:
[ecx + 6c]- 存储乘法因子[ecx + eax * 2 + 194h]- 被覆盖的内存位置
-
调试技巧:
- 使用
gflags /p /enable cscript.exe /full启用页堆调试 - 检查内存状态是否为
MEM_RESERVE
- 使用
漏洞复现环境
- 操作系统: Windows 7至Windows 10未打补丁版本
- 调试工具: WinDbg, GFlags
- 触发文件: 精心构造的MDB文件
- 触发方式: Excel或cscript.exe
总结
该漏洞利用Windows JET引擎对MDB文件版本检查的缺陷,通过精心构造的文件头引导程序进入错误处理路径,最终导致堆损坏和可能的代码执行。漏洞的根本原因在于版本字段欺骗导致程序采取错误分支,结合后续解密和内存操作中的缺陷,形成了完整的利用链。