Linux内核AF_PACKET原生套接字缝隙(CVE-2020-14386)分析

颁布功夫 2020-09-22

缝隙布景


近日, ,,,,,,,Openwall社区上公开了一个Linux内核AF_PACKET原生套接字内存粉碎缝隙。。 。。。。凭据细节描述, ,,,,,,,该缝隙呈此刻net/packet/af_packet.c中, ,,,,,,,由整数溢出导致越界写, ,,,,,,,能够通过它进行权限提升。。 。。。。该缝隙风险评级为高, ,,,,,,,编号为CVE-2020-14386。。 。。。。


受影响产品缓和解措施


1、受影响产品


该缝隙影响Linux刊行版高于4.6的内核版本, ,,,,,,,蕴含:

  • Ubuntu Bionic (18.04) and newer

  • Debian 9

  • Debian 10

  • CentOS 8/RHEL 8

2、缓解措施


(1)建补系统

上游内核补丁如下:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=acf69c946233259ab4d64f8869d4037a198c7f06


(2)关关CAP_NET_RAW职能

针对RHEL8, ,,,,,,,具体关关步骤如下:

# echo"user.max_user_namespaces=0" > /etc/sysctl.d/userns.conf

# sysctl -p/etc/sysctl.d/userns.conf


(3)针对一些受影响的容器产品, ,,,,,,,同样采取关关CAP_NET_RAW职能进行缓解

Kubernetes Pod安全战术:配置Pod安全战术以删除运行容器中的CAP_NET_RAW职能, ,,,,,,,参考链接:https://cloud.google.com/kubernetes-engine/docs/security-bulletins。。 。。。。


有关概想


1、AF_PACKET套接字


网络和谈栈中, ,,,,,,,原始套接字是一个特殊的套接字类型, ,,,,,,,从实现上能够分为两类, ,,,,,,,一类为链路层原始套接字;;;;;;;另一类为网络层原始套接字。。 。。。。链路层原始套接字可直接用于接管和发送链路层的MAC�。。 。。。。� ,,,,,,,在发送时必要挪用者自行机关和封装MAC首部。。 。。。。链路层原始套接字挪用socket()函数创建。。 。。。。第一个参数指定地址簇类型为AF_PACKET, ,,,,,,,第二个参数套接字类型为SOCK_RAW或SOCK_DGRAM, ,,,,,,,当类型指定为SOCK_RAW时, ,,,,,,,套接字接管和发送的数据都是从MAC首部起头的。。 。。。。在发送时必要由挪用者从MAC首部起头机关和封装报文数据。。 。。。。


2、PACKET_MMAP


仅依附AF_PACKET过滤数据包是极度低效的, ,,,,,,,内核又提供了PACKET_MMAP支持。。 。。。。PACKET_MMAP在内核空间中分配一块环形内核缓冲区, ,,,,,,,用户空间通过mmap将该内核缓冲区映射出来。。 。。。。收到的数据包拷贝到环形内核缓冲区中, ,,,,,,,用户层能够直接操作数据, ,,,,,,,通过内核空间和用户空间共享的缓冲区起到削减数据拷贝的作用, ,,,,,,,提高处置效能。。 。。。。


PACKET_MMAP实现过程


通过setsockopt()函数设置环形缓冲区, ,,,,,,,option参数设置为PACKET_RX_RING或PACKET_TX_RING。。 。。。。为了方便内核与用户层治理和交互环形缓冲区中的数据�。。 。。。。� ,,,,,,,内核界说了TPACKET_HEADER结构体, ,,,,,,,该结构体存储着一些元信息如套接字地址信息、功夫戳以及环形缓冲区治理信息等。。 。。。。若是通过setsockopt()函数设置了PACKET_VNET_HDR选项, ,,,,,,,还需增长一个virtio_net_hdr结构体。。 。。。。一个数据帧蕴含两个部门, ,,,,,,,第一部门为TPACKET_HEADER, ,,,,,,,第二部门为Data, ,,,,,,,并且要保障页面对齐, ,,,,,,,如下图所示:

目前TPACKET_HEADER存在三个版本, ,,,,,,,每个版本长度略有分歧。。 。。。。对于v1和v2, ,,,,,,,收发环形缓冲区用tpacket_req结构体治理, ,,,,,,,该结构体蕴含四个数据域:别离为内存块的大幼和数量、每个数据帧的大幼和数据帧总数。。 。。。。如下图所示:



