CVE-2017-14491 DNSmasq 堆溢出分析

汽车安全 3年前 (2021) admin
944 0 0

前言



在研究IVI和TBOX安全的时候经常能遇到DNSmasq服务,而这些DNS的版本往往较低。本篇是我分析CVE-2017-14491的心路历程,作为一个只对DNS有初步了解的情况下,如何一步步通过信息来找到漏洞原理,以此篇来提高自己漏洞分析能力及帮助自己以后少踩坑,分析DNSmasq的主要原因是因为我们目前挖物联网的漏洞主要通过httpd等web端进行挖掘,这些终端还有没有一些其他的渗透方式,为此找到了DNSmasq。

漏洞信息



POC:https://github.com/google/security-research-pocs/blob/master/vulnerabilities/dnsmasq/CVE-2017-14491-instructions.txt
源码分析:DNSmasq 2.74
分析参考:https://zhuanlan.zhihu.com/p/30472217
危害:RCE

组件概述



DNSmasq是一个小巧且方便地用于配置DNS和DHCP的工具,适用于小型网络,它提供了DNS功能和可选择的DHCP功能。它服务那些只在本地适用的域名,这些域名是不会在全球的DNS服务器中出现的。DHCP服务器和DNS服务器结合,并且允许DHCP分配的地址能在DNS中正常解析,而这些DHCP分配的地址和相关命令可以配置到每台主机中,也可以配置到一台核心设备中(比如路由器),DNSmasq支持静态和动态两种DHCP配置方式,许多路由器都会使用到DNSmasq。

复现过程



首先编译DNSmasq,然后根据测试步骤进行复现
gdb dnsmasqset args -p 53535 --no-daemon --log-queries -S 127.0.0.2 --no-hosts --no-resolv

CVE-2017-14491 DNSmasq 堆溢出分析
python test.py 127.0.0.2 53 #监听53端口dig @localhost -p 53535 -x 8.8.8.125 +retry=0 > /dev/null #发出dns请求dig @localhost -p 53535 -x 8.8.8.125 +retry=0 > /dev/null #发出dns请求

遇到崩溃断在这里
CVE-2017-14491 DNSmasq 堆溢出分析
从这里看到是iface->found = 0出现了错误,从左边变量可以看见iface不是一个地址,而是0x5a5a5a5a5a5a5a5a(”ZZZ……”)
说明payload将iface->next溢出了,再来看看daemon->interfaces里面的内容,如下图:
CVE-2017-14491 DNSmasq 堆溢出分析
很明显里面保存了网卡的信息,next里面的地址是0x5555558df830,那就跟着查看next,直到next是0x5a5a为止
现在可以看到该地址里面保存的数据,从数据可以看出该结构体给我们的脚本溢出了,对应的地址是0x5555558df730,查看后发现的确给溢出了,很明显这个地址是堆
CVE-2017-14491 DNSmasq 堆溢出分析
查看栈回溯,主要是通过check_dns_listeners进行调用的
CVE-2017-14491 DNSmasq 堆溢出分析
Check_dns_listeners函数如下:
CVE-2017-14491 DNSmasq 堆溢出分析
这里主要是reply_query和receive_query值得我们注意,因为这里是处理我们dns请求的函数,重点还是要跟到reply_query,查看payload主要处理逻辑,进入reply_query看到recvfrom,这里应该就是接收payload的地方,将接收到的数据保存到daemon->packet
CVE-2017-14491 DNSmasq 堆溢出分析
查看dnsmasq->packet,保存数据地址是0x5555558de380,数据大小是0x1000,也就是说0x5555558de380-0x0x5555558df380都是我们数据存储的地址。
CVE-2017-14491 DNSmasq 堆溢出分析
稍等,0x5555558df380和0x5555558df730也就相差0x3b0,也就是说我们溢出的地方很有可能就在0x5555558df380,所以在崩溃的地方再次查看0x5555558df380的数据
CVE-2017-14491 DNSmasq 堆溢出分析
看来我想的没错,packet已经溢出了,那么现在问题是需要定位溢出函数在哪里了,整个数据处理逻辑那么多,我们一步一步去跟和盲目下断点显示是很消耗耐心的一件事情,说不定你跟了十几回你就麻木了(诶,我跟到哪里了,我在干嘛)这时候我就想到了硬件断点,既然它溢出了,那么它肯定在0x5555558df380读写数据了,我们就将硬件断点设在0x5555558df380就好了
watch 0x5555558df380
重复测试步骤:
CVE-2017-14491 DNSmasq 堆溢出分析
可以看见在add_resource_record这里断下了,而p所指的内容是0x5555558df382,也就是该函数往堆外的地方写数据了,接着用bt看函数调用
CVE-2017-14491 DNSmasq 堆溢出分析
可以看到看到函数调用链为receive_query->answer_request->add_resource_record,且调用位置是rfc1035.c:1851
查看rfc1035.c:1851
CVE-2017-14491 DNSmasq 堆溢出分析
从名字和函数参数可能猜测是将cache_get_name(crecp)的值放入到ansp中
用bt full查看
CVE-2017-14491 DNSmasq 堆溢出分析
在answer_request下ansp的值0x5555558df380,也就是堆溢出的地方,那么断在这里的时候我就想:为什么需要两次才能触发堆溢出,那么什么情况下才会用这个函数逻辑
而我经过试验发现rfc1035.c:1851add_resource_record第一次是没有调用,而第二次才调用,cache_get_name是什么。再回头看看DNS处理过程,有这么一句话:
DNS拿到请求后,先检查一下自己的缓存中有没有这个地址,有的话就直接
返回。这个时候拿到的ip地址,会被标记为非权威服务器的应答
那么这个cache就是我们第一次查询时保存的内容也就是我们的payload,而第二次是返回的cache的内容,但是问题又随之而来了,明明我们第一次返回的数据是没有造成堆溢出的,而第二次却溢出了,这是为什么?
这时候我们得看看我们的数据包了

