“Phoenix Talon”in Linux Kernel —潜伏长达11年之久的内核漏洞

https://p5.ssl.qhimg.com/t0131e3be4e2a9183be.png


About “Phoenix Talon”

2017年5月9日,启明星辰ADLab发现Linux内核存在远程漏洞“Phoenix Talon”(取凤凰爪四趾之意),涉及CVE-2017-8890、CVE-2017-9075、CVE-2017-9076、CVE-2017-9077,可影响几乎所有Linux kernel 2.5.69 ~Linux kernel 4.11的内核版本、对应的发行版本以及相关国产系统。可导致远程 DOS,且在符合一定利用条件下可导致 RCE,包括传输层的TCP、DCCP、SCTP以及网络层的IPv4和IPv6协议均受影响。实际上该漏洞在 Linux 4.11-rc8 版本中已经被启明星辰ADLab发现,且后来的Linux 4.11 stable版同样存在此问题。经研究这些漏洞在 Linux 内核中至少已经潜伏了11年之久,影响极为深远。

启明星辰ADLab已第一时间将“Phoenix Talon”漏洞反馈给了Linux 内核社区,漏洞上报后Linux社区在Linux 4.12-rc1中合并了修复该问题的补丁。

这些漏洞中以CVE-2017-8890最为严重(达到Linux内核漏洞两个评分标准的历史最高分,CVSS V2评分达到满分10.0,CVSS V3评分是历史最高分9.8,NVD上搜索历史上涉及Linux内核漏洞这样评分的漏洞不超过20个),以下分析以该漏洞为例,引用官方描述如下:

“The inet_csk_clone_lock function in net/ipv4/inet_connection_sock.c in the Linux kernel through 4.10.15 allows attackers to cause a denial of service (double free) or possibly have unspecified other impact by leveraging use of the accept system call.”

The Vulnerability

CVE-2017-8890本身是一个 double free 的问题,使用setsockopt()函数中MCAST_JOIN_GROUP选项,并调用accept()函数即可触发该漏洞。

接着先看看几个组播相关的数据结构:

http://p0.qhimg.com/t01246c4f863a71f38b.png

该结构体的两个成员分别用于指定所加入的多播组的组IP地址和所要加入组的本地接口IP地址。

ip_setsockopt()实现了该功能,它通过调用ip_mc_join_group()把socket加入到多播组。

http://p4.qhimg.com/t01e87bbb8d4cb0e53d.png

其中sk.__sk_common.skc_rcv_saddr对于组播而言,只接收该地址发来的组播数据,对于单播而言,只从该地址所代表的网卡接收数据;mc_ttl为组播的ttl;mc_loop表示组播是否发向回路;mc_index表示组播使用的本地设备接口的索引;mc_addr表示组播源地址;mc_list为组播列表。

http://p6.qhimg.com/t01c4178dc656581f79.png

next_rcu指向链表的下一个节点;multi表示组信息,即在哪一个本地接口上,加入到哪一个多播组;sfmode是过滤模式,取值为MCAST_INCLUDE或MCAST_EXCLUDE,分别表示只接收sflist所列出的那些源的多播数据报和不接收sflist所列出的那些源的多播数据报;sflist是源列表。

下面分别从该漏洞内存分配的关键代码及二次释放的关键代码进行分析。

1、The Allocate

https://p0.ssl.qhimg.com/t010507585740f23219.png

https://p2.ssl.qhimg.com/t0128a4d6e19dfaecb3.png

进入内核调用SyS_setsockopt()函数,level 设置的不为 SOL_SOCKET即可,一般设置为SOL_IP,在1798行处被调用。紧接着调用sock_common_setsockopt()函数。

net/ipv4/ip_sockglue.c

http://p2.qhimg.com/t0185d43dfe56eebbb0.png

然后进入ip_setsockopt()函数,调用 do_ip_setsockopt()函数(1264行代码)。

net/ipv4/ip_sockglue.c

http://p7.qhimg.com/t0171cf1eef7409b686.png

代码1019~1021行调用copy_from_user()将用户态的数据拷贝到内核态。之前已经将option设置为MCAST_JOIN_GROUP,紧接着调用ip_mc_join_group()函数:

net/ipv4/igmp.c

http://p1.qhimg.com/t01a9c181b8fbacad50.png

代码2128行sock_kmalloc()进行了内存分配。

2、The first free

在内核里无时无刻都在产生软中断,而此次漏洞涉及的软中断是由 accept()系统调用引起的,由于该函数本身作用于进程上下文,并不会产生软中断。但是调用 accept() 时,会在内核中诱发某种软中断产生,该软中断会调用rcu_process_callbacks()函数:

