目录

CVE-2017-8620 Windows Search远程代码执行漏洞简单分析

CVE-2017-8620 Windows Search远程代码执行漏洞简单分析

一、漏洞信息

1. 漏洞简述

  • 漏洞名称:Windows Search Remote Code Execution Vulnerability
  • 漏洞编号:CVE-2017-8620;Bugtraq ID:100034
  • 漏洞类型:Remote Code Execution

2. 组件概述

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

Microsoft Windows的所有版本均附带服务器消息块(SMB)协议的实现。 SMB是本机Windows网络框架,支持文件共享,网络打印,远程过程调用和其他功能。在Windows系统上,SMB协议通过附加的安全性,文件和磁盘管理支持扩展了CIFS协议。 通过各种SMB命令和子命令类型提供这些功能。

3. 漏洞概述

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

4. 漏洞影响版本

• Microsoft Windows 10 for 32-bit Systems • Microsoft Windows 10 for x64-based Systems • Microsoft Windows 2012 R2 • Microsoft Windows 8.1 for 32-bit Systems • Microsoft Windows 8.1 for x64-based Systems • Microsoft Windows RT 8.1 • Microsoft Windows Windows 7 for 32-bit Systems Service Pack 1 • Microsoft Windows Windows 7 for x64-based Systems Service Pack 1 • Microsoft Windows Server 2008 for 32-bit Systems SP 2 (Server Core) • Microsoft Windows Server 2008 for 32-bit Systems SP2 • Microsoft Windows Server 2008 for Itanium-based Systems Service Pack 2 • Microsoft Windows Server 2008 for x64-based systems • Microsoft Windows Server 2008 R2 for Itanium-based Systems Service Pack 1 • Microsoft Windows Server 2012 R2 • Microsoft Windows Server 2012 R2 (Server Core) • Microsoft Windows Server 2016 • Microsoft Windows Server 2016 Server Core

5. 解决方案

获取该漏洞补丁,地址:https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-8620

二、漏洞复现

三、漏洞分析

1. 漏洞基本信息

  • 漏洞文件:tquery.dll
  • 漏洞函数:CRegXpr::CRegXpr()
  • 漏洞对象:一个CPropertyRestriction结构,其prval具有与VT_LPWSTRvType混淆的VT_LPWSTR以外的vType

2. 背景知识

备注:此处略去SMB相关介绍,漏洞自身与SMB关系不大,SMB只是作为WSP传输的工具协议,使用的pipe名称为MsFteWds。

Windows Search Protocol(WSP)

