Treck TCP/IP協議庫“Ripple20”系列漏洞分析
2020年6月16日,位于以色列的一家專門從事物聯網和嵌入式設備安全的JSOF公司警告說,由于嚴重安全漏洞影響了Treck TCP/IP協議堆棧,全球數億臺物聯網設備可能會受到遠程攻擊。該漏洞修復于2020年6月29號由Treck發布。
漏洞名稱 | CVE-2020-11896:Treck TCP/IP 任意代碼執行漏洞 CVE-2020-11898:Treck TCP/IP 信息泄露漏洞 |
威脅等級 | 高危 |
影響范圍 | Treck TCP/IP < 6.0.1.67 |
漏洞類型 | 代碼執行,拒絕服務 |
利用難度 | 困難 |
Treck TCP/IP是一家總部位于美國辛辛那提的軟件公司“Treck”在1997年推出的一套專用于嵌入式系統的TCP/IP底層Internet協議套件庫。通過設計針對內核、定時器、驅動程序、套接字的API接口,Treck TCP/IP協議套件庫可以很容易地集成到各種各樣的嵌入式產品中。二十多年來,全球很多公司一直在使用這個庫,使他們的設備或軟件通過TCP/IP協議連接到互聯網。
2.1 TCP/IP堆棧介紹
首先介紹Treck TCP/IP使用的2個機制:
(1)ipv4報文分片操作
在TCP/IP協議中,由于數據鏈路層MTU(最大傳輸單元)的限制,當一個IP數據包從一個MTU較高的網絡傳向MTU較低的網絡時數據包就會被分片成一個個大小小于或等于MTU較低的目標網絡的碎片。數據包在傳輸過程中往往都要經過數個網絡,每個網絡的MTU或許都不同,如果數據包大小比網絡的MTU大時就進行分片,如果比網絡的MTU小時則不做操作,也就是說傳輸過程中數據包可能被多次分片,但不進行重組,重組操作由數據包的最終接收方執行。
(2)IP隧道
IP隧道技術允許兩個獨立網絡之間的虛擬點對點鏈接。它是通過將一個數據包(可能是IP數據包)封裝在另一個數據包中來實現的,從而使內部數據包具有與外部數據包不同的源地址和目的地址。
外部數據包的源地址和目的地址是IP隧道的兩端,內部數據包的地址用于在兩側的網絡中傳輸數據。中間的路由器不會考慮封裝的數據內容,而鏈接的兩端需要配置隧道協議。入口點需要將原始數據包用外部IP封裝,出口點則要解包并檢查其中是否存在一個可以在目標網絡中發送的標準數據包。
根據JSOF對這個漏洞的描述,Treck TCP/IP協議堆棧中的數據包由稱為tspacket的數據結構表示,包含另一個重要結構ttUserPacket,以及指向tsSharedData數據結構的指針,一個tspacket與一個數據緩沖區相關聯,tspacket包含以下幾個涉及漏洞的字段:
tsSharedData結構為:
這些結構用于支持IP報文分片,字段pktuLinkDataPtr指向當前片段的數據緩沖區。這個數據緩沖區中的確切位置隨著網絡堆棧在不同階段處理數據包的不同而改變,并取決于當前正在處理的數據包的層位置。堆棧中的一個常見模式是報文在堆棧中的層之間移動時調整pktuLinkDataPtr指針。例如,如果我們的數據包是ICMP返回請求數據包(Ping),數據將由三層包組成:以太網,其次是IPv4,最后是ICMP。在這種情況下,當以太網層被處理時(在函數tfEtherRecv中),pktuLinkDataPtr指向以太網報頭的開始處,然后在移動到下一層之前,使用以下圖所示代碼進行調整:
0xe是以太網報頭(6位(目的地址MAC)+6位(源地址MAC)+2位(以太網類型))的長度大小。當tfEtherRecv完成數據包處理時,它使用表示下一層協議的以太網類型EtherType字段將數據包轉發到下一層處理。所支持以太網類型包括ARP、IPv4和IPv6。
2.2 漏洞根本原因
首先了解以下兩個字段:
IHL(4位):表示IP報頭的大小(以雙字為單位)。最小值為5(20個字節)。如果有IP選項,則報頭長度會變大,最大值為0xf(60字節)。
TotalLength總長度(2字節):整個IP數據包的大小,以字節為單位包括報頭。
函數tfIpIncomingPacket從一些基本的健全性檢查開始。除報頭校驗和外還驗證ip_version,data_available,header_length,total_length等字段,如果所有健全性檢查均通過,則該函數檢查IP報頭中指定的總長度是否嚴格小于數據包的pktuChainDataLength值,如果是則表明實際收到的數據比IP報頭中所描述的要多,這時進行微調操作以刪除多余的數據。如果為真,則進行微調操作以刪除多余的數據。判斷方式為:
這造成了協議的漏洞。pktuLinkDataLength的大小為當前片段和pktuChainDataLength保存整個數據包的大小。如果上述操作發生,則會創建了一個不一致情況,其中pkt->pktuChainDataLength==pkt->pktuLinkDataLength,但可能會有其他片段指向pkt->pktuLinkNextPtr。另一種情況,鏈表上片段的總長度比存儲在pktuChainDataLength中的長度要大,這時構成不一致的狀態。
每次使用一個接收到的片段都會調用tfIpIncomingPacket函數,并會調用-tfIp ReassemblePacket來處理。tfIpReassemblePacket負責將片段插入到上面描述的鏈表中。它不會將片段復制到連續的內存緩沖區中。接收到所有片段時,tfIpReassemblePacket將完整數據包作為片段的鏈接列表返回,以便在下一個協議層上進一步處理。此重組操作是在易受攻擊的微調操作之后執行的。一旦重新分配操作完成,tfIpIncomingPacket將返回或轉發數據包,以便在下一個網絡層(例如:UDP)進行處理。因為我們需要一個碎片化的數據包才能到達不一致狀態,所以這種情況阻止了我們利用漏洞。換句話說,成功攻擊的代碼只可能會在每個碎片的基礎上執行(或者在單個碎片分組上)。
這樣做并不易實現漏洞利用,但是結合IP隧道即可以實現允許封裝的內層IP數據包被tfIpIncomingPacket函數作為非碎片數據包處理。tfIpIncomingPacket函數將被遞歸調用,一次用于IP隧道的內層,幾次用于外層(每個碎片一次)。當tfIpIncomingPacket函數處理內層IP數據包時,它正在處理傳入的片段數據(內層IP數據包由鏈接在一起的兩個tsPacket結構表示),但仍將調用易受攻擊的微調數據流,從而構成了漏洞利用的條件。
使用UDP實現堆棧溢出。由于已經有了一個定義長度和實際長度不一致的狀態,接下來可以利用這個不一致來實現內存空間攻擊。協議中有一段代碼,實現將片段數據復制到單個連續緩沖區中。這是處理UDP數據報的代碼的一部分。該操作的內部邏輯包括分配一個新的數據包(使用tfGetSharedBuffer),其大小基于pktuChainDataLength字段,然后將數據包的不同片段復制到新分配的數據包中。負責執行復制功能的函數是tfCopyPacket函數,它按順序接受源數據包和目標數據包。
可以看出,函數tfCopyPacket沒有考慮到它寫入緩沖區的長度。它只是從源數據包(我們的分段數據包)中獲取每個鏈接,并將其數據復制到目標數據包中。目標數據包是根據pktuChainDataLength的值分配的,因此,如果之前漏洞被觸發了,則分配的緩沖區可能小于我們失效后數據包中所有單獨鏈接的長度總和,此時,就會發生緩沖區堆溢出。
綜上所述,當使用Treck TCP/IP協議棧的設備,開放UDP端口正在偵聽,我們可以快速發送數據包,以便套接字接收隊列為非空。同時,我們發送一個人為構建好的片段化的UDP數據包,該數據包將觸發漏洞。如果之前使用tfGetSharedBuffer在內存上分配了一個小的緩沖區,那么tfCopyPacket操作可以將其成功溢出。
受影響版本:Treck TCP/IP < 6.0.1.67
3.1檢測方式
可通過針對代碼資產進行核查,看是否使用了Treck的相關代碼,并從源代碼中查看軟件版本是否在受影響范圍。針對二進制庫文件,可以使用如下命令查看庫文件的版本,確定是否使用了受影響的版本。
strings 驅動名稱| grep -e"[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"
若檢測當前版本在受影響范圍內,則存在上述安全風險。
3.2修復建議
TreckTCP/IP最新版本已修復該漏洞,修復版本為6.0.1.67及其后的所有版本。
訪問該鏈接獲取最新版相關組件:https://treck.com/products/
3.3 深信服檢測方案
訪問該鏈接獲取深信服檢測工具:
https://edr.sangfor.com.cn/api/download/scan_tool.zip
Treck官方發布漏洞相關軟件庫更新
深信服千里目安全實驗室發布漏洞分析文章
(本文由深信服科技供稿)
CHIMA大講堂直播與回放:
https://djt.chima.org.cn
全國衛生健康行業網絡安全技能大賽:
https://chcsc.chima.org.cn
點擊此處可查看文章詳情