内容简介:作者:maldiohead@ 360 NirvanTeamCVE-2018-4407是XNU内核的BSD网络模块的一个内核堆溢出漏洞,可以造成内核崩溃
作者:maldiohead@ 360 NirvanTeam
漏洞简述:
CVE-2018-4407是XNU内核的BSD网络模块的一个内核堆溢出漏洞,可以造成内核崩溃
受影响的系统有:
- macOS 10.13.6及以下
- iOS11 及以下
漏洞分析
twitter上的poc:
send(IP(dst=“Target IP“,options=[IPOption(“A”*8)])/TCP(dport=2323,options=[(19, “1"*18),(19, “2”*18)]))
本次分析以这个poc为说明。
通过wireshark抓包,根据ip头数据结构,发现ip头数据是没问题的,然后根据options的结构体发现ip Options的数据格式不合法。Ip options主要是用来测试,调试等目的用的。
IP options 的结构说明
公开的poc网络请求的数据包填充了8字节的options数据。下图是抓包得来的数据。
Poc中的ip options的数据
可以发现ip options的数据完全不合法,
通过分析XNU内核代码,我们找到了处理ip options的相关处理函数ip_dooptions
文件位置(darwin-xnu\bsd\netinet\ip_input.c),在函数ip_dooptions中会循环解析options中的数据,如果中间某次出错就会直接goto到bad流程中。结合poc我们会看到这里optlen的值是0x41, cnt是0x8所以这里会从3256行直接跳到bad流程中,而在bad流程中则会调用icmp_error函数(icmp_error的目的是构造一个类型错误的数据包,来响应来自远程的错误的ip数据包)。
解析ip option数据
在函数icmp_error中在下面这句导致了溢出:
m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip);
这是一个内存拷贝函数,会拷贝大小为icmplen长度的对象n中数据到icp->icmp_ip这个缓冲区中。所以对于这个内存拷贝函数,需要确定icmplen和目的缓冲区大小,就明确了为什么会产生这个漏洞。首先我们看一下icmplen的长度,通过分析会发现icmplen由下面这句代码确定:
icmplen = min(oiphlen + icmpelen, min(nlen, oip->iplen));
这里oiphlen是ip头与ipoptions之和即28字节,nlen是原始packet的长度,这里必然是大于oip->ip_len的,而oip->ip_len的长度是88字节,由于这个包是TCP包。所以icmpelen由281行代码确定(如下图)。
icmplen相关代码
通过分析数据包及代码,可以知道tcphlen长度为60字节 ,icmp_datalen等于8,oip->ip_len等于88,所以icmpelen的值是60。分析完了所有与icmplen值相关的数据,最终确定icmplen这里的值是88。
所以接下来就是分析icp->icmp_ip缓冲区的大小,在294或296初始化一个mbuf,而icp就是属于mbuf对象的m_data成员。所以这里首先要判断m到底是由哪一行决定的。
分配m对象
根据前面的判断,我们可以知道sizeof(struct ip) + ICMP_MINLEN + icmplen)
大小是88,所以对于到底值调用294行的函数初始化mbuf还是296行,主要是看MHLEN的大小,查看了MHLEN的宏定义,由于m_hdr ,pkthdr的结构有点复杂
MHLEN定义
所以想直接知道MHLEN的准确值比较麻烦。于是我进行了内核调试,获取了这个值。
MHLEN得值
很明显MHLEN的值是0x57也就是87,所以mbuf的初始化就在296行这里进行的。
也就是调用m_getcl函数,对于这个函数,可以看到在3732行进行了mbuf对象内存的申请,mcache_alloc这个函数也是相当复杂的,这里对于分析这个漏洞没多大关系,就不再关注具体是怎么分配对象了。。
初始化mbuf
重点是MBUF_INIT这个宏代码(如下图),这里首先在888行判断pkthdr的值是否为0,结合上图的3726行代码,就会发现mbuf->m_data指针指向的是m_pktdat.
MBUF_INIT代码
对于m_ pktdat 定义:
#define m_pktdat M_dat.MH.MH_dat.MH_databuf
和mbuf的定义:
mbuf的定义:
所以我们知道了m->m_data的大小是87字节。在这里icp指向的地址是m->m_data
对于代码:
m_copydata(n, 0, icmplen, (caddr_t)&icp->icmp_ip);
结合前面的计算,我们知道了icp->icmp_ip就等于 &m->m_data[7]
,而此刻icmplen的值是88,icp->icmp_ip的大小之后87-8=79 ,所以拷贝过程中就造成了堆内存溢出。
对于Twitter上的poc来说,只要构造出来的数据包大于79字节即可造成溢出,
同时对于ip options并不需要填充8字节,只要能够造成在调用到bad流程就可以,经过我的测试,这里ip options最小只需要1字节即可。总体的数据包大于79,就可以造成溢出。从而导致内核崩溃。
这个漏洞能利用吗?
通过分析,可以发现mbuf最大长度是2000字节,所以我们最大可以构造这么大的长度的数据包,来存放我们的shellcode,但是要想稳定利用,还得堆喷和内核信息泄露的漏洞结合起来,来达到远程代码执行的目的。
所以单个的这个漏洞很难实现稳定的远程代码执行的目的。
引用:
- CVE-2018-4407 poc:
https://twitter.com/ihackbanme/status/1057811965945376768
- Structure of the IP Datagram:
http://www.rhyshaden.com/ipdgram.htm
- Kernel RCE caused by buffer overflow in Apple’s ICMP packet-handling code
https://lgtm.com/blog/apple_xnu_icmp_error_CVE-2018-4407
- Memory Buffers, Socket Manipulation, and Socket Input/Output
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 漏洞预警 | 潜伏长达11年之久的Linux内核漏洞
- 针对多个DirectX内核漏洞的分析
- macOS 被曝内核存在高危漏洞
- “水滴”来袭:详解Binder内核通杀漏洞
- Apple CVE-2018-4407 内核漏洞利用与修复
- Linux内核发现两个尚未修复的DoS漏洞
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Think Python
Allen B. Downey / O'Reilly Media / 2012-8-23 / GBP 29.99
Think Python is an introduction to Python programming for students with no programming experience. It starts with the most basic concepts of programming, and is carefully designed to define all terms ......一起来看看 《Think Python》 这本书的介绍吧!