使用WSP的最小搜索查询其流程大概如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[ 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字节的头部开始,其结构如下:

1
2
3
4
5
6
Offset 	Size (bytes) 	Field
--------------------------------------------
0x00 	0x4 			_msg
0x04 	0x4 			_status
0x08 	0x4 			_ulChecksum
0x0c 	0x4 			_ulReserved2

_msg字段标识标头部后面的消息类型(有的一个value表示两种类型,此时要根据数据流的传输方向判定具体代表哪种类型。带"In"字符的是从client到server,带"Out"字符的是从server到client);
_status字段表明所请求操作的状态,由服务器填充;
_ulChecksum包含从_ulReserved2字段后面开始的消息的校验和;
_ulReserved2字段除了后续的消息为CPMGetRowsIn之外,都必须设置为0。

跟本漏洞相关的是CPMCreateQueryIn消息, 此消息创建一个新的搜索查询,其结构如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
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字段是否存在(CRestrictionPresent为0时,RestrictionArray字段不能存在;CRestrictionPresent字段为非0时,RestrictionArray字段必须存在),后者包含描述查询命令树的CRestrictionArray结构。 命令树是为搜索查询指定的限制条件和排序顺序的组合。

CRestrictionArray的详细结构如下:

1
2
3
4
5
6
Offset   Size(bytes)  	Field
-------------------------------------------
0x00     0x1         	count
0x01     0x1         	isPresent
0x02     0x3         	padding
0x05     var         	Restriction

count字段表明Restriction字段中包含CRestriction的数量,该字段必须设置为0x01;
isPresent字段标识Restriction字段是否存在是否包含CRestriction结构,值为0(省略)或1(不省略);
CRestriction指示用于命令树节点的限制类型,类型决定了在该结构的"Restriction"字段中找到的内容,格式如下:

1
2
3
4
5
Offset   Size(bytes) 	Field
------------------------------------------
0x00     0x4        	 ulType
0x04     0x4        	 Weight
0x08     var         	 Restriction

ulType标识Restriction字段中存在的限制结构的类型。 此漏洞涉及具有指定CPropertyRestrictionulTypeRTProperty(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

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
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结构包含从每一行获取的属性,比较运算符和常量。 对于每一行,将行中特定属性返回的值与常量进行比较,以确定它是否具有_relop字段指定的关系。 其具体结构如下:

1
2
3
4
5
6
7
Offset     	    Size (bytes)         Field
------------------------------------------
0x00         	 0x4                 _relop
0x04         	 var (m)             _Property
0x04 + m    	 var (n)             _prval
0x04 + m + n 	 0x3                 _padding_lcid
0x07 + m + n 	 0x4                 _lcid

_relop字段标识比较的类型,例如, 大于,小于,正则表达式等;
_Property字段标识要匹配的属性,而_prval字段指定与属性相关的值;
_prval字段包含一个CBaseStorageVariant项,它具有以下结构:

1
2
3
4
5
6
Offset     Size (bytes)     Field
------------------------------------------
0x00         0x2             vType
0x02         0x1             vData1
0x03         0x1             vData2
0x04         var             vValue

vType字段标识存储在vValue中的值的类型。 此漏洞涉及VT_LPWSTR vType,该vType用于存储以null结尾的Unicode字符串。

3. 详细分析

当运行了GSS服务的server接受到CPMCreateQueryIn消息时,会解析RestrictionArray并为每个限制条件实例化相关对象。如果服务解析的是一个响应CPropertyR etrictionCRestriction,此时ulType的值为0x5,则解组prval字段并实例化CBaseStorageVariant对象。如果CPropertyRestrictionrelop字段的值为0x6,表示采用的操作是正则表达式比较,则服务开始将正则表达式解析为确定性有限自动机(DFA)。 但是,在解析正则表达式之前,服务未能成功验证prval字段中的CBaseStorageVariant对象的类型是否为VT_LPWSTR。如果类型不是VT_LPWSTR,则会发生类型混淆。 远程未经身份验证的攻击者可以通过向目标服务器发送恶意CPMCreateQueryIn消息来利用这些漏洞。成功利用可能会导致在SYSTEM上下文中的目标服务器上执行远程代码。 需要注意,SMB和WSP中的所有多字节整数都以little-endian字节顺序存储

4. 源码分析

使用IDA反编译存在漏洞的文件: tquery.dll version 7.0.7601.23861

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# CPropertyRestriction::CPropertyRestriction(long, class PDeSerStream &):
.text:6EC88B61 push ebx ; struct PDeSerStream *
.text:6EC88B62 lea ecx, [ebp+var_20]
.text:6EC88B65 call ?SetLPWSTR@CStorageVariant@@QAEXPBGI@Z ; 开始进行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 
.text:6AF27821 inc eax
.text:6AF27822 inc eax
.text:6AF27823 cmp dx, di
.text:6AF27826 jnz short loc_6AF2781E

5. 攻击流量

https://cdn.jsdelivr.net/gh/AlexsanderShaw/BlogImages@main/img/ana1.png

https://cdn.jsdelivr.net/gh/AlexsanderShaw/BlogImages@main/img/ana2.png

四、漏洞检测和防御

根据漏洞原理,需要对SMB、WSP的诸多命令和结构进行遍历,且WSP命令中存在诸多变量字段,数值和长度无法确定,故很难在流量侧进行防御。