首页
社区
课程
招聘
[原创] #30天写作挑战#2个Windows Search的漏洞的简单分析
发表于: 2020-9-30 15:15 15134

[原创] #30天写作挑战#2个Windows Search的漏洞的简单分析

2020-9-30 15:15
15134

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

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

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

• 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

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

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

Windows Search Protocol(WSP)

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

CPMConnectIn消息开始于客户端和服务器之间的会话,CPMCreateQueryIn包含查询条件并创建新查询,CPMSetBindingsIn指定如何在CPMGetRowsOut中构建搜索结果,CPMGetRowsIn从服务器返回的查询结果中请求数据。

所有的WSP消息以一个16字节的头部开始,其结构如下:

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

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

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

在上面的结构中,需要重点关注的字段是CRestrictionPresentRestrictionArray。 前者标识了RestrictionArray字段是否存在(CRestrictionPresent为0时,RestrictionArray字段不能存在;CRestrictionPresent字段为非0时,RestrictionArray字段必须存在),后者包含描述查询命令树的CRestrictionArray结构。 命令树是为搜索查询指定的限制条件和排序顺序的组合。

CRestrictionArray的详细结构如下:

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

ulType标识Restriction字段中存在的限制结构的类型。 此漏洞涉及具有指定CPropertyRestrictionulTypeRTProperty(0x5)CRestrictions。 某些CRestriction类型可以包含嵌套的CRestrictions,形成一个限制树。因此,CPropertyRestriction可以嵌入以下任何限制条件中:

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

带注释的字段可以包含更多限制,这些限制也可以包含嵌套限制,从而形成树。 CPropertyRestriction结构包含从每一行获取的属性,比较运算符和常量。 对于每一行,将行中特定属性返回的值与常量进行比较,以确定它是否具有_relop字段指定的关系。 其具体结构如下:

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

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

当运行了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字节顺序存储

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

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

暂未发现无损检测方案

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

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

Windows Search服务在处理内存中的对象时存在缺陷,会造成堆溢出。远程未经过认证的攻击者可以通过向目标主机发起一个恶意请求实现任意代码执行,成功的攻击可以获得目标主机的SYSTEM权限。

• Microsoft Windows 7
• Microsoft Windows 8
• Microsoft Windows 8.1
• Microsoft Windows 10
• Microsoft Windows Server 2003
• Microsoft Windows Server 2008
• Microsoft Windows Server 2012
• Microsoft Windows Server 2016
• Microsoft Windows Vista
• Microsoft Windows XP

获取微软官方针对此漏洞的安全补丁,地址: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2017-11771

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

Windows Search Protocol(WSP)

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

CPMConnectIn消息开始于客户端和服务器之间的会话,CPMCreateQueryIn包含查询条件并创建新查询,CPMSetBindingsIn指定如何在CPMGetRowsOut中构建搜索结果,CPMGetRowsIn从服务器返回的查询结果中请求数据。

所有的WSP消息以一个16字节的头部开始,其结构如下:

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

与本漏洞相关的是CPMGetRowsIn消息。该消息主要用于从查询中请求数据行(row),其详细格式如下:

cRowsToTransfer字段指定CPMGetRowsOut消息中包括多少row,cbRowWidth字段表示row的长度(以字节为单位),cbReserved字段指定结果在CPMGetRowsOut消息中的偏移量(与cbSeek字段相加然后进行计算偏移),cbReadBuffer字段指定 CPMGetRowsOut消息中的数据大小,以字节为单位,该字段必须设置为_cbRowWidth值的最大值或_cRowsToTransfer值的1000倍,四舍五入到最接近的512字节倍数。 该值不得超过0x00004000。

server接收到CPMGetRowsIn消息后,首先检查cbReserved的值是否小于cbReadBuffer。然后调用CFixedVarBufferAllocator::CFixedVarBufferAllocator()来初始化buffer,该buffer中应该有相应的CPMGetRowsOut消息。该函数会使用下面的方式对结果数据进行初始位置和结束位置的计算:

如果计算出的resultDataEnd不是8字节对齐的,则函数一次从resultDataEnd减去一个字节,直到对齐为止。

但是,在返回分配的buffer前,函数没有对resultDataEnd是否大于等于resultDataStart进行验证,直接调用了CFixedVarBufferAllocator::CFixedVarBufferAllocator()函数进行初始化buffer的chunk分配。AllocFixed()函数使用下面的方式来确认buffer中是否有足够空间:

因为CFixedvarBufferAllocator()没有进行两个字段大小的比较,所以有可能会出现resultDataEnd小于resultDataStart的情况,这样当两个字段进行减法运算的时候就会造成溢出。然后会调用AllocFixed()函数进行内存分配,但是此时的buffer的offset有可能是错误的。当row被复制到分配的chunk时,数据会被写到buffer的末尾,最终导致一个堆溢出。

SMB1:

SMB2:

首先进行了前期的验证工作,例如创建命名管道,建立查询连接,判断文件夹是否处于共享访问。按照查询流程依次进行数据发送,来到GetRowsIn消息:

暂无。

首先监控通过SMB建立MsFtewds命名管道的操作,然后使用byte_math检测出现漏洞的字段

SMBandx命令有链式结构,可能可以嵌套,产生绕过。

看雪论坛内部共享,请勿擅自转发,谢谢。

 
 
 
[ 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
[ 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
 
Offset     Size (bytes)     Field
--------------------------------------------
0x00     0x4             _msg
0x04     0x4             _status
0x08     0x4             _ulChecksum
0x0c     0x4             _ulReserved2
Offset     Size (bytes)     Field
--------------------------------------------
0x00     0x4             _msg
0x04     0x4             _status
0x08     0x4             _ulChecksum
0x0c     0x4             _ulReserved2
 
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
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
 
 
Offset   Size(bytes)      Field
-------------------------------------------
0x00     0x1             count
0x01     0x1             isPresent
0x02     0x3             padding
0x05     var             Restriction
Offset   Size(bytes)      Field
-------------------------------------------
0x00     0x1             count
0x01     0x1             isPresent
0x02     0x3             padding
0x05     var             Restriction
Offset   Size(bytes)     Field
------------------------------------------
0x00     0x4             ulType
0x04     0x4             Weight
0x08     var              Restriction
Offset   Size(bytes)     Field
------------------------------------------
0x00     0x4             ulType
0x04     0x4             Weight
0x08     var              Restriction
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)
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)
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
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
Offset     Size (bytes)     Field
------------------------------------------
0x00         0x2             vType
0x02         0x1             vData1
0x03         0x1             vData2
0x04         var             vValue
Offset     Size (bytes)     Field
------------------------------------------
0x00         0x2             vType
0x02         0x1             vData1
0x03         0x1             vData2
0x04         var             vValue
# 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
# 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

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-9-30 15:19 被有毒编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//