深入分析ISC BIND服务器中的信息泄露漏洞

  • A+
所属分类:逆向工程
深入分析ISC BIND服务器中的信息泄露漏洞点击上方蓝字关注我们

近期,研究人员在ISC BIND服务器中发现了一个漏洞,该漏洞存在于Simple and Protected GSSAPI Negotiation Mechanism (SPNEGO) 组件中,影响9.11.31和9.16.15之前的BIND服务器。

攻击者可以在无需身份验证的情况下远程触发该漏洞,进而对堆内存进行越界读取,最终导致服务器上的信息泄漏。此外,攻击者还能够将其与其他漏洞结合使用,以在受影响的BIND服务器上执行任意代码。

漏洞细节


该漏洞的根本原因位于der_match_tag_and_length()函数。该函数被用于标签匹配,并从网络数据包中获取以下长度字段。基于BIND中der_get_length()的正常使用,解析的长度字段length_ret应该由调用者验证。但是, der_match_tag_and_length()却是一个例外。


static int der_match_tag_and_length(const unsigned char *p, size_t len, Der_class xclass,                          Der_type type, int tag, size_t *length_ret,                          size_t *size) {     size_t l, ret = 0;     int e;      e = der_match_tag(p, len, xclass, type, tag, &l);     if (e) {         return (e);     }     p += l;     len -= l;     ret += l;     e = der_get_length(p, len, length_ret, &l);  // (1)     if (e) {         return (e);     }     /* p += l; */     len -= l;     POST(len);     ret += l;     if (size) {         *size = ret;     }     return (0); }


标注(1)处的length_ret处于控制之下,且尚未经过验证。以下是der_match_tag_and_length()的调用者之一:


OM_uint32 gss_accept_sec_context_spnego(...) { // ...     ret = der_match_tag_and_length(buf, buf_size, ASN1_C_CONTEXT, CONS, 0,                                    &len, &taglen);     if (ret) {         return (ret);     }      ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);  // (2) // ... }


然后,使用不受信任的len解码标注(2)处的negTokenInit。decode_NegTokenInit()中的许多检查都基于len。现在,这些检查是不正确的,这可能会导致对不同子字段的越界访问,例如mechTypes、reqFlags、mechToken等。


触发机制


由于该漏洞存在于SPNEGO组件中,因此,必须在BIND中对TKEY-GSSAPI进行相应的配置。


# cat /etc/bind/named.conf.options options {     directory "/var/cache/bind";     tkey-gssapi-keytab "/etc/bind/dns.keytab"; };  # cat /etc/bind/named.conf.local zone "example.nil." IN {     type master;     file "/etc/bind/example.nil.db"; };


其中,dns.keytab文件可以在bin/tests/system/tsiggss/ns1/中找到,而example.nil.db文件则是bin/tests/system/tsiggss/setup.sh脚本生成。


现在,相应的测试环境已经准备好了,可以通过构造以下SPNEGO请求,远程触发漏洞。


深入分析ISC BIND服务器中的信息泄露漏洞

精心制作的SPNEGO请求


标注(1)处的length_ret由偏移量0xa5控制为 0x91929394。子字段mechToken是一个八位字节串。它的长度是被精心设计为0x727374,出现在偏移量0xcd处。


当收到此精心设计的请求后,会在处理mechToken字段时触发越界读取,并产生以下调用栈。


#0  __memmove_avx_unaligned_erms at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:494 #1  der_get_octet_string at spnego.c:830 #2  decode_octet_string at spnego.c:1015 #3  decode_NegTokenInit at spnego_asn1.c:607 #4  gss_accept_sec_context_spnego at spnego.c:593 #5  dst_gssapi_acceptctx at gssapictx.c:730 #6  process_gsstkey at tkey.c:551 #7  dns_tkey_processquery at tkey.c:882 #8  ns_query_start at query.c:11653 #9  ns__client_request at client.c:2169 #10 isc__nm_async_readcb at netmgr.c:1861 #11 isc__nm_readcb at netmgr.c:1836 #12 processbuffer at tcpdns.c:997 #13 process_sock_buffer at tcpdns.c:1639 #14 read_cb at tcpdns.c:1060


漏洞利用


以下是可能在受影响的服务器上造成信息泄漏的一种方法。


OM_uint32 gss_accept_sec_context_spnego(...) { // ...     ret = decode_NegTokenInit(buf + taglen, len, &init_token, &ni_len);     if (ret) {         *minor_status = EINVAL; /* XXX */         return (GSS_S_DEFECTIVE_TOKEN);     }      for (i = 0; !found && i < init_token.mechTypes.len; ++i) { // (3)         unsigned char mechbuf[17];         size_t mech_len;          ret = der_put_oid(mechbuf + sizeof(mechbuf) - 1,                           sizeof(mechbuf), &init_token.mechTypes.val[i],                           &mech_len);         if (ret) {             free_NegTokenInit(&init_token);             return (GSS_S_DEFECTIVE_TOKEN);         }         if (mech_len == GSS_KRB5_MECH->length &&                 isc_safe_memequal(GSS_KRB5_MECH->elements,                                   mechbuf + sizeof(mechbuf) - mech_len,                                   mech_len))         {             found = 1;             break;         }         if (mech_len == GSS_MSKRB5_MECH->length &&                 isc_safe_memequal(GSS_MSKRB5_MECH->elements,                                   mechbuf + sizeof(mechbuf) - mech_len,                                   mech_len))         {             found = 1;             if (i == 0) {                 pref = GSS_MSKRB5_MECH;             }             break;         }     }      if (!found) {         free_NegTokenInit(&init_token);         return (send_reject(minor_status, output_token)); // (5)     } // ... ret = send_accept(&minor_status2, output_token, ot, pref);  // (4) // ... }


在decode_NegTokenInit()解析了negTokenInit及其子字段后,标注(3)处的循环会在解析的mechType中搜索有效的OID。如果找到有效的OID,服务器将在标注(4)处响应接收消息。否则,服务器在标注(5)处响应拒绝接收。这使我们能够获取某些堆块的偏移量。


总结


ISC BIND是互联网上最流行的DNS服务器,所以该漏洞的影响范围相当大,特别是该漏洞可以在远程且无需身份验证的情况下触发。因此建议受影响的用户尽快更新相应的DNS服务器。


深入分析ISC BIND服务器中的信息泄露漏洞

END



深入分析ISC BIND服务器中的信息泄露漏洞


好文!必须在看

本文始发于微信公众号(SecTr安全团队):深入分析ISC BIND服务器中的信息泄露漏洞

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: