首页
社区
课程
招聘
[原创]CVE-2015-2370之DCOM DCE/RPC协议原理详细分析
发表于: 2018-12-2 20:55 17139

[原创]CVE-2015-2370之DCOM DCE/RPC协议原理详细分析

王cb 活跃值
13
2018-12-2 20:55
17139

这个CVE-2015-2370漏洞是一种DCOM DCE/RPC协议中ntlm认证后数据包重放导致的权限提升漏洞
分析的重点DCOM DCE/RPC协议原理,这个协议主要由2块内容组成,dcom的远程激活机制和ntlm身份认证

微软官方解释
有一个运行在135端口的rpcss服务也就是dcom的激活服务负责协调本机所有com对象的激活,当本机激活时采用通过内核通信,无法捕获数据包,属于内部操作,只有当远程激活或远程重定向到本机激活这种方式才可以捕获到数据包.远程激活有2种方式,一种是采用CoCreateInstanceEx方式指定远程服务器和激活身份等参数调用rpscss的IRemoteSCMActivator接口的RemoteCreateInstance方法激活,或者CoGetClassObject =调用rpscss的IRemoteSCMActivator接口的RemoteGetClassObject方法激活同样可选指定远程服务器和激活身份等参数.还有一种方式方式是客户端marshal服务端unmarshal方式,在marshal的stream中写入OBJREF通过其中的DUALSTRINGARRAY字段指定远程解析的服务器或端口,远程服务器rpcss服务采用IObjectExporter接口中的ResolveOxid或ResolveOxid2方法实现反序列化出来需要unmarshal的远程com对象remunkown指针.CVE-2015-2370是通过在ntlm身份认证后在ResolveOxid2之后又重放了一个RemoteCreateInstance请求导致以客户端的高权限创建出来一个OLE Packager的文件实现了权限提升.用户也可以创建一个rpc服务实现自己实现这2个接口自定义的rpcss解析和激活服务.这2个模块的可以在rpcss服务加载的rpcss.dll中找到具体实现,以下是接口定义:

ntlm官方解释
CVE-2015-2370采用CoGetInstanceFromIStorage方式触发服务器从IStorage自身实现的IMarhal接口的MarshalInterface方法往stream中写入marshaldata

marshaldata是一个OBJREF可以通过如下脚本使用010editor解析

结果是一个standard的matshal模式,其中的DUALSTRINGARRAY字段指定远程解析的服务器为127.0.0.1的6666端口,也就是我们要使用中间人攻击监听端口,如下图:
127.0.0.1的6666监听的数据包经过中转后最终发送至135端口的rpcss服务,服务端先进行ServerAlive进行服务器时候在线确认,之后进行ntlm身份认证.

NTLM认证共需要三个消息完成:

(1). Type1 消息: Negotiate 协商消息。
客户端在发起认证时,是首先向服务器发送协商消息,协商需要认证的服务类型从数据包中UUID为IOXIDResolver(99fcfec4-5260-101b-bbcb-00aa0021347a)代表协商的服务是IObjectExporter,如图它被我们替换成了ISystemActivator(000001a0-0000-0000-c000-000000000046)代表协商的服务替换成IRemoteSCMActivator方式,这里CVE-2015-2370为之后重放了一个RemoteCreateInstance请求做铺垫,告诉rpcss服务要最终要激活和请求是RemoteCreateInstance数据包中的内容,Type1 消息中的Negotiate Flags代表客户端要和服务器端协商加密等级
(2). Type2 消息: Challenge 挑战消息。
服务器在收到客户端的协商消息之后,在Negotiate Flags写入出自己所能接受的加密等级,并生成一个随机数challenge返回给客户端.这个challenge实际上也可以被重放,由接受另一个Authenticate来认证,实现身份窃取,笔者会在接下去的实验中认证.如果Type2 消息的reserved字段不为0,为本机内部认证,可以在RottenPotato类似的方式使用SSPI中的函数获取SecurityContext,有兴趣的读者可以研究下.
(3). Type3 消息: Authenticate激活消息。
客户端在收到服务端发回的Challenge消息之后,读取了服务端的随机数challenge。使用自己的客户端身份信息以及服务器的随机数challenge通过复杂的运算,生成一个客户端随机数challenge和客户端的在Negotiate Flags,如果包含签名这会把整个Authenticate认证消息加入运算,导致身份窃取替换无效,如无签名可以替换,详细看实验证明.Authenticate认证消息发送之后客户端会在服务器端返回之前接着发送ResolveOxid2(IObjectExporter模式)或RemoteCreateInstance(IRemoteSCMActivator模式)给服务器端,告诉服务器端最终需要解析的请求.
(4). 服务器在收到 Type3的消息之后,处理请求后会返回激活成功或失败消息,至此dcom远程激活完成

