作者: 啟明星辰ADLab
公眾號: https://mp.weixin.qq.com/s/cVZvgd5xvj4ljchlwDSDYQ

一、漏洞背景

2019年6月18日,Redhat發布安全公告,Linux內核TCP/IP協議棧存在3個安全漏洞(CVE-2019-11477/CVE-2019-11478/CVE-2019-11479),這些漏洞與最大分段大小(MSS)和TCP選擇性確認(SACK)功能相關,允許遠程攻擊者進行拒絕服務攻擊。

二、關鍵概念

(一)數據包重傳確認機制

TCP數據包傳輸過程中,來自滑動窗口的數據包丟失可能對TCP吞吐量產生影響。TCP使用累積確認(ACK)方案解決該問題,其中不接收不在滑動窗口左邊緣的接收段,這會強制發送方等待往返時間以找出每個丟失的數據包,或者不必要地重新傳輸已正確接收的段,從而降低整體吞吐量。

選擇性確認(SACK)是一種在多個丟棄的段的情況下解決此行為的策略。通過選擇性確認,數據接收方可以向發送方通知已成功達到的所有段,因此發送方只需重新傳輸實際丟失的段。具體選擇性確認過程,如下圖所示。

(二)最大分段大小(Max Segment Size)

MSS(Maximum Segment Size,最大報文段大小)的概念是指TCP層所能夠接收的最大分段大小,該值只包括TCP段的數據部分,不包括Option部分。另外,在TCP首部有一個MSS選項,在三次握手過程中,TCP發送端使用該選項告訴對方自己所能接受的最大分段大小。

(三)TSO(TCP Segmentation Offload)

TSO是一種利用網卡來對大數據包進行自動分段,降低CPU負載的技術。其主要是延遲分段。

(四)GSO(Generic Segmentation Offload)

GSO是協議棧是否推遲分段,在發送到網卡之前判斷網卡是否支持TSO,如果網卡支持TSO則讓網卡分段,否則協議棧分完段再交給驅動。如果TSO開啟,GSO會自動開啟。

三、漏洞原理

(一) CVE-2019-11477

根據補丁可知,該漏洞是由一個16bit無符號數溢出導致的,該無符號數存在如下結構體中。

該tcp_skb_cb結構體存放著TCP每個數據包的控制信息,根據注釋可知,tcp_gso_segs/size只用于寫隊列過程中。

Linux內核TCP/IP協議棧實現中,每個數據緩沖區是由一個sk_buff結構體統一管理的。在一個完整的數據緩沖區中skb_end后面緊跟著一個skb_shared_info結構體數據,skb_shared_info結構體如下所示:

結構體最后一個成員是frags[MAX_SKB_FRAGS]數據。MAX_SKB_FRAGS聲明如下所示:

PAGE_SIZE為4KB情況下(即一個內存頁面為4KB大小),MAX_SKB_FRAGS取值為65536/4096 + 1即17,因此一個skb中最多容納17個數據分片。對于x86系統,每個數據分片最多可以記錄32KB數據的大小。

數據分片skb_frag_struct結構體如下所示:

在整個協議棧操作過程中,數據包既要進行IP被分片的,又要進行TCP分段。傳輸數據時,協議棧會根據GSO值,MSS值以及滑動窗口三者之間的大小關系判斷是否進行分片。并通過tcp_set_skb_tso_segs()函數設置GSO,具體實現如下圖所示:

如果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。關鍵代碼如下:

skb_shift()和tcp_shifted_skb()兩個函數主要實現該功能。重傳過程中多個skb隊列合并到一個skb隊列中,如果填充17個分片到最大容量, 17 * 32 * 1024/8=69632,已經大于65535,導致無符號整數溢出。

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

行1299,判斷tcp_gso_segs和pcount的大小,如果tcp_gas_segs小于pcount,BUG_ON斷言觸發導致內核崩潰。

根據補丁可知,skb_shift()被tcp_skb_shift()代替,只是加了兩個判斷,如下所示:

補丁中分別判斷了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()函數進行分片。根據補丁可知:

補丁在tcp_fragment()函數中加入了最小空間判斷。Sk是sock結構體類型,每一個tcp鏈接對應一個。所以所有要發送的skb數據大小都要累加到sk->sk_wmem_queued中,sk->sk_wmem_queued表示為該套接字TCP寫隊列緩沖區大小。通常在使用時候需要判斷該值是否夠用。如下所示:

根據注釋可知,判斷最新排隊skb包所需的最小可寫空間。補丁中,判斷剩余發送緩存為大于等于當前發送隊列占用空間的一半,即還有1/3以上的空余空間時,并且小于sk->sk_sndbuf發送上限才可以正常發送,否則就判定TCP寫隊列太大。

(三) CVE-2019-11479

? 該漏洞由于過度消耗資源導致拒絕服務。如果惡意數據包將MSS選項設置成較小值,這將迫使協議棧花費非常高的網絡或CPU資源發送數據包開銷。Linux內核中將MSS_NOW硬編碼為48。根據補丁可知:

進行了max最大值判斷,而不再是固定硬編碼。這里的sysctl_tcp_min_snd_mss被設置為65535,如下所示:

避免了攻擊者使用極小MSS值。

四、影響版本及補丁修復

及時更新最新補丁或禁用SACK和過濾極小MSS的數據包。

CVE-2019-11477

影響版本:

Linux 2.6.29 ~ 4.19.13(stable kernel releases4.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 releases4.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 releases4.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


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/960/