FavoriteLoading
0

Linux内核漏洞导致权限升级 CVE-2017-1000112

Linux内核漏洞导致权限升级 CVE-2017-1000112

Linux内核中的UDP分段卸载(UFO)代码中的内存损坏错误可能导致本地特权升级。在这篇文章中,我们将研究这个漏洞及其附带的漏洞。虽然这个bug会影响IPv4和IPv6代码路径,但是我们仅分析了在Ubuntu xenial的弱内核版本4.8.0上运行的IPv4代码。漏洞已在Commit 85f1bd9中修复

Andrey Konovalov最近公布了在Linux网络子系统中发现的漏洞的本地特权升级漏洞,同时使用工具syzcaller“fuzzing”。在一个oss-sec邮件线程中, Konovalov写道:“使用MSG_MORE __ip_append_data()构建UFO数据包时,会调用ip_ufo_append_data()来附加。然而在两个send()调用之间,追加路径可以从UFO切换到非UFO,从而导致内存损坏。“

网卡卸载和UFO

网络接口卡(NIC)卸载允许协议stack传输大于以太网最大传输单元(MTU)的数据包,默认为1500字节。当NIC卸载启用时,内核将将多个数据包组合到一个大数据包中,并将其传递给硬件,从而处理IP分段并将其分段到MTU大小的数据包中。这种卸载通常与高速网络接口一起使用,以增加吞吐量,因为UFO可以发送大的UDP数据包。

Linux内核可以利用各种NIC 的分段卸载能力

触发POC

以下是一个简单的概念证明,将触发内核的恐慌:

 

 

要在内核中构建UFO数据包,我们可以采取以下两个步骤之一:

  • 使用UDP_CORK套接字选项,该选项告诉内核将此套接字上的所有数据累加到禁用该选项时要发送的单个图表中。
  • 在调用send / sendto / sendmsg时,使用MSG_MORE标志,该标志告诉内核在执行不指定该标志的调用时,将该套接字上的所有数据累加到单个图表中。此方法触发此漏洞。

在内核中,udp_sendmsg函数负责构建UDP数据包并将其发送到下一层。以下代码显示了在调用send / sendto / sendmsg时,用户程序使用UDP_CORK套接字选项或MSG_MORE标志启用的UDP软木功能的剥离实现。当启用UDP软件启动时,会调用ip_append_data函数将多个数据包累加到单个大数据包中。

 

 

函数ip_append_data是__ip_append_data周围的包装器,它通过分配一个新的套接字缓冲区来存储传递给它的数据,或通过在套接字被锁定时将数据附加到现有数据来负责套接字缓冲区管理。这个功能执行的一个重要任务是处理UFO。套接字缓冲区在套接字的发送队列中进行管理。在软件套接字的情况下,队列中有一个条目可以附加附加数据。数据位于发送队列上,直到udp_sendmsg确定是调用udp_push_pending_frames的时候,udp_push_pending_frames最终确定套接字缓冲区并调用udp_send_skb。

Linux内核将数据包存储在结构sk_buff(套接字缓冲区)中,由所有网络层用于存储其头,关于用户数据(有效内容)和其他内部信息的信息。

 

 

内核中的套接字缓冲区。

在上图中,sk_buff的头,数据,尾部和终端成员指向存储协议头和用户有效负载的存储器区域的边界。头和终点指向分配给缓冲区的空间的开始和结束。数据和尾部指向整个空间内用户数据的开始和结束。在结束边界之后,结构skb_shared_info保存IP分片的重要信息。

内存腐败

当使用MSG_MORE标志进行“发送”的第一次调用时,如早先的POC所示,__ip_append_data将通过调用ip_ufo_append_data来创建一个新的套接字缓冲区,如下面的代码所示:

 

 

当此调用完成并且新的套接字缓冲区被创建时,用户数据被复制到片段,并且共享信息结构被更新为片段信息,如下图所示。新创建的sk_buff然后被放置在队列中。

 

 

在下一步中,PoC通过设置选项SO_NO_CHECK来更新套接字以不计算UDP上的校验和; 这将覆盖套接字结构的sk-> sk_no_check_tx成员。在__ip_append_data里面,这个变量被检查为调用ip_ufo_append_data之前的一个条件。

在POC第二次调用“发送”期间,在__ip_append_data内部采用非UFO路径,进入片段长度计算循环。在循环的第一次迭代期间,拷贝的值变为负值,从而触发新的套接字缓冲区分配。加上Fraggap计算超过MTU并触发碎片。这导致使用skb_copy_and_csum_bits函数将由第一个发送呼叫创建的sk_buff的用户有效载荷复制到新分配的sk_buff。这将从源缓冲区中将指定数量的字节复制到目标sk_buff并计算校验和。调用长度大于新创建的sk_buff边界结束限制的skb_copy_and_csum_bits会覆盖套接字缓冲区以外的数据,并破坏紧接在sk_buff之前的skb_shared_info结构。

 

 

 

损坏的skb_shared_info结构如下。地址为0xffff88003a4ca900的内存是新创建的sk_buff,结束= 1728,其中碎片被触发。

 

开发

大多数默认的Ubuntu桌面系统允许无特权用户命名空间时,无特权用户可以利用此错误。用户应该能够做两件事情:

  • 设置启用UFO(可能来自用户命名空间)的界面,或者使用该界面(如果已经存在)。(默认情况下,“lo”界面启用UFO。)
  • 禁用NETIF_F_UFO接口功能或设置SO_NO_CHECK套接字选项。

代码执行可以通过在大型缓冲区末尾创建一个假skb_shared_info结构,并将回调成员设置为shellcode,将其转移到用户模式的shellcode。第二个“发送”触发套接字缓冲区上的超出条件,使用用户模式的shellcode地址覆盖skb_shared_info-> destructor_arg,这是从内核内存释放sk_buff之前调用的。

当暴露给非特权用户时,Linux内核提供了一个很大的攻击面。所有用户应保持系统修补最新更新。

 

 

SOURCE    Linux Kernel Vulnerability Can Lead to Privilege Escalation: Analyzing CVE-2017-1000112