010补丁对比发现的九个漏洞(9)

SrvOs2FeaListToNt函数会通过如下伪代码完成转换:

SrvOs2FeaListToNt() {     outputLen = SrvOs2FeaListSizeToNt(feaList);     output = SrvAllocateNonPagedPool(outputLen);     // start copy all FEA data to output in a list of FILE_FULL_EA_INFORMATION format }

SrvOs2FeaListToNt先调用SrvOs2FeaListSizeToNt,根据原始FEA_LIST计算出FILE_FULL_EA_INFORMATION列表缓冲区长度,然后调用SrvAllocateNonPagedPool申请新的缓冲区,最后将所有SMB_FEA数据以FILE_FULL_EA_INFORMATION格式拷贝到新的缓冲区。漏洞出现在用于计算新缓冲区长度的SrvOs2FeaListSizeToNt函数:

SrvOs2FeaListSizeToNt(feaList) {   outputLen = 0;   foreach (fea in feaList) {     if (IsFeaDataOutOfBound(fea, feaList)) {       // 缩小FEAfeaList.SizeOfListInBytes的范围只在合法的FEA中,因此拷贝步骤不会再检查其合法性       // feaList.SizeOfListInBytes定义为DWORD但却以WORD类型设置,因此HIDWORD永远不会被修改       (WORD) feaList.SizeOfListInBytes = Pos(fea) - Pos(feaList);       return outputLen;     }     outputLen += GetNtLengthForFea(fea);   }   return outputLen; }

根据上面伪代码的描述,如果发送一个feaList.SizeOfListInBytes为0×1000字节,但有效的FEA条目却小于0×1000字节(假设为0×4000)的请求。经过上述错误类型的长度计算,feaList.SizeOfListInBytes就变成了0×14000(因为HIDWORD没有被修改而Pos(fea) – Pos(feaList)得到的结果为0×4000)。后续拷贝SMB_FEA数据到输出区域时,就会导致缓冲区溢出。

要想成功实现利用,需要发送一个大于0×10000字节的transaction data,但FEA_LIST结构只在SMB_COM_TRANSACTION2命令中存在,TotalDataCount字段类型是USHORT(最大值为0xFFFF),因此我们需要利用Bug6(借助SMB_COM_NT_TRANS命令)来发送一个大于0×10000字节的FEA_LIST。

所需条件最少的漏洞利用途径是采用TRANS2_OPEN2子命令。处理该命令的SrvSmbOpen2函数,在权限检查之前会调用SrvOs2FeaListToNt函数转换FEA_LIST列表。因此,客户端只需访问服务端任意一个共享(IPC$是最好的选择),然后发送符合上述要求的transaction命令即可。

需要注意的是,Win8以上操作系统默认不允许匿名连接访问IPC$(IPC$可以连接上,但大部分transaction命令都无法使用)。

Bug8: SrvOs2GeaListSizeToNt中的类型分配错误

该bug和bug7类似,只是出现在与上述不同的SrvOs2GeaListSizeToNt函数。要想利用,必须提供有效的FID才行。

Bug9: SESSION_SETUP_AND_X请求格式混淆漏洞

该bug在MS17-010补丁中并没有被修复,将它放在这,是因为NSA武器库借助了该bug来实现漏洞的利用。该Bug本身只能欺骗服务端,来申请一个大的非分页内存池(小于0×20000字节),来存储客户端信息。

在NT LM 0.12中,包含两种格式的SMB_COM_SESSION_SETUP_ANDX请求。第一种格式:

SMB_Parameters {   UCHAR  WordCount;  //13   Words    {     UCHAR  AndXCommand;     UCHAR  AndXReserved;     USHORT AndXOffset;     USHORT MaxBufferSize;     USHORT MaxMpxCount;     USHORT VcNumber;     ULONG  SessionKey;     USHORT OEMPasswordLen;     USHORT UnicodePasswordLen;     ULONG  Reserved;     ULONG  Capabilities;    } } SMB_Data  {   USHORT ByteCount;   Bytes    {     UCHAR     OEMPassword[];     UCHAR     UnicodePassword[];     UCHAR      Pad[];     SMB_STRING AccountName[];     SMB_STRING PrimaryDomain[];     SMB_STRING NativeOS[];     SMB_STRING NativeLanMan[];    } }

该请求用于LM和NTLM的身份认证。

另外一种格式:

SMB_Parameters {   UCHAR  WordCount;  //12   Words    {     UCHAR  AndXCommand;     UCHAR  AndXReserved;     USHORT AndXOffset;     USHORT MaxBufferSize;     USHORT MaxMpxCount;     USHORT VcNumber;     ULONG  SessionKey;     USHORT SecurityBlobLength;     ULONG  Reserved;     ULONG  Capabilities;   } } SMB_Data {   USHORT ByteCount;   Bytes    {     UCHAR      SecurityBlob[SecurityBlobLength];     SMB_STRING NativeOS[];     SMB_STRING NativeLanMan[];   } }

该请求用于NTLMv2(NTLM SSP)的身份认证。

需要注意的是,两种格式的WordCount是不同的(第一种格式为13,第二个格式为12)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/2fdecb1a7e0d23e78a1017478a1e4d25.html