查看原文
其他

Windows Search远程代码执行漏洞简单分析及流量侧检测防御思路

有毒 看雪学院 2019-09-17

本文为看雪论坛精华文章

看雪论坛作者ID:有毒



漏洞描述



Windows搜索服务(WSS)是Windows的一项默认启用的基本服务。允许用户在多个Windows服务和客户端之间进行搜索。

Windows Search是一个桌面搜索平台,具备对大多数常见文件类型和数据类型的即时搜索功能。 其主要组件是WSearch Windows服务,它负责索引、组织和提取有关本地文件系统的信息。此外,它还实现了Generic Search Service(GSS),可以为搜索查询提供结果所需的后端功能。客户端使用Windows Search Protocol(WSP)向托管GSS的服务器发出查询。WSP依赖于服务器消息块(SMB)命名管道协议进行消息传输和身份验证。     


Windows搜索处理内存中的对象时,存在远程执行代码漏洞,成功利用此漏洞的攻击者可以控制受影响的系统。虽然漏洞与SMB协议本身无关,但攻击者可SMB目标作为攻击媒介,因此该漏洞面临着与Wannacry类似的大规模利用风险。CNVD对该漏洞的技术评级为“高危”。

信息搜集


漏洞文件:tquery.dll

漏洞函数:CRegXpr::CRegXpr()

数据对象:一个CPropertyRestriction结构

背景知识:Windows Search、MS-CIFS、MS-SMB

因为是Windows Search的一个漏洞,需要对Windows Search具备一定的了解,此漏洞使用的SMB的途径,所以也要对SMB有一定的了解。


漏洞原理分析



Windows Search Protocol


使用WSP的最小搜索查询可能类似于以下流程:

[ Client ] --------------------> [ Server ] - CPMConnectIn
[ Client ] <-------------------- [ Server ] - CPMConnectOut
[ Client ] --------------------> [ Server ] - CPMCreateQueryIn
[ Client ] <-------------------- [ Server ] - CPMCreateQueryOut
[ Client ] --------------------> [ Server ] - CPMSetBindingsIn request
[ Client ] <-------------------- [ Server ] - CPMSetBindingsIn response
[ Client ] --------------------> [ Server ] - CPMGetRowsIn
[ Client ] <-------------------- [ Server ] - CPMGetRowsOut
[ Client ] --------------------> [ Server ] - CPMGetFreeCursorIn
[ Client ] <-------------------- [ Server ] - CPMGetFreeCursorOut
[ Client ] --------------------> [ Server ] - CPMDisconnect


CPMConnectIn消息开始客户端和服务器之间的会话,CPMCreateQueryIn包含规范并创建新查询,CPMSetBindingsIn指定如何在CPMGetRowsOut中构建搜索结果,CPMGetRowsIn从查询中请求数据行。
 
所有的WSP消息以一个16字节的头部开始,其结构如下:

Offset Size (bytes) Field
--------------------------------------------
0x00 0x4 _msg
0x04 0x4 _status
0x08 0x4 _ulChecksum
0x0c 0x4 _ulReserved2


_msg字段标识标头部后面的消息类型,_status字段包含所请求操作的状态并由服务器填充,_ulChecksum包含从_ulReserved2字段后面开始的消息的校验和。跟本漏洞相关的是CPMCreateQueryIn消息,故本文暂且重点关注该消息。 此消息创建一个新的搜索查询,并具有以下结构:
 

Offset Size (bytes) Field
--------------------------------------------------------------------
0x00 0x4 Size
0x04 0x1 CColumnSetPresent
0x05 0x3 paddingCColumnSet
0x08 var (w) ColumnSet
0x08 + w 0x1 CRestrictionPresent
0x09 + w var (x) RestrictionArray
0x09 + w + x 0x1 CSortSetPresent
0x0a + w + x 0x3 paddingCCortSet
0x0d + w + x var (y) SortSet
0x0d + w + x + y 0x1 CCategorizationSetPresent
0x0e + w + x + y 0x3 paddingCCategorizationSet
0x11 + w + x + y var (z) CCategorizationSet
0x11 + w + x + y + z 0x14 RowSetProperties
0x25 + w + x + y + z var (m) PidMapper
0x25 + w + x + y + z + m var (n) GroupArray
0x25 + w + x + y + z + m + n 0x4 Lcid


从上面的结构中可以看出,有很多字段数值大小不是固定的,这对后续的流量监测可能造成很大困难。


在上面的结构中,需要重点关注的字段是CRestrictionPresentRestrictionArray 前者标识了RestrictionArray字段是否存在,后者包含描述查询命令树的CRestrictionArray结构。 

命令树是为搜索查询指定的限制和排序顺序的组合。CRestrictionArray具有以下结构:

Offset Size(bytes) Field
-------------------------------------------
0x00 0x1 count
0x01 0x1 isPresent
0x02 0x3 padding
0x05 var Restriction


isPresent字段标识Restriction字段是否存在且Restriction字段是否包含CRestriction结构。CRestriction在查询命令树中包含限制节点,并具有以下格式:

Offset Size(bytes) Field
------------------------------------------
0x00 0x4 ulType
0x04 0x4 Weight
0x08 var Restriction


ulType标识Restriction字段中存在的限制结构的类型。此漏洞涉及具有指定CPropertyRestrictionulType为RTProperty(0x5)CRestrictions 

某些CRestriction类型可以包含嵌套的CRestrictions,形成一个限制树;因此,CPropertyRestriction可以嵌入以下任何限制中:

RTAnd (0x1), Restriction contains a CNodeRestriction structure
RTOr (0x2), Restriction contains a CNodeRestriction structure
RTNot (0x3), Restriction contains a CRestriction structure
RTProximity (0x6), Restriction contains a CNodeRestriction structure
RTVector (0x7), Restriction contains a CVectorRestriction structure
RTCoerce_Add (0xA), Restriction contains a CCoercionRestriction structure
RTCoerce_Multiply (0xB), Restriction contains a CCoercionRestriction structure
RTCoerce_Absolute (0xC), Restriction contains a CCoercionRestriction structure
RTPhrase (0x00FFFFFD), Restriction contains a CNodeRestriction structure


上述列表中的限制具有以下结构:

CNodeRestriction:
Offset Size(bytes) Field
----------------------------------------------------------------
0x00 0x4 cNode (number of structures in paNode)
0x04 var paNode (array of CRestriction structures)

CVectorRestriction:
Offset Size (bytes) Field
------------------------------------------------------------
0x00 var (n) pres (CNodeRestriction structure)
0x00 + n 0x3 padding
0x03 0x4 ulRankMethod


CCoercionRestriction:
Offset Size (bytes) Field
-------------------------------------------------------
0x00 0x4 flValue
0x04 var childRes (CRestriction structure)


带注释的字段可以包含更多限制,这些限制也可以包含嵌套限制,从而形成树。 

CPropertyRestriction结构包含从每一行获取的属性,比较运算符和常量。 对于每一行,将行中特定属性返回的值与常量进行比较,以确定它是否具有指定的关系。此限制具有以下结构:

Offset Size (bytes) Field
------------------------------------------
0x00 0x4 relop
0x04 var (m) Property
0x04 + m var (n) prval
0x04 + m + n 0x3 padding
0x07 + m + n 0x4 lcid


relop字段标识比较的类型,例如大于、小于、正则表达式等。属性字段标识要匹配的属性,而prval字段指定与属性相关的值。 

prval字段包含一个CBaseStorageVariant项,它具有以下结构:

Offset Size (bytes) Field
------------------------------------------
0x00 0x2 vType
0x02 0x1 vData1
0x03 0x1 vData2
0x04 var vValue


vType字段标识存储在vValue中的值的类型。

此漏洞涉及VT_LPWSTR vType,该vType用于存储以null结尾的Unicode字符串。


漏洞流程



当服务器收到CPMCreateQueryIn消息时,它会解析RestrictionArray并为每个限制实例化相关对象。如果服务解析ulType为0x5CRestriction,对应于CPropertyRestriction,则解组prval字段并实例化CBaseStorageVariant对象。

如果CPropertyRestriction的relop字段与0x6匹配,表示正则表达式比较,则服务开始将正则表达式解析为确定性有限自动机(DFA)。

但是,在解析正则表达式之前,服务无法验证CBaseStorageVariant对象的类型是否为VT_LPWSTR,这是一个以null结尾的Unicode字符串。如果类型不是VT_LPWSTR,则会发生类型混淆。

远程未经身份验证的攻击者可以通过向目标服务器发送恶意CPMCreateQueryIn消息来利用这些漏洞。成功利用可能会导致在SYSTEM上下文中的目标服务器上执行远程代码。

需要注意,SMB和WSP中的所有多字节整数都以little-endian字节顺序存储。


>>>>

漏洞触发代码


使用的dll版本为7.0.7601.23861


CPropertyRestriction::CPropertyRestriction(long, class PDeSerStream &):

.text:6EC88B61 push ebx ; struct PDeSerStream *
.text:
6EC88B62 lea ecx, [ebp+var_20]
.text:6EC88B65 call ??0CStorageVariant... ; unmarshall prval
.text:6EC88B6A push eax
.text:6EC88B6B mov ecx, edi
.text:6EC88B6D mov byte ptr [ebp+var_4], 3
.text:6EC88B71 call ??4CStorageVariant... ; CStorageVariant::operator=


Parse(const struct CRestriction , struct CTimeLimit ):

