Linux内核TCP和谈多个SACK职能回绝服务缝隙分析

颁布功夫 2019-06-21
缝隙布景


2019年6月18日,,,,,,,,Redhat颁布安全布告,,,,,,,,Linux内核TCP/IP和谈栈存在3个安全缝隙(CVE-2019-11477/CVE-2019-11478/CVE-2019-11479),,,,,,,,这些缝隙与最大分段大幼!�。 。。。∕SS)和TCP选择性确认(SACK)职能有关,,,,,,,,允许远程攻击者进行回绝服务攻击。。。 。。。


关键概想



数据包沉传确认机造


TCP数据包传输过程中,,,,,,,,来自滑动窗口的数据包迷失可能对TCP吞吐量产生影响。。。 。。。TCP使用累积确认(ACK)规划解决该问题,,,,,,,,其中不接管不在滑动窗口左边缘的接管段,,,,,,,,这会强造发送方期待往返功夫以找出每个迷失的数据包,,,,,,,,或者不用腹地沉新传输已正确接管的段,,,,,,,,从而降低整体吞吐量。。。 。。。


选择性确认(SACK)是一种在多个抛弃的段的情况下解决此行为的战术。。。 。。。通过选择性确认,,,,,,,,数据接管方能够向发送方通知已成功达到的所有段,,,,,,,,因而发送方只需沉新传输现实迷失的段。。。 。。。具体选择性确认过程,,,,,,,,如下图所示。。。 。。。


8827太阳集团(Macau)股份有限公司-Official website


最大分段大幼!�。 。。。∕aximum Segment Size)


