详述 ISC BIND 服务器中的信息泄露漏洞

本文揭示了ISC BIND DNS服务器中的两个安全漏洞:一个信息泄露漏洞和一个远程代码执行漏洞。漏洞影响早期版本,可通过SPNEGO请求触发,可能导致数据泄露并可能被利用执行任意代码。建议用户及时更新到已修复版本以保障系统安全。
摘要由CSDN通过智能技术生成

 聚焦源代码安全,网罗国内外最新资讯!

编译:奇安信代码卫士

去年,趋势科技 ZDI 收到了关于 ISC BIND 服务器中存在一个远程代码执行漏洞的漏洞报告。之后,这名匿名研究员再次提交了位于这个流行的 DNS 服务器中的另一个bug。和第一个 bug 一样,第二个 bug 也存在于 Simple 和 Protected GSSAPI 谈判机制 (SPNEGO) 组件中,且位置和之前提交的漏洞报告中提到的一样。厂商将第二个 bug 评估为低危漏洞,因此并非分配任何 CVE 编号或安全公告。然而,该 bug 实际上仍然值得进一步审查。

该漏洞影响早于 9.11.31 和9.16.15 之前的 BIND 版本,可遭远程触发且无需认证,可导致在堆内存上的界外 (OOB) 读取并将信息泄露给远程攻击者。攻击者还可能利用该漏洞和之前提交的漏洞在受影响 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等)上的 OOB 访问权限。

漏洞触发

用于复现该 bug 的配置和第一个 bug 一样。如下截屏是为该 bug 构造的 SPNEGO 请求。

位于 (1) 处的 length_ret 从偏移量 0xa5 as 0x91929394 受控。子字段 mechToken 是一个十进制字符串,它的长度是构造的值 0x727374,出现在偏离量 0xcd 处。

收到这个构造的请求后,在处理字段 mechToken 过程中触发 OOB。如下调用栈基于 BIND 版本 9.16.13。

#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) 处的循环在被解析的 mechTypes 过程中搜索有效的 OIDs。如找到合法的 OID,则服务器以在 (4) 处的接收信息响应。否则,服务器以位于 (5) 处的拒绝信息响应。这就使得我们能够为某些堆块获得偏移量。很有可能可以结合利用之前提交的对缓冲区溢出漏洞实施利用但需要更多的研究工作。

补丁

从版本9.16.15开始,SPNEGO 的 ISC 实现就从 BIND 9 源代码删除。BIND 9 当前总是使用系统 GSSAPI 库提供的 SPNEGO 实现。鉴于此,相关漏洞也别删除,这一功能变化也适用于版本9.1.1.31。

用户应当确保目前使用的是已修复 BIND 版本,因为很多 OS 发行版本提供的 BIND 包不同于官方发布的 ISC 发布版本。具体而言,某个发行版本常常会为 BIND 程序包选择稳定的基准版本,之后选择性地为他们认为应当包含的漏洞应用所选补丁。这样做的后果之一是,即使版本号不同(而且很可能)小于 ISC 已修复的版本号,但 BIND 中可能包含修复方案。

结论

ISC BIND 是互联网上最流行的 DNS 服务器,其影响范围很大,尤其是在该漏洞可被远程触发且无需认证的情况下更是如此。建议所有用户尽快更新 DNS 服务器。这名匿名研究员还报告了存在于 TKEY 查询处理过程中的一个远程代码执行漏洞,最近也已被修复。

推荐阅读

BIND DNS 软件受高危漏洞影响 易遭 DoS 攻击

BIND 安全漏洞导致 DNS 服务器崩溃

DNS软件BIND遭受严重的DOS漏洞影响

原文链接

https://www.zerodayinitiative.com/blog/2021/6/15/zdi-21-502-an-information-disclosure-bug-in-isc-bind-server

题图:Pixabay License

本文由奇安信编译,不代表奇安信观点。转载请注明“转自奇安信代码卫士 https://codesafe.qianxin.com”。

奇安信代码卫士 (codesafe)

国内首个专注于软件开发安全的

产品线。

    觉得不错,就点个 “在看” 或 "赞” 吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值