.text:6ED350B3 cmp eax, 6 ; eax contains relop, check if relop indicates regexp
.text:6ED350B6 jnz short loc_6ED350DE
.text:6ED350B8 push 40h ; unsigned int
.text:6ED350BA call ?ciNew@@YGPAXI@Z ; ciNew(uint)
.text:6ED350BF mov [ebp+arg_0], eax
.text:6ED350C2 mov ecx, [esi+14h]
.text:6ED350C5 mov edx, [esi+10h]
.text:6ED350C8 push ecx
.text:6ED350C9 push edx
.text:6ED350CA push [ebp+arg_4]
.text:6ED350CD mov ecx, eax
.text:6ED350CF push esi
.text:6ED350D0 mov byte ptr [ebp+var_4], 7
.text:6ED350D4 call ??0CRegXpr@@QA... ; CRegXpr(), 解析正则表达式


CRegXpr::CRegXpr(class CInternalPropertyRestriction *, class CTimeLimit &, unsigned long, unsigned long):

.text:6ED37ABC push 0A8h ; unsigned int
.text:6ED37AC1 call ?ciNew@@YGPAXI@Z ; ciNew(uint)
.text:6ED37AC6 mov [ebp+var_7C], eax
.text:6ED37AC9 push [ebp+var_78] ; int
.text:6ED37ACC mov ecx, [esi+20h]
.text:6ED37ACF push 0 ; int
.text:6ED37AD1 push [ebp+arg_4] ; int
.text:6ED37AD4 mov byte ptr [ebp+var_4], 6
.text:6ED37AD8 push ecx ; unsigned __int16 *
.text:6ED37AD9 mov ecx, eax
.text:6ED37ADB call ??0CDFA@@Q... ; CDFA::CDFA(), 不检测类型就直接解析vValue


CNFA::CNFA(unsigned __int16 *, int, int):

.text:6AF2781E mov dx, [eax] ; eax指向VT_LPWSTR data
.text:6AF27821 inc eax
.text:6AF27822 inc eax
.text:6AF27823 cmp dx, di
.text:6AF27826 jnz short loc_6AF2781E



>>>>

漏洞触发流


The attacker sends a NEGOTIATE request to the target server:
[ Attacker ] --------------------> [ Target ]
The server responds:
[ Attacker ] <-------------------- [ Target ]
The attacker sends a SESSION_SETUP (NTLMSSP_NEGOTIATE) request to the target server:
[ Attacker ] --------------------> [ Target ]
The server responds:
[ Attacker ] <-------------------- [ Target ]
The attacker sends a SESSION_SETUP (NTLMSSP_AUTH) request to the target server:
[ Attacker ] --------------------> [ Target ]
The server responds:
[ Attacker ] <-------------------- [ Target ]
The attacker sends a TREE_CONNECT request to the target server:
[ Attacker ] --------------------> [ Target ]
The server responds:
[ Attacker ] <-------------------- [ Target ]
The attacker sends a CREATE request to the target server:
[ Attacker ] --------------------> [ Target ]
The server responds:
[ Attacker ] <-------------------- [ Target ]
The attacker sends a CPMConnectIn message to the target server:
[ Attacker ] --------------------> [ Target ]
The server responds with a CPMConnectOut message:
[ Attacker ] <-------------------- [ Target ]
The attacker sends a CPMCreateQueryIn message to the target server:
[ Attacker ] --------------------> [ Target ]
The server responds with a CPMCreateQueryOut message:
[ Attacker ] <-------------------- [ Target ]



流量侧检测防御思路


1、首先确认为SMB消息,这个就简单略过了,经常做流量检测的都知道怎么防御(其实是我懒23333)

2、对于SMB1,首先检测pipe的使用,经常使用的命令是SMB_COM_NT_CREATE_ANDX,代码为0xa2,其对应的结构如下:

Offset Size (bytes) Field
-----------------------------------------------------------
0x00 0x1 WordCount
0x01 0x1 AndXCommand
0x02 0x1 AndXReserved
0x03 0x2 AndXOffset
0x04 0x1 Reserved
0x05 0x2 NameLength
0x07 0x4 Flags
0x0b 0x4 RootDirectoryFID
0x0f 0x4 DesiredAccess
0x13 0x8 AllocationSize
0x1b 0x4 ExtFileAttributesMicrosoft Research Service 20
0x1f 0x4 ShareAccess
0x23 0x4 CreateDisposition
0x27 0x4 CreateOptions
0x2b 0x4 ImpersonationLevel
0x2f 0x1 SecurityFlags
0x30 0x2 ByteCount
0x32 var FileName


需要对所有SMB_COM_NT_CREATE_ANDX


命令中的FileName字段进行检测,查看是否存在Unicode编码的 "\MsFteWds" 。


