【安全性公示】CVE

2021-04-09 07:29 jianzhan
DNS_RESOURCE_RECORD *pResourceRecord; unsigned BYTE *pCurrentPos; unsigned int dwRemainingDataLength; unsigned int dwBytesRead; unsigned int dwAllocationSize; DNS_COUNT_NAME countName; pResourceRecord = NULL; pCurrentPos = Name_PacketNameToCountNameEx( countName, pPacket, pRecordData, pRecordData + wRecordDataLength, 0); if (pCurrentPos) (pCurrentPos  = pRecordData //  -- Check #1 - Bounds check  pCurrentPos - pRecordData  = 0xFFFFFFFF //  -- Check #2 - Same bounds check (?)  wRecordDataLength  = (unsigned int)(pCurrentPos - pRecordData)) //  -- Check #3 - Bounds check dwRemainingDataLength = wRecordDataLength - (pCurrentPos - pRecordData); dwBytesRead = countName.bNameLength + 2; // size := len(countName) + 2 + len(payload) dwAllocationSize = dwBytesRead + dwRemainingDataLength; if (dwBytesRead + dwRemainingDataLength  = dwBytesRead //  -- Check #4 - Integer Overflow check (32 bits)  dwAllocationSize  = 0xFFFF) //  -- Check #5 - Integer Overflow check (16 bits) pResourceRecord = RR_AllocateEx(dwAllocationSize, 0, 0); if (pResourceRecord) Name_CopyCountName( pResourceRecord- data,  countName); memcpy( pResourceRecord- data + pResourceRecord- data- bOffset + 2, pCurrentPos, dwRemainingDataLength); return pResourceRecord; }


如您所闻,此作用包括很多安全性查验。在其中一项(查验#5)是16位外溢查验,能防止此作用的系统漏洞变型。大家也要谈及的是,此作用比中的一般作用具备大量的安全性性查验dns.exe,这使大家想要知道是不是早已留意到并修补了该不正确,但仅在该特殊作用中。

如前上述,Microsoft在2个不一样的控制模块中完成了DNS顾客端和DNS网络服务器。尽管大家的系统漏洞的确存有于DNS网络服务器中,但大家爱看看它是不是也存有于DNS顾客端中。

image.png

图13:Sig_RecordReadfrom的反选编片断dnsapi.dll。

看上去,与不一样dns.exe!SigWireRead,dnsapi.dll!Sig_RecordRead 它的确认证了Sig_RecordRead+D0传送给其的值dnsapi.dll!Dns_AllocateRecordEx低于0xFFFF字节数,进而避免了外溢。

此系统漏洞不会有dnsapi.dll,而且2个控制模块中间的取名承诺不一样,这一客观事实使大家坚信Microsoft管理方法DNS网络服务器和DNS顾客端的2个彻底不一样的编码库,而且不一样步不正确补丁下载她们。

开发设计方案

依据Microsoft的规定,大家决策保存相关系统漏洞运用原语的信息内容,便于为客户出示充足的時间修复其DNS网络服务器。反过来,大家探讨了可用于Windows Server 2012R2的开发设计方案。可是,大家的确觉得该方案也应可用于别的版本号的Windows Server。

该dns.exe二进制文档是应用Control Flow Guard(CFG)编译程序的,这寓意着遮盖运行内存中涵数指针的传统式方式不够以运用此bug。假如此二进制文档并不是应用CFG编译程序的,那麼运用此不正确将十分简易,由于很早以前之前大家就碰到了下列奔溃:

image.png

图14:在奔溃ntdll!LdrpValidateUserCallTarget。

如您所闻,大家在失事ntdll!LdrpValidateUserCallTarget。它是承担认证做为CFG一一部分的涵数指针总体目标的涵数。大家能看到,待认证的指针(rcx)是彻底可控性的,这寓意着大家在此全过程中的某点取得成功重新写过了涵数指针。大家见到奔溃的缘故是,涵数指针被作为每一个详细地址具备“容许” /“不容许”位的全局性位图文件表的数据库索引,而大家的随意详细地址造成对该表自身中未投射网页页面的载入。

以便在摆脱CFG的同时将此系统漏洞运用到详细的远程控制编码实行中,大家必须寻找具备下列作用的原语:在哪儿里写(精准地遮盖堆栈上的回到详细地址)和信息内容泄露(泄露运行内存详细地址) ,比如堆栈)。

信息内容泄露

以便完成Infoleak原语,大家应用外溢来毁坏仍在缓存文件中的DNS資源纪录的数据库。随后,当再度从缓存文件中查寻时,大家可以泄露邻近的堆运行内存。

WinDNS的堆管理方法器

WinDNS应用该作用Mem_Alloc动态性分派运行内存。此作用管理方法自身的运行内存池,以作为合理的缓存文件。有4个运行内存池储存区,用以不一样的分派尺寸(较大为0x50、0x68、0x88、0xA0)。假如恳求的分派尺寸超过0xA0字节数,则默认设置为HeapAlloc,应用当地Windows堆。堆管理方法器为运行内存池头分派附加的0x10字节数,在其中包括数据库,包含缓存区的种类(已分派/空余),偏向下一个能用运行内存块的指针,用以调节查验的cookie等。堆管理方法器以单连接目录的方法完成了其分派目录,这寓意着将依照释放出来时的反过来次序分派块(LIFO)。

写在哪儿里

以便完成“在哪儿里写”原语,大家根据毁坏块的标头(数据库),客观事实上毁坏了空余目录来进攻WinDNS堆管理方法器。

在空余目录毁坏以后,下一次大家试着分派尺寸适合的一切內容时,运行内存分派器都是为大家分派大家挑选的运行内存地区做为可写分派–“ Malloc-Where”运用原语。

要绕开CFG,大家期待该运行内存地区坐落于堆栈上(因为信息内容泄露,大家期待了解其部位)。一旦在堆栈上具备写作用,便可以将回到详细地址遮盖到要实行的详细地址,进而合理地被劫持了实行步骤。

非常值得一提的是,默认设置状况下,DNS服务会在前3次奔溃中再次起动,进而提升了取得成功运用的机遇。

结果

Microsoft已确定此高比较严重性系统漏洞,并将其分派给CVE-2020-1350。

大家坚信,运用此系统漏洞的将会性很高,由于大家以内部发觉了运用此系统漏洞需要的全部原语。因为時间限定,大家沒有再次追求完美该系统漏洞的运用(包含将全部运用原语连接在一起),但大家的确坚信,坚定不移的进攻者将可以运用它。取得成功运用此系统漏洞将造成比较严重危害,由于您常常会发觉未打补丁下载的Windows域自然环境,特别是在是域操纵器。服务供应商(ISP)乃至将会已经将其公共性DNS网络服务器设定为WinDNS。

明显提议客户修复受危害的Windows DNS网络服务器,防止止运用此系统漏洞。

做为临时性的处理方式,在运用补丁下载以前,提议将DNS信息(根据TCP)的较大长短设定为0xFF00,那样能够清除此系统漏洞。您能够根据实行下列指令来那样做:

reg add  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters  /v  TcpReceivePacketSize  /t REG_DWORD /d 0xFF00 /f