MSS(Maximum Segment Size,,,,,,,,最大报文段大幼!�。 。。。┑母畔胧侵窽CP层所可能接管的最大分段大幼!�。 。。。�,,,,,该值只蕴含TCP段的数据部门,,,,,,,,不蕴含Option部门。。。 。。。另表,,,,,,,,在TCP首部有一个MSS选项,,,,,,,,在三次握手过程中,,,,,,,,TCP发送端使用该选项通知对方自己所能接受的最大分段大幼。。。 。。。


TSO(TCP Segmentation Offload)


TSO是一种利用网卡来对大数据包进行自动分段,,,,,,,,降低CPU负载的技术。。。 。。。其重要是延长分段。。。 。。。


GSO(Generic Segmentation Offload)


GSO是和谈栈是否推迟分段,,,,,,,,在发送到网卡之前判断网卡是否支持TSO,,,,,,,,若是网卡支持TSO则让网卡分段,,,,,,,,不然和谈栈分完段再交给驱动。。。 。。。若是TSO开启,,,,,,,,GSO会自动开启。。。 。。。


缝隙道理


CVE-2019-11477


凭据补丁可知,,,,,,,,该缝隙是由一个16bit无符号数溢出导致的,,,,,,,,该无符号数存在如下结构体钟祝。。 。。。


8827太阳集团(Macau)股份有限公司-Official website


该tcp_skb_cb结构体存放着TCP每个数据包的节造信息,,,,,,,,凭据注解可知,,,,,,,,tcp_gso_segs/size只用于写队列过程钟祝。。 。。。


Linux内核TCP/IP和谈栈实现中,,,,,,,,每个数据缓冲区是由一个sk_buff结构体统一治理的。。。 。。。在一个齐全的数据缓冲区中skb_end后面紧随着一个skb_shared_info结构体数据,,,,,,,,skb_shared_info结构体如下所示:


8827太阳集团(Macau)股份有限公司-Official website


结构体最后一个成员是frags[MAX_SKB_FRAGS]数据。。。 。。。MAX_SKB_FRAGS申明如下所示:

8827太阳集团(Macau)股份有限公司-Official website


PAGE_SIZE为4KB情况下(即一个内存页面为4KB大幼!�。 。。。�,,,,,MAX_SKB_FRAGS取值为65536/4096 + 1即17,,,,,,,,因而一个skb中最多包容17个数据吩飕。。。 。。。对于x86系统,,,,,,,,每个数据吩飕最多能够纪录32KB数据的大幼。。。 。。。
数据吩飕skb_frag_struct结构体如下所示:


8827太阳集团(Macau)股份有限公司-Official website


在整个和谈栈操作过程中,,,,,,,,数据包既要进行IP被吩飕的,,,,,,,,又要进行TCP分段。。。 。。。传输数据时,,,,,,,,和谈栈会凭据GSO值,,,,,,,,MSS值以及滑动窗口三者之间的大幼关系判断是否进行吩飕。。。 。。。并通过tcp_set_skb_tso_segs()函数设置GSO,,,,,,,,具体实现如下图所示:


8827太阳集团(Macau)股份有限公司-Official website


若是skb->len大于mss_now,,,,,,,,行1207,,,,,,,,将tcp_gso_segs设置为skb->len/mss_now。。。 。。。行1208,,,,,,,,将tcp_gso_size设置为mss_now。。。 。。。


若是启用了SACK,,,,,,,,在产生丢包后,,,,,,,,接管端会返回SACK块,,,,,,,,SACK块中纪录沉迷失包的序列编号。。。 。。。发送端会解析SACK块中纪录的迷失包序列编号,,,,,,,,并沉新传输,,,,,,,,并且在一个滑动窗口中可能蕴含多个SACK块,,,,,,,,SACK块中也可能蕴含多个skb队劣祝。。 。。。在TCP沉传数据包过程中,,,,,,,,能够将多个skb队列归并到一个skb队列中进行沉传。。。 。。。


tcp_shift_skb_data()函数实现这个职能。。。 。。。尝试将逾越多个skb的SACK块折叠为一个skb。。。 。。。关键代码如下:


8827太阳集团(Macau)股份有限公司-Official website


skb_shift()和tcp_shifted_skb()两个函数重要实现该职能。。。 。。。沉传过程中多个skb队列归并到一个skb队列中,,,,,,,,若是填充17个吩飕到最大容量,,,,,,,, 17*32*1024/8=69632,,,,,,,,已经大于65535,,,,,,,,导致无符号整数溢出。。。 。。。


在skb_shift ()函数中,,,,,,,,tcp_gso_segs溢出后,,,,,,,,进入tcp_shifted_skb()函数后,,,,,,,,如下所示:


8827太阳集团(Macau)股份有限公司-Official website


行1299,,,,,,,,判断tcp_gso_segs和pcount的大幼!�。 。。。�,,,,,若是tcp_gas_segs幼于pcount,,,,,,,,BUG_ON断言触发导致内核崩溃。。。 。。。


凭据补丁可知,,,,,,,,skb_shift()被tcp_skb_shift()包办,,,,,,,,只是加了两个判断,,,,,,,,如下所示:

8827太阳集团(Macau)股份有限公司-Official website


补丁平别离判断了skb->len+shift_len不能大于65535*8字节和tcp_skb_pcount(to) + pcount不能大于65535。。。 。。。第一个判断,,,,,,,,skb->len是暗示sk_buff结构体中暗示payload长度,,,,,,,,shift_len暗示要归并到skb中的payload。。。 。。。


CVE-2019-11478


该缝隙也是整数溢出,,,,,,,,在数据包沉新传输过程中,,,,,,,,将传输队列分段为多个微幼的skbs,,,,,,,,膨胀skb中写队列内存产生溢出。。。 。。。在处置SACK块中蕴含的skb并将其归并后,,,,,,,,凭据GSO判断进行是否吩飕,,,,,,,,若是必要,,,,,,,,挪用tcp_fragement()函数进行吩飕。。。 。。。凭据补丁可知:


8827太阳集团(Macau)股份有限公司-Official website


补丁在tcp_fragment()函数中参与了最幼空间判断。。。 。。。Sk是sock结构体类型,,,,,,,,每一个tcp链接对应一个。。。 。。。所以所有要发送的skb数据大幼都要累加到sk->sk_wmem_queued中,,,,,,,,sk->sk_wmem_queued暗示为该套接字TCP写队列缓冲区大幼。。。 。。。通常在使用时辰必要判断该值是否够用。。。 。。。如下所示:


8827太阳集团(Macau)股份有限公司-Official website


凭据注解可知,,,,,,,,判断最新列队skb包所需的最幼可写空间。。。 。。。补丁中,,,,,,,,判断渣滓发送缓存为大于蹬宗当前发送队列占用空间的一半,,,,,,,,即还有1/3以上的空余空间时,,,,,,,,并且幼于sk->sk_sndbuf发奉上限能力够正常发送,,,,,,,,不然就判定TCP写队列太大。。。 。。。


CVE-2019-11479


该缝隙由于过度亏损资源导致回绝服务。。。 。。。若是恶意数据包将MSS选项设置成较幼值,,,,,,,,这将迫使和谈栈破费极度高的网络或CPU资源发送数据包开销。。。 。。。Linux内核中将MSS_NOW硬编码为48。。。 。。。凭据补丁可知:

8827太阳集团(Macau)股份有限公司-Official website


进行了max最大值判断,,,,,,,,而不再是固定硬编码。。。 。。。这里的sysctl_tcp_min_snd_mss被设置为65535,,,,,,,,如下所示:


8827太阳集团(Macau)股份有限公司-Official website


预防了攻击者使用极幼MSS值。。。 。。。


影响版本及补丁建复


实时更新最新补丁或禁用SACK和过滤极幼MSS的数据包。。。 。。。


CVE-2019-11477

影响版本:

  • Linux 2.6.29 ~ 4.19.13(stable kernel releases 4.4.182,  4.9.182, 4.14.127, 4.19.52, 5.1.11之表)

  • RHEL 8 (kernel, kernel-rt),,,,,,,,RHEL 7 (kernel, kernel-rt),,,,,,,,RHEL 6

禁用sack:

  • sudo sysctl -w net.ipv4.tcp_sack=0

补丁!�。 。。。�

  • https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git/commit/?id=3b4929f65b0d8249f19a50245cd88ed1a2f78cff

CVE-2019-11478

影响版本:

  • Linux 2.6.29 ~ 4.19.13(stable kernel releases 4.4.182,  4.9.182, 4.14.127, 4.19.52, 5.1.11之表)

  • RHEL 8 (kernel, kernel-rt),,,,,,,,RHEL 7 (kernel, kernel-rt),,,,,,,,RHEL 6,,,,,,,,RHEL 5

禁用sack:

  • sudo sysctl -w net.ipv4.tcp_sack=0

补丁!�。 。。。�

  • https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git/commit/?id=f070ef2ac66716357066b683fb0baf55f8191a2e

CVE-2019-11479

影响版本:

  • Linux 2.6.29 ~ 4.19.13(stable kernel releases 4.4.182,  4.9.182, 4.14.127, 4.19.52, 5.1.11之表)

  • RHEL 8 (kernel, kernel-rt),,,,,,,,RHEL 7 (kernel, kernel-rt),,,,,,,,RHEL 6,,,,,,,,RHEL 5

过滤号令:

  • sudo iptables -A INPUT -p tcp -m tcpmss --mss 1:500 -j DROP

关关tcp_mtu_probing:

  • sysctl net.ipv4.tcp_mtu_probing

补丁!�。 。。。�

  • https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git/commit/?id=5f3e2bf008c2221478101ee72f5cb4654b9fc363

  • https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git/commit/?id=967c05aee439e6e5d7d805e195b3a20ef5c433d6