从数据包分析IRemoteSCMActivator::RemoteCreateInstance主要是其中pActProperties结构其中包含这几个常见字段

详细解释可以参考官方文档,其中InstanceInfoData的InstantiatedObjectClsId是表示要创建com实例的OLE Packager的clsid: {F20DA720-C02F-11CE-927B-0800095AE340},由于wireshark错位的原因以二进制中的数据为准
OLE Packager是一个ActiveX控件的包格式,会将自身在pActProperties其中的InstanceInfoData字段的ifdStg的marshal结构中的二进制数据写入C:\Users\<username>\AppData\Local\Temp(2)的文件中当被创建时

这个ifdStg也是一个OBJREF结构,它通过一个ObjrefMoniker将这个OLE Packager对象转换而成,CreateObjrefMoniker是一个将com对象marshal后转换成一个moniker可以在ObjrefMoniker::GetDisplayName函数中获取Base64Encoded的OBJREF二进制数据的函数.poc中读取源文件的二进制数据filedata是最终要创建高权限文件的内容写入OLE Packager,导致在OLE Packager的unmarshal后位于C:\Users\<username>\AppData\Local\Temp\创建一个文件名为(2)的文件内容为filedata,通过创建CreateJunction给temp和C:\users\public\libraries\Sym文件夹使(2)的文件也会在Sym里创建,同时创建CreateSymlink给Sym文件夹的(2)文件和最终要写入的任意文件路径,导致(2)中的filedata二进制写入目标文件,最终实现RemoteCreateInstance被服务器端解析后以高权限进程写入任意文件

操作系统:Windows Server 20008 R2
开发环境: vs2013

我设计了一个实验来演示ntlm数据包重放现象,git地址
我创建了2个用户alice和bob,分别以alice和bob身份CoCreateInstanceEx创建一个com对象.然后把这2个创建过程的数据包通过2个lcx服务器(192.168.0.6=>proxy1和192.168.0.12->proxy2)的135端口中转至本机135端口,通过以下lcx命令:
在192.168.0.6和192.168.0.12上分别执行
lcx -listen 1234 135
在本机上执行
lcx -slave 192.168.0.6 1234 127.0.0.1 2222
lcx -slave 192.168.0.12 1234 127.0.0.1 6666
过程如下图:

在这个进程中把把rpcss服务给alice的ntlm认证tyep2 Challenge激活消息转发给接收bob,alice绑定的rpcss服务接收bob的tyep3 Authenticate消息的,把rpcss服务给bob的tyep2 Challenge转发给alice,bob绑定rpcss服务接收alice的tyep3 Authenticate消息的,由于ntlm机制的原因Challenge和Authenticate消息都是本机的激活消息,Authenticate消息也没有给自己添加签名(IRemoteSCMActivator模式),我们看数据包分析

结果都返回了RemoteCreateInstance成功的返回消息
接下来我们把alice的身份换成了一个不存在的用户alice1,也以同样的方式转发tyep2 Challenge和tyep3 Authenticate消息,实验的结果是这个不存在的alice1用户反而被bob成功创建CoCreateInstanceEx了com对象,反过来说原本应该成功的bob被alice1的身份替换了反而创建失败


[培训]科锐逆向工程师培训第53期2025年7月8日开班!

最后于 2019-8-9 09:04 被王cb编辑 ,原因: objref脚本更新
收藏
免费 4
支持
分享
最新回复 (2)
雪    币: 42947
活跃值: (65767)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
感谢分享!
2018-12-3 09:16
0
雪    币: 70
活跃值: (106)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
357K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6F1K9h3E0D9j5i4y4T1i4K6u0r3M7%4m8D9L8$3W2@1M7H3`.`.
2018-12-3 09:39
0
游客
登录 | 注册 方可回帖
返回