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版本,并下载对应版本安全补丁进行更新:

            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小时持续的安全运营服务。在漏洞爆发之初,对存在漏洞的用户,检查并更新了客户防护设备的策略,确保客户防护设备可以防御此漏洞风险。