• 我的位置:
  • 首页
  • -
  • 漏洞预警
  • -
  • 操作系统
  • -
  • Windows DNS Server远程代码执行漏洞分析
    • CNNVD编号:未知
    • 危害等级: 高危 
    • CVE编号:CVE-2020-1350
    • 漏洞类型: 远程代码执行
    • 威胁类型:远程
    • 厂       商:未知
    • 漏洞来源:深信服
    • 发布时间:2021-01-06
    • 更新时间:2021-01-13

    漏洞简介

    Microsoft Windows Server操作系统自带了一个DNS server,Windows自Windows 2000后提供了一些DNS API给应用程序开发者,允许他们通过这些API使用一些DNS方法(例如创建DNS查询,比较记录,查找name等)。

    一种最简单的用户和DNS Server的交互过程如下图所示:


    DNS查询和响应均通过DNS消息进行传输,消息的结构如下所示:

    +---------------------+ |        Header     | +---------------------+ |   Question / Zone  |  the question / zone for the name server +---------------------+ |   Answer / Prereq  |  RRs answering the question / prereq +---------------------+ | Authority / Updates |  RRs pointing toward an authority / updates +---------------------+ |       Additional   |  RRs holding additional information +---------------------+
    此外,DNS还包含Dynamic Update消息类型,在结构上类似于query/response,但是在Dynamic Update消息中的section的名称有一定变化,如上面结构所示,Question称为Zone,Answer称为Prerequisites,Authority称为Updates。


    DNS Header部分的结构如下所示:

    Field

    Length(Bits)

    Description

    ID

    16

    匹配query和response消息的ID

    QR

    1

    指明为Query(QR=0)还是Response(QR=1)的flag标志

    OPCODE

    4

    指明query的类型,0表示为标准类型,5表示为Dynamic Update

    AA

    1

    Authoritative Answer,表明answer是否来自于authority

    TC

    1

    Truncation,指明是否因为传输限制进行truncate

    RD

    1

    Recursion Desired,指明resolver是否递归执行query

    RA

    1

    Recurision Available,指明resolver是否递归处理query

    Z

    3

    未使用

    RCODE

    4

    指明错误状态,0表示没有错误

    QDCOUNT

    16

    Question/Zone Section中的entity数量

    ANCOUNT

    16

    Answer/Prereq Section中的entity数量

    NSCOUNT

    16

    Authority/Updates Section中的entity数量

    ARCOUNT

    16

    Additional Section中的entity数量

    所有多字节数据均以大端序进行传输,上面提到的各个section都包含不定数量的Resource Records(RR),这些RR指定了DNS 资源和entity的详细信息。RR的结构如下:

    Field

    Length(bytes)

    Description

    Name

    var

    Owner Name,该domain属于的node

    Type

    2

    资源记录type码

    Class

    2

    资源记录class码

    TTL

    4

    记录缓存的秒数

    RDLENGTH

    2

    RDATA字段的长度

    RDATA

    var

    记录数据,格式取决于type和class

    对于Zone section来说,包含如上格式的RR,但是省略TTL,RDLENGTH,RDATA。


    Name字段编码了0个或多个DNS标签,标签以空字符结尾。每个标签为一个1字节固定长度的字节字符串。例如,一个域名为www.example.com,会切分成3个标签,www,example以及com,然后进行编码组合到一起\x03www\x07example\x03com\x00。或者,不使用按照长度编码为字节字符串,而是一个标签包含一个2字节的指针,前2个最重要的位设置为1,其他位存储从DNS Header部分的未压缩标签出现的位置的偏移(字节数),例如Zone包含一个Name为\x03www\x07example\x03com\x00的RR,然后其他的RR可以使用2字节的指针\xc0\xc0指向该name,0xc0是距Zone RR的Name字段出现的DNS数据包起点的偏移。


    Dynamic Update是可以远程更新DNS记录的一种功能,该功能允许经过授权的更新者区域中的权威名称server上增加和删除资源记录。通常情况下,Dynamic Update使用SIG或者TSIG对更新进行签名。

    漏洞公示

    在Windows系统中,DNS Client和DNS Server通过两个不同的模块进行实现:

    - DNS Client:dnsapi.dll,负责处理DNS 解析
    - DNS Server:dns.exe,负责响应DNS查询
    在dns.exe中,实现针对各种支持的响应类型的解析函数:


    dns!RR_DispatchFunctionForType()通过RRWireReadTable来确定对应的处理功能。RRWireReadTable中包含的支持的响应类型如下:


    对于SIG 查询的响应类型也在其中。而处理 SIG 查询的响应类型的函数为dns!SigWireRead(),其汇编代码如下:


    也就是在接收到包含SIG RRd的Dynamic Update查询后,dns!SigWireRead()函数被调用来进行RR解析,并存储到一个堆缓冲区中。在调用DNS!RR_AllocateEx()函数进行堆区分配之前,首先调用dns!Name_PacketNameToCountNameEx()函数统计Signer's Name的长度,然后按照如下公式进行计算需要分配的缓冲区的大小:
    bsize (buffer size) = Length of uncompressed Signer's Name + 0x14 + Length of Signature

    上面公式的计算过程使用的均为16位寄存器,然后在RR_AllocateEx()函数中进行扩展:


    如果最后bsize的计算结果大于0xFFFF(16位寄存器能表示的最大值),那么在传入RR_AllocateEx()函数进行内存分配操作时,就会分配一个很小的缓冲区:


    从代码中可以看到,在进行内存分配时,实际分配的内存大小为bsize + 0x4a,而且在进行copy操作时,将SIG RR的Signature字段copy到了偏移为Length of uncompressed Signer's Name+0x4c处的缓冲区中,这主要是为了确保Signature可以被copy到缓冲区的末尾位置。


    正常情况下,bsize的计算结果会比0xFFFF小,原因如下:
    - DNS通过TCP传输的packet的最大数据量为0xFFFF
    - DNS的packet一定包含一个12字节的Header
    - 对于root zone来说,一个最小的Zone RR大小为5字节
    - Signer's Name字段前的SIG RR的长度为18个字节


    因此,在正常情况下,Signer's Name和Signature长度的和一定小于0xFFFF - 12 - 5 - 18 = 0xFFDC,那么也就说明bsize的长度不会大于0xFFF0(0xFFDC + 0x14)。


    但是,仍然有可能构造一个恶意的Signer's Name来使得bsize的大小超过0xFFFF来造成溢出。因为SIG RR的前18个字节在调用memcpy()函数之前都不会被处理,从而可以任意使用这些字节来存储一个DNS name,而且,构造的DNS name的最后2个字节可以指向Zone RR的Name字段。例如,Name的前18个字节如下:
    \x0FAAAAAAAAAAAAAAA\xc0\x0c

    使用嵌套指针在SIG RR的18个字节中构造一个Name,如下所示:

    Label1 = <Label1_Length> <Label1_Name> \xc0\x0cCrafted_Name = <Label2_Length> <Label1> <Pointer1>
    Pointer1指向Label1_Length处的字节。请注意,Crafted_Name包含一个指向Label1的指针Pointer1,Label1本身包含在Crafted_Name中。由于Label1的指向\xc0\x0c后缀(即Zone RR的Name字段),因此不会导致无限递归,而是通过添加作为名称子集的后缀来延长Crafted_Name 。以一个例子来说明该种方案:
    Label1 = \x0cAAAAAAAAAAAA\xc0\x0cCrafted_Name = \x11\x0cAAAAAAAAAAAA\xc0\x0c\xc0XX
    其中,Zone假设为example.com,XX指向Label1。Crafted_Name就变成\x0CAAAAAAAAAAAA\xC0\x0C.AAAAAAAAAAAA.example.com,长度由原来的18字节变为40字节。通过嵌套指针,使得长度变为了原来的2倍。如果Signer's Name指向Crafted_Name,那么就可能实现bsize大于0xFFFF,从而触发漏洞。

    参考网站

    暂无

    受影响实体

    暂无

    补丁

    1、微软官方补丁

    微软官方目前已发布针对此漏洞的安全更新补丁,千里目实验室建议广大用户及时确认所用Windows版本,并下载对应版本安全补丁进行更新:

    https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350

    2、缓解措施

    微软官方对于无法及时安装安全更新的用户提供了临时的缓解措施:

    通过注册表编辑器,限制tcp包的长度

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters DWORD = TcpReceivePacketSize Value = 0xFF00

    注意:需要重新启动DNS服务才能生效。

    移除此临时缓解措施:

    管理员可以移除值 TcpReceivePacketSize 及其数据,使注册表项

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters 下的所有其他内容恢复原来的状态。

    3、深信服解决方案

    深信服下一代防火墙

    可轻松防御此漏洞,建议部署深信服下一代防火墙的用户更新至最新的安全防护规则,可轻松抵御此高危风险。

    深信服EDR

    深信服EDR已完成漏洞规则库更新,支持该漏洞的检测及补丁分发。EDR3.2.10及以上版本需要升级相应的SP包,更新漏洞补丁规则库版本到20200722103111及以上版本,即可检测漏洞并分发补丁进行漏洞修复。联网用户可直接在线更新,离线升级包及漏洞补丁规则库已上传至深信服社区,有需要的用户请到深信服社区下载。

    深信服云盾

    已第一时间从云端自动更新防护规则,云盾用户无需操作,即可轻松、快速防御此高危风险。

    深信服安全感知平台

    可检测利用该漏洞的攻击,实时告警,并可联动【深信服下一代防火墙等产品】实现对攻击者ip的封堵。

    深信服安全运营服务

    深信服云端安全专家提供7*24小时持续的安全运营服务。在漏洞爆发之初,对存在漏洞的用户,检查并更新了客户防护设备的策略,确保客户防护设备可以防御此漏洞风险。
    https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350