CVE-2017-14491 DNSmasq 堆溢出分析
这是第一次发送数据的数据包,可能第一次看没啥感到奇怪的,可是再仔细看看,你会发现DCBBEEEE.DDDD.CCCCCCC.AAAA.BBBB.com在wireshark解析的窗口出现了好几次,而我们的数据包才出现了一次,之后一些奇怪的编码,那么就是这里就关注到rfc1035的规范了,它会将一些重复Answers进行压缩以减少数据包的大小,而再回头看看add_resource_record进行循环处理的时候的效果,我们可以进行对比查看数据包有何不同
这是第一次处理之后的
CVE-2017-14491 DNSmasq 堆溢出分析
这是第二次处理之后的
CVE-2017-14491 DNSmasq 堆溢出分析
这是第三次处理之后的
CVE-2017-14491 DNSmasq 堆溢出分析
 我们可以发现每一次处理之后都将Answer中name解析开来了,导致整个数据包一下子溢出了,这就是溢出的原因的所在,导致我们可以控制到其他位置

总结



这篇文章主要是分析DNSmasq漏洞点在哪,为什么会溢出,我把分析的主要点都放在里面,我觉得还是比较新手向的,有兴趣的可以详细阅读和查看。但由于篇幅实在过大,我没有将其他分析点放在这里,有问题可以和我联系。
这次漏洞分析总体是参考Larrxi给出的CVE复现过程,但有些地方和它那部分有所不同,比如漏洞崩溃点,复现的思路等等,这次复现给了我很大的提高,踩了很多坑,也逐渐找到了很多漏洞复现的思路,这个漏洞最终可以实现远程命令执行,但由于最近实在太忙了,没有继续整理,后续有时间我会尝试实现远程命令执行,并接下来会分析其他相关漏洞,敬请期待。

CVE-2017-14491 DNSmasq 堆溢出分析


CVE-2017-14491 DNSmasq 堆溢出分析
CVE-2017-14491 DNSmasq 堆溢出分析
CVE-2017-14491 DNSmasq 堆溢出分析

扫描二维码获取

更多干货





天问实验室






原文始发于微信公众号(天问实验室):CVE-2017-14491 DNSmasq 堆溢出分析

版权声明:admin 发表于 2021年9月23日 上午9:40。
转载请注明:CVE-2017-14491 DNSmasq 堆溢出分析 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...