对于相同的“\ MsFteWds”值,检测设备还必须检查能够打开命名管道的以下任何不常见命令的Name / FileName字段:

• SMB_COM_NT_TRANSACT with NT_TRANSACT_CREATE subcommand
• SMB_COM_TRANSACTION2 with TRANS2_OPEN2 subcommand
• SMB_COM_OPEN (deprecated)
• SMB_COM_OPEN_ANDX (deprecated)
• SMB_COM_TRANSACTION with TRANS_CALL_NMPIPE subcommand (obsolescent)


如果找到打开上述“\ MsFteWds”管道的任何命令,则设备必须继续检查此会话中的任何后续SMB1命令,并查找能够写入命名管道的命令。 这些命令包括:

SMB_COM_WRITE
SMB_COM_WRITE_AND_UNLOCK
SMB_COM_WRITE_RAW
SMB_COM_WRITE_MPX
SMB_COM_WRITE_AND_CLOSE
SMB_COM_WRITE_ANDX
SMB_COM_WRITE_PRINT_FILE
SMB_COM_TRANSACTION (TRANS_RAW_WRITE_NMPIPE)
SMB_COM_TRANSACTION (TRANS_WRITE_NMPIPE)


如果找到上述数据,检测设备必须解析这些结构以获得发送到命名管道的数据。获得数据后,必须将此数据解析为WSP消息。


3、WSP消息的解析

设备必须检查CRestrictionPresent是否包含非零值,如果是,则根据以下结构解析RestrictionArray

Offset Size (bytes) Field
-------------------------------------------
0x00 0x1 count
0x01 0x1 isPresent
0x02 0x3 padding
0x05 var Restriction


检测设备必须检查isPresent字段的值为0x1,如果相等,则将Restriction字段解析为CRestriction结构数组,其数量与count字段相等。

必须按如下方式解析CRestriction结构:

Offset Size (bytes) Field
------------------------------------------
0x00 0x4 ulType
0x04 0x4 Weight
0x08 var Restriction


ulType标识Restriction字段中存在的限制结构的类型。 设备必须查找ulTypeRTProperty(0x5)CRestriction节点,对应于CPropertyRestriction。 请注意,有几个限制允许嵌套限制,其中可能出现CPropertyRestriction 

因此,设备还必须解析这些限制及其相应的字段,可能包含其他限制并找到嵌套的CPropertyRestrictions

以下是包含嵌套限制的限制的ulType值列表:

RTAnd (0x1), Restriction contains a CNodeRestriction structure
RTOr (0x2), Restriction contains a CNodeRestriction structure
RTNot (0x3), Restriction contains a CRestriction structure
RTVector (0x7), Restriction contains a CVectorRestriction structure
RTCoerce_Add (0xA), Restriction contains a CCoercionRestriction structure
RTCoerce_Multiply (0xB), Restriction contains a CCoercionRestriction structure
RTCoerce_Absolute (0xC), Restriction contains a CCoercionRestriction structure


上述列表中的限制的结构在前面已经给出,根据之前给出的相关结构,检测设备必须解析可能包含其他限制的限制的相关字段。

如果设备找到嵌套的CRestriction,则它必须递归检查ulType for RTProperty(0x5)或任何可能的递归类型。 

此外,如果设备找到嵌套的CNodeRestriction,它必须检查paNode数组中的每个CR限制,查找等于RTProperty和递归类型的ulType值。换句话说,检测设备必须检查每个嵌套节点。
 
如果检测设备找到ulType值为0x5CRestriction节点,则设备必须将Restriction字段解析为CPropertyRestriction,其结构在前面也已经给出。
 
下一步,设备必须检查relop字段并检查其值是否等于0x6,可以使用正则表达式比较。如果找到,则设备必须再解析prval字段。
 
检测设备必须检查vType字段并确保它等于0x1F(VT_LPWSTR)。如果不相等,则应认为该部分流量为攻击流量。


以上只是个人综合其他前辈的经验进行的分析结果,可能存在偏差或错误。这个漏洞需要了解的东西比较多,分析起来比较麻烦。而且以上分析仅仅针对SMBv1的情况,对于SMBv2和SMBv3的情况尚未分析完毕,仍需继续努力啊。欢迎各位师傅前辈指导交流。




- End -




看雪ID:有毒  

https://bbs.pediy.com/user-779730.htm  


*本文由看雪论坛 钞Sir 原创,转载请注明来自看雪社区




进阶安全圈,不得不读的一本书





推荐文章++++

HEVD 内核漏洞之未初始化栈变量

Talosec硬件钱包的侧信道攻击测试分析    Part1

Linux Kernel Exploit 内核漏洞学习(3)-Bypass-Smep

HW行动 rdpscan后门简单分析

打造自己的PE解释器






官方微博:看雪安全

商务合作请发邮件至:wsc@kanxue.com




“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存