kernel/rcu/tree.c

http://p1.qhimg.com/t0126d41857bc2098dc.png

__rcu_process_callbacks调用rcu_do_batch()函数,如下:

kernel/rcu/tree.c

http://p3.qhimg.com/t01c7216e39bc17a24f.png

注意代码中第2879行,函数__rcu_reclaim()实现如下:

kernel/rcu/rcu.h

http://p2.qhimg.com/t015cac3807d2f33ade.png

在113行调用kfree()进行了第一次释放。

3、The second free

当断开TCP连接时,内核通过sock_close()函数直接调用sock_release()来实现断开功能,该函数会清空ops,更新全局 socket 数目,更新 inode 引用计数。随后进入到 inet_release()函数调用 tcp_close()函数来最终关闭 sock。

net/ipv4/af_inet.c

http://p3.qhimg.com/t01491fef7660038511.png

用户程序断开TCP连接时,内核里使用 ip_mc_drop_socket()函数进行回收。

net/ipv4/igmp.c

http://p8.qhimg.com/t013dd572b250598be0.png

代码2612行调用kfree_rcu()进行第二次释放。

Affected

1、受影响的内核版本

经研究,理论上Linux kernel 2.5.69 ~ Linux kernel 4.11的所有版本都受“Phoenix Talon”影响,且经开源社区验证“Phoenix Talon”漏洞影响的Linux内核版本部分列表如下:

http://p4.qhimg.com/t015da67c32d579927a.png

http://p3.qhimg.com/t0135f2f57e674f441b.png

http://p8.qhimg.com/t016d7fb59d51e22697.png

经启明星辰ADLab测试Linux kernel 4.11亦受影响。

2、受影响的发行版本

经开源社区验证部分受影响发行版本(不完整列表)如下:

Red Hat Enterprise MRG 2

Red Hat Enterprise Linux 7

Red Hat Enterprise Linux 6

Red Hat Enterprise Linux 5

SUSE Linux Enterprise Desktop 12 SP1

SUSE Linux Enterprise Desktop 12 SP2

SUSE Linux Enterprise Server 11 SP3 LTSS

SUSE Linux Enterprise Server 11 SP4

SUSE Linux Enterprise Server 12 GA

SUSE Linux Enterprise Server 12 SP1

SUSE Linux Enterprise Server 12 SP2

SUSE Linux Enterprise Server for SAP 11 SP3

SUSE Linux Enterprise Server for SAP 11 SP4

SUSE Linux Enterprise Server for SAP 12 GA

SUSE Linux Enterprise Server for SAP 12 SP1

SUSE Linux Enterprise Server for SAP 12 SP2

另外,启明星辰ADLab对下列的部分发行版本做了测试,确认均受“Phoenix Talon”漏洞影响:

Ubuntu 14.04LTS (Trusty Tahr)

Ubuntu 16.04LTS (Xenial Xerus)

Ubuntu 16.10(Yakkety Yak)

Ubuntu 17.04(Zesty Zapus)

Ubuntu 17.10(Artful Aardvark)

Solution

1、官方已经发布了修复该问题的补丁,可通过升级Linux内核修复“Phoenix Talon”相关漏洞。

2、使用 Grsecurity/PaX 对内核加固。

Timeline

May 09 – Report sent to Linux Kernel Community

May 09 – Linux Kernel Community confirmed

May 09 – Linux Kernel Community patched in linux upstream

May 10 – Assgined CVE number

“Phoenix Talon”在Linux内核中潜伏长达11年之久,影响范围非常广泛(以上只是官方以及我们测试的部分结果,即使这些也足够看出“Phoenix Talon”波及之深之广),启明星辰ADLab提醒广大用户尽快采取相应的修复措施,避免引发漏洞相关的网络安全事件。

Reference

1.https://people.canonical.com/~ubuntu-security/cve/2017/CVE-2017-8890.html

2.https://security-tracker.debian.org/tracker/CVE-2017-8890

3.https://www.suse.com/security/cve/CVE-2017-8890/

4.https://bugzilla.redhat.com/show_bug.cgi?id=1450973

5.https://bugzilla.suse.com/show_bug.cgi?id=1038544

6.https://www.mail-archive.com/netdev@vger.kernel.org/msg167626.html

7.https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8890

8.https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9075

9.https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9076

10.https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9077

11.https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/id=657831ffc38e30092a2d5f03d385d710eb88b09a

12.http://www.securityfocus.com/bid/98562/info

13.http://www.openwall.com/lists/oss-security/2017/05/30/24

14.https://www.kernel.org

15.Linux Kernel Documentation

(完)