近日,亚信安(ān)全应急响应中(zhōng)心监测到Nginx发布安(ān)全公(gōng)告,修复了Nginx解析器中(zhōng)的一个DNS解析程序漏洞(CVE-2021-23017),由于函数ngx_resolver_copy()在处理(lǐ)DNS响应时出现了一个off-by-one错误(也称:单字节溢出),这种错误通常在当迭代太多(duō)或太少时出现,该漏洞只需网络攻击者伪造指定DNS服務(wù)器的UDP数据包就可(kě)以导致在堆分(fēn)配的缓冲區(qū)中(zhōng)一个字节被覆盖。 所有(yǒu)配置解析器语法的实例都可(kě)以通过DNS响应(响应来自Nginx的DNS请求)来触发该漏洞。 特制数据包允许使用(yòng)一个点字符(.’, 0x2E)覆盖下一个堆块元数据的最低有(yǒu)效字节,攻击者利用(yòng)该漏洞,可(kě)以实现DDOS拒绝服務(wù),甚至实现遠(yuǎn)程代码执行。

由于Nginx中(zhōng)缺乏DNS欺骗缓解措施,并且在检查DNS事務(wù)ID之前调用(yòng)了易受攻击的功能(néng),因此遠(yuǎn)程攻击者可(kě)能(néng)能(néng)够通向中(zhōng)毒服務(wù)器注入受毒的DNS响应来利用(yòng)此漏洞。
Nginx是高性能(néng)的异步框架的网页(yè)服務(wù)器,也可(kě)以用(yòng)作(zuò)反向代理(lǐ)、负载平衡器和HTTP缓存,其在全球web服務(wù)器中(zhōng)的占有(yǒu)率常年位居最高。
目前漏洞细节已被披露,亚信安(ān)全应急响应中(zhōng)心建议受影响的用(yòng)户尽快升级,避免导致黑客攻击利用(yòng)。
CVE-2021-23017
高危,CVSS评分(fēn)8.1
NGINX 0.6.18 – 1.20.0
NGINX Open Source 1.20.1 (stable)
NGINX Open Source 1.21.0 (mainline)
NGINX Plus R23 P1
NGINX Plus R24 P1
当Nginx配置中(zhōng)设置resolver时(如:resolver 127.0.0.1:8088),Nginx DNS解析器(core/ngx_resolver.c)可(kě)以通过DNS解析多(duō)个模块的主机名(míng)。
Nginx中(zhōng)通过ngx_resolver_copy()调用(yòng)来验证和解压缩DNS响应中(zhōng)的每个DNS域名(míng),接收网络数据包作(zuò)為(wèi)输入和指向正在处理(lǐ)的名(míng)称的指针,并在成功后返回指向包含未压缩名(míng)称的新(xīn)分(fēn)配缓冲區(qū)的指针。调用(yòng)整體(tǐ)上分(fēn)两步完成:
1)通过计算未压缩的域名(míng)大小(xiǎo)的長(cháng)度len并验证输入包的合法性,丢弃包含大于128个指针或包含超出输入缓冲區(qū)边界的域名(míng)。
2)分(fēn)配输出缓冲區(qū),并将未压缩的域名(míng)复制到其中(zhōng)。
第1部分(fēn)中(zhōng)的大小(xiǎo)计算与第2部分(fēn)中(zhōng)的未压缩的域名(míng)之间的不匹配,导致一个len的一个off-by-one错误,从而允许以一个字节為(wèi)单位写一个点字符超出name->data的边界。
当压缩名(míng)称的最后一部分(fēn)包含一个指向NUL字节的指针时,就会发生计算错误。尽管计算步骤仅考虑标签之间的点,但每次处理(lǐ)标签并且接着的字符為(wèi)非NUL时,解压缩步骤都会写入一个点字符。当标签后跟指向NUL字节的指针时,解压缩过程如下:

如果计算的大小(xiǎo)恰好与堆块大小(xiǎo)对齐,则超出范围的点字符将覆盖下一个堆块長(cháng)度的元数据中(zhōng)的最低有(yǒu)效字节。这可(kě)能(néng)会直接导致下一个堆块的大小(xiǎo)写入,但还会覆盖3个标志(zhì),从而导致PREV_INUSE被清除并且IS_MMAPPED被设置。

DNS响应可(kě)以通过多(duō)种方式触发漏洞。
首先,Nginx必须发送了DNS请求,并且必须等待响应。然后,可(kě)以在DNS响应的多(duō)个部分(fēn)进行投毒:
DNS Questions QNAME
DNS Answers NAME
DNS Answers RDATA for CNAME and SRV responses
通过使用(yòng)多(duō)个中(zhōng)毒的QNAME,NAME或RDATA值制作(zuò)响应,可(kě)以在处理(lǐ)响应时多(duō)次击中(zhōng)易受攻击的函数,从而有(yǒu)效地执行多(duō)次脱机写入。
此外,当攻击者交付中(zhōng)毒的CNAME时,它将递归解析,在ngx_resolve_name_locked()调用(yòng)ngx_strlow()(ngx_resolver.c:594)期间触发额外的OOB写入,并在ngx_resolver_dup()(ngx_resolver.c:790)和ngx_crc32_short()(ngx_resolver.c:596)期间触发额外的OOB读取。
用(yòng)于“example.net”请求的DNS响应示例负载,其中(zhōng)包含被污染的CNAME:

该POC中(zhōng)payload填充了足够的字节来覆盖next_chunk.mchunk_size带点的最低有(yǒu)效字节:

24字节的标签导致分(fēn)配了24字节的缓冲區(qū),该缓冲區(qū)填充有(yǒu)24字节+一个超出范围的点字符。
1)官方升级
目前官方已在最新(xīn)版本中(zhōng)修复了该漏洞,请受影响的用(yòng)户尽快升级版本进行防护,官方下载链接:http://nginx.org/en/download.html
2)其他(tā)防护措施
若相关用(yòng)户暂时无法升级nginx至新(xīn)版本,也可(kě)安(ān)装(zhuāng)补丁进行修复:
http://nginx.org/download/patch.2021.resolver.txt