捕获的frame被划分为多个block, ,,,,,,,每个block是一块物理上陆续的内存区域, ,,,,,,,有tp_block_size/tp_frame_size个frame, ,,,,,,,block的总数是tp_block_nr。。 。。。。例如, ,,,,,,,tp_block_size = 4096, ,,,,,,,tp_frame_size = 2048, ,,,,,,,tp_block_nr = 4, ,,,,,,,tp_frame_nr = 8。。 。。。。得到的缓冲区结构如下图所示:



每个frame必须放在一个block中, ,,,,,,,每个block保留整数个frame, ,,,,,,,也就是说一个frame不能逾越两个block。。 。。。。在用户层映射环形缓冲区能够直接使用mmap()函数。。 。。。。固然环形缓冲区在内核中是由多个block组成的, ,,,,,,,但是映射后它们在用户空间中是陆续的。。 。。。。


缝隙分析


该缝隙具体呈此刻tpacket_rcv()函数中, ,,,,,,,该函数是基于PACKET_MMAP的数据包接管函数。。 。。。。具体职能实现如下代码所示:



行2226到行2228, ,,,,,,,若是sk_type为SOCK_DGRAM, ,,,,,,,暗示不必要自行机关MAC首部, ,,,,,,,由内核填充, ,,,,,,,则macoff蹬宗netoff, ,,,,,,,大幼为TPACKET_ALIGN(tp_hdr_len)+ 16 + tp_reserve。。 。。。。若是sk_type为SOCK_RAW, ,,,,,,,则进入行2230, ,,,,,,,暗示必要自行机关MAC首部。。 。。。。行2231到行2233, ,,,,,,,首先推算netoff, ,,,,,,,大幼为TPACKET_ALIGN(tp_hdrlen +(maclen < 16 ?16 : maclen)) + tp_reserve。。 。。。。行2234到行2237, ,,,,,,,若是设置了PACKET_VNET_HDR选项, ,,,,,,,还需加上一个virtio_net_hdr结构体的大�。。 。。。。� ,,,,,,,而后设置do_vnet为真。。 。。。。行2238, ,,,,,,,推算macoff。。 。。。。


由于macoff、netoff以及maclen被界说为unsigned short类型, ,,,,,,,最大值为0xffff。。 。。。。而tp_reserve被界说为unsigned int类型, ,,,,,,,最大值为0xffffffff, ,,,,,,,并且大幼能够通过setsockopt()函数进行设置, ,,,,,,,如下代码所示:



因而, ,,,,,,,在推算netoff时, ,,,,,,,能够通过节造tp_reserve造成整数溢出, ,,,,,,,进而推算出谬误的macoff。。 。。。。当执行到如下代码时:



行2287, ,,,,,,,挪用virtio_net_hdr_from_skb()函数从sk_buff中拷贝数据, ,,,,,,,该函数第二个参数为h.raw + macoff – sizeof(struct virtio_net_hdr), ,,,,,,,h.raw为tpacket_rcv_uhdr类型的指针, ,,,,,,,指向环形缓冲区的frame, ,,,,,,,由于macoff是可控的, ,,,,,,,能够让maoff幼于sizeof(struct virtio_net_hdr), ,,,,,,,导致向前越界写, ,,,,,,,最多可写入sizeof(struct virtio_net_hdr)个字节。。 。。。。凭据提供的PoC, ,,,,,,,调试代码如下图所示:



rdx中存放着TPACKET_ALIGN(tp_hdrlen+(maclen < 16 ? 16 : maclen)), ,,,,,,,大幼为0x50。。 。。。。rbp+0x4e4处存放着po->tp_reserve, ,,,,,,,大幼为0x0000ffb4。。 。。。。相加后, ,,,,,,,整数上溢后, ,,,,,,,rdx为0x0004。。 。。。。当执行到越界接见时, ,,,,,,,具体如下:



R9存放着h.raw指针, ,,,,,,,rdx存放着macoff, ,,,,,,,virtio_net_hdr结构体大幼为0xa。。 。。。。如下图所示:



产生内存接见谬误, ,,,,,,,造成系统崩溃。。 。。。。


参考链接:


[1] https://blog.csdn.net/sinat_20184565/article/details/82788387

[2] https://www.openwall.com/lists/oss-security/2020/09/03/3

[3] https://elixir.bootlin.com/linux/v5.6/source/Documentation/networking/packet_mmap.txt

[4] https://sysdig.com/blog/cve-2020-14386-falco/

[5] https://bugzilla.redhat.com/show_bug.cgi?id=1875699#c9