首页
论坛
专栏
课程

[原创]CVE-2017-8620:Windows Search远程代码执行漏洞简单分析及流量侧检测防御思路

2019-8-11 17:49 2941

[原创]CVE-2017-8620:Windows Search远程代码执行漏洞简单分析及流量侧检测防御思路

2019-8-11 17:49
2941

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

漏洞描述

Windows搜索服务(WSS)是windows的一项默认启用的基本服务。允许用户在多个Windows服务和客户端之间进行搜索。
Windows搜索处理内存中的对象时,存在远程执行代码漏洞,成功利用此漏洞的攻击者可以控制受影响的系统。虽然漏洞与SMB协议本身无关,但攻击者可SMB目标作为攻击媒介,因此该漏洞面临着与Wannacry类似的大规模利用风险。CNVD对该漏洞的技术评级为“高危”。

信息搜集

  1. 漏洞文件:tquery.dll
  2. 漏洞函数:CRegXpr::CRegXpr()
  3. 数据对象:一个CPropertyRestriction结构

漏洞原理分析

背景知识

  • Windows Search
  • MS-CIFS
  • MS-SMB
    因为是Windows Search的一个漏洞,需要对Windows Search具备一定的了解,此漏洞使用的SMB的途径,所以也要对SMB有一定的了解。
Windows Search是一个桌面搜索平台,具备对大多数常见文件类型和数据类型的即时搜索功能。 其主要组件是WSearch Windows服务,它负责索引、组织和提取有关本地文件系统的信息。 此外,它还实现了Generic Search Service(GSS),可以为搜索查询提供结果所需的后端功能。客户端使用Windows Search Protocol(WSP)向托管GSS的服务器发出查询。 WSP依赖于服务器消息块(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

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

 

在上面的结构中,需要重点关注的字段是CRestrictionPresent和RestrictionArray。 前者标识了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字段中存在的限制结构的类型。 此漏洞涉及具有指定CPropertyRestriction的ulType为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为0x5的CRestriction,对应于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

漏洞触发流

  1. The attacker sends a NEGOTIATE request to the target server:
    [ Attacker ] --------------------> [ Target ]
  2. The server responds:
    [ Attacker ] <-------------------- [ Target ]
  3. The attacker sends a SESSION_SETUP (NTLMSSP_NEGOTIATE) request to the target server:
    [ Attacker ] --------------------> [ Target ]
  4. The server responds:
    [ Attacker ] <-------------------- [ Target ]
  5. The attacker sends a SESSION_SETUP (NTLMSSP_AUTH) request to the target server:
    [ Attacker ] --------------------> [ Target ]
  6. The server responds:
    [ Attacker ] <-------------------- [ Target ]
  7. The attacker sends a TREE_CONNECT request to the target server:
    [ Attacker ] --------------------> [ Target ]
  8. The server responds:
    [ Attacker ] <-------------------- [ Target ]
  9. The attacker sends a CREATE request to the target server:
    [ Attacker ] --------------------> [ Target ]
  10. The server responds:
    [ Attacker ] <-------------------- [ Target ]
  11. The attacker sends a CPMConnectIn message to the target server:
    [ Attacker ] --------------------> [ Target ]
  12. The server responds with a CPMConnectOut message:
    [ Attacker ] <-------------------- [ Target ]
  13. The attacker sends a CPMCreateQueryIn message to the target server:
    [ Attacker ] --------------------> [ Target ]
  14. 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字段中存在的限制结构的类型。 设备必须查找ulType为RTProperty(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值为0x5的CRestriction节点,则设备必须将Restriction字段解析为CPropertyRestriction,其结构在前面也已经给出。

 

下一步,设备必须检查relop字段并检查其值是否等于0x6,可以使用正则表达式比较。 如果找到,则设备必须再解析prval字段。

 

检测设备必须检查vType字段并确保它等于0x1F(VT_LPWSTR)。 如果不相等,则应认为该部分流量为攻击流量。

备注

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



[公告]安全测试和项目外包请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最新回复 (2)
wsc 2019-8-13 09:08
2
0
666
niuzuoquan 2019-8-13 23:51
3
0
mark
游客
登录 | 注册 方可回帖
返回