概述
在Linux核心处理TCP网络资料包时候存在缺陷导致三个漏洞,CVE编号分别为:CVE-2019-11477,CVE-2019-11478和CVE-2019-11479。最严重的漏洞CVE-2019-11477,可以让远端攻击者DDOS系统导致核心崩溃,从而影响系统的可用性。根据Redhat官方安全中心标准CVE-2019-11477为严重漏洞(Important),而CVE-2019-11478和CVE-2019-11479中等漏洞(Moderate)。三个漏洞中前两个与资料包选择性确认(SACK)和最大段大小(MSS)相关,第三个漏洞与最大段大小(MSS)相关。
Redhat官方目前已经提供升级包和缓解引数设定措施,。
漏洞背景
Linux核心处理TCP网络资料包时候存在缺陷导致三个漏洞,CVE编号分别为:CVE-2019-11477,CVE-2019-11478和CVE-2019-11479。漏洞仅可以用于DOS拒绝攻击,不涉及资讯泄露或者许可权提升。选择性确认SACK
TCP的选择性确认(Selective Acknowledgment,SACK)是一种机制,资料接收方可以通知传送方有关成功接受的资料包段的资讯。这样来通知传送方重传发送包集中丢失的资料包段。禁用TCP SACK时,需要重传整个资料包完成资料传输。最大资料包段大小MSS
最大资料包段大小(maximum segment size,MSS)是TCP报头中设定的引数,用来指定重建TCP资料包段需要的资料的大小。由于资料包在变化的路由网络传输过程中可能会碎片化,因此主机必须将MSS指定为等于主机可以处理的最大IP资料报文的有效负载大小。MSS过大可能会导致资料包流在到达目的地的过程中碎片化,较小的资料包可以确保较少的碎片但最终会导致未使用的开销。
操作系统和传输型别预设设定了MSS大小。有特权访问许可权的攻击者可以在资料包中建立特殊的MSS设定的原始资料包传送攻击。
TCP SACK
TCP是面向连线的协议。当双方希望通过TCP连线进行通讯时,他们通过TCP握手交换某些资讯建立连线,例如发起一个TCP请求,通过SYN传送初始序列ID,确认ID,连线使用的最大资料包段大小(MSS),认证资讯和处理选择性确认(SACK)等。整体TCP连线通过我们熟知的三次握手最终建立。TCP通过一个数据段单元传送和接收使用者资料包。 TCP资料段由TCP头,选项和使用者资料组成。每个TCP段都有序列号(SEQ)和确认号(ACK)。
接收方通过SEQ号和ACK号来跟踪成功接收了哪些段。ACK号下一个预期接受的段。

上图中使用者A通过13个100字节的段传送1k字节的资料,每个段具有20字节的TCP头,总计是13个段。在接收端,使用者B接收了段1,2,4,6,8-13,而段3,5和7丢失,B没有接收到。
通过使用ACK号,使用者B告诉A,他需要段3,使用者A收到B接收到2,而没有收到3,A将重新发送全部段,尽管B已经收到了4,6和8-13段。所以导致大量重复传输,效能低下。
选择性确认SACK

为了解决上面提到的问题问题,Linux在RFC-201议案中提出了选择性确认(Selective Acknowledgement,SACK)机制。通过SACK,B可以使用TCP选项字段通知A已成功接收了的所有段(1,2,4,6,8-13),A只需重传段3,5和7就可以。这样一来可以大大节省了网络带宽,提高了效能。

SACK奔溃: CVE-2019-11477
套接字缓冲区(SKB):
套接字缓冲区(Socket Buffer,SKB)是Linux TCP/IP实现中使用的核心的资料结构。它是缓冲区的连结列表,用来储存网络资料包。该列表可以用做传输伫列,接收伫列和SACK伫列,重传伫列等。SKB可以将分组资料储存成片段,Linux SKB最多可以容纳17个片段。该数在linux/include/linux/skbuff.h定义:define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1) => 17
在x86平台上每段资料包中最多可容纳32KB的资料(PowerPC上为64KB)。资料包将传送时,它被放置在传送伫列中,它的详细资讯定义控制缓冲区结构中( linux/include/linux/skbuff.h):

其中,tcp_gso_segs和tcp_gso_size字段用通知装置驱动程式有关分段解除安装的资讯。
当Segmentation offload选项开启并且SACK机制也启用时,由于资料包丢失和某些资料包的选择性重传,SKB可能最终持有多个数据包,由tcp_gso_segs计数。列表中的多个这样的SKB被合并为一个以有效地处理的不同SACK块。它涉及将资料从一个SKB移动到列表中的另一个SKB。在此资料移动期间,SKB结构可以达到其最大限制为17个片段,并且tcp_gso_segs引数可以溢位并触发下面的BUG_ON()呼叫,从而导致所述核心奔溃。

远端使用者可以通过将TCP连线的最大段大小(MSS)设定为48字节的最低限制并发送一系列特殊的SACK资料包来触发此问题,导致最低MSS每段仅留下8字节资料,从而增加了传送所有资料所需的TCP段数。
影响版本
影响Linux 核心2.6.29及以上版本
Centos
修复和缓解方案
及时更新补丁
可以等待发行方的补丁包,然后通过包管理器(yum,apt)等升级。核心设定
通过设定Linux核心引数禁用SACK,方法:echo 0 > /proc/sys/net/ipv4/tcp_sack
后者
sysctl -w net.ipv4.tcp_sack=0
可以防止CVE-2019-11477 和 CVE-2019-11478攻击。
可以防火墙设定限制MSS大小,对太小的包直接DROP:
firewall:
firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -p tcp --tcp-flags SYN SYN -m tcpmss --mss 1:500 -j DROPfirewall-cmd --permanent --direct --add-rule ipv6 filter INPUT 0 -p tcp --tcp-flags SYN SYN -m tcpmss --mss 1:500 -j DROP
firewall-cmd -reload
firewall-cmd --permanent --direct --get-all-rules
iptables:
iptables -I INPUT -p tcp --tcp-flags SYN SYN -m tcpmss --mss 1:500 -j DROPiptables -nL -v
批量更新(Ansible)
最后提供一个Ansible cook档案用来批量更新禁止SACK:
将以上程式码储存为disable_tcpsack.yml,然后ansible执行:
ansible-playbook -e HOSTS=all disable_tcpsack.yml





























