AMNESIA33:開源TCP/IP協議棧系列漏洞分析與驗證

發布時間 2020-12-14

前言


近期,國外安全研究人員在多個被廣泛使用的開源TCP/IP協議棧發現了多個漏洞,這一系列漏洞統稱為AMNESIA33。這些漏洞廣泛存在于嵌入式和物聯網設備中,影響了多個行業領域(包括醫療、運輸、能源、電信、工業控制、零售和商業等),目前已知范圍內涉及了超150家供應商以及數以百萬計的設備。與URGEN11和Ripple20不同的是,AMNESIA33影響的是多個開源TCP/IP協議棧,因此這些漏洞可以悄無聲息地影響到無數個代碼庫、開發團隊與各個公司的產品。目前已知的漏洞涉及到了智能家居、工廠PLC、SCADA設備與工控交換機,電力監控等設備。


這些漏洞存在于uIP、FNET、picoTCP和Nut/Net等開源協議棧上,影響TCP/IP協議棧的多個組件,包括DNS、IPv6、IPv4、TCP、ICMP、LLMNR和mDNS等。其中包括多個嚴重漏洞,它們的CVE編號分別為CVE-2020-17437、CVE-2020-17443、CVE-2020-24338、CVE-2020-24336、CVE-2020-25111。


CVE-2020-17437(CVSS評分8.2)、CVE-2020-17443(CVSS評分8.2)可導致設備拒絕服務。CVE-2020-24338、CVE-2020-24336、CVE-2020-25111(這三個CVSS評分均為9.8)都可導致遠程代碼執行(RCE)。其它28個漏洞的嚴重程度各異,CVSS評分分別從4到8.2。


由于IoT、OT、IT設備供應鏈的特性,漏洞影響的設備眾多,影響范圍廣且持續時間長,漏洞修復的實施較困難。同時,由于uIP、picoTCP開源協議棧已經不再維護,所以部分漏洞沒有補丁,很多產品只能尋找替代技術方案或者是增加防范措施。


因此,啟明星辰ADLab對相關漏洞進行了分析,并成功復現了多個漏洞,開發了AMNESIA33相關漏洞檢測技術,并提取了流量監控特征,這些技術正在應用到我們的安全產品中。為了緩解漏洞的影響,我們提出下列防范建議。

防范建議 


對于這些漏洞的防范緩解措施,我們建議采取如下幾個措施: 


● 配置內網設備的DNS服務器為內網DNS服務器。

● 如不必要,請關閉IPv6設置。

● 利用漏掃產品識別出采用問題協議棧的設備資產,對組織內可能存在問題的IoT、OT和IT設備進行風險評估。

● 防火墻及IPS產品加入AMNESIA33漏洞攻擊識別特征,監控惡意流量。

● 如不必要,設備不要暴露在公網。

● 盡可能更新相關受影響協議棧到最新版本。


下表是部分已經修復的協議棧及版本:


TCP/IP協議棧

修復版本

FNET

4.70及以上

uIP-Contiki-NG

4.6.0及以上

Nut/Net

5.1及以上



CISA聯盟分享了13個涉及到AMNESIA33漏洞的公司的產品修復建議,包括了Microchip、Siemens等公司的產品,詳見參考鏈接[5]。


相關概念介紹 


1、DNS協議解析


DNS的請求和響應的基本單位是DNS報文(Message)。請求和響應的DNS報文結構是完全相同的,每個報文都由以下五段(Section)構成:


圖片


DNS Header是每個DNS報文都必須擁有的一部分,它的長度固定為12個字節。Question部分存放的是向服務器查詢的域名數據,一般情況下它只有一條Entry。每個Entry的格式是相同的,如下所示:


圖片


QNAME是由labels序列構成的域名。QNAME的格式使用DNS標準名稱表示法。這個字段是變長的,因此有可能出現奇數個字節,但不進行補齊。DNS使用一種標準格式對域名進行編碼。它由一系列的label(和域名中用.分割的label不同)構成。每個label首字節的高兩位用于表示label的類型。RFC1035中分配了四個里面的兩個,分別是:00表示的普通label,11(0xC0)表示的壓縮label。


Answer、Authority和Additional三個段的格式是完全相同的,都是由零至多條Resource Record(資源記錄)構成。這些資源記錄因為不同的用途而被分開存放。Answer對應查詢請求中的Question,Question中的請求查詢結果會在Answer中給出,如果一個響應報文的Answer為空,說明這次查詢沒有直接獲得結果。


RR(Resource Record)資源記錄是DNS系統中非常重要的一部分,它擁有一個變長的結構,具體格式如下:


圖片


● NAME:它指定該條記錄對應的是哪個域名,格式使用DNS標準名稱表示法

● TYPE:資源記錄的類型。

● CLASS:對應Question的QCLASS,指定請求的類型,常用值為IN,值為0x001。

● TTL(Time To Live)資源的有效期:表示你可以將該條RR緩存TLL秒,TTL為0表示該RR不能被緩存。TTL是一個4字節有符號數,但是只使用它大于等于0的部分。

● RDLENGTH:一個兩字節非負整數,用于指定RDATA部分的長度(字節數)。

● RDATA:表示一個長度和結構都可變的字段,它的具體結構取決于TYPE字段指定的資源類型。

DNS響應包如下圖所示:


圖片


從上圖中可知,該Answers區段中存在9個資源記錄,紅框中表示的是主機地址(A類型)資源記錄。


域標簽label在DNS數據包里被編碼,每個普通標簽的第一個字節代表這個標簽的長度,剩下的字母數字字符為標簽本身(一些特殊字符也是可以的),但是最終結尾的字符一定是以空字節結尾(即0x00),用來表示域名的結束。舉個例子,如下圖所示,域標簽第一個字符是0x03,這代表第一個標簽長度為3(即0x77 0x77 0x77 == “www”),同理,0x62 0x61 0x690x64 0x75 == “baidu”,最后可以看到以0x00結尾。


圖片


2、TCP緊急模式


為了發送重要協議數據,TCP提供了一種稱為緊急模式(urgentmode)的機制,TCP協議在數據段中設置URG位,表示進入緊急模式。通過設置緊急模式,發送方可以在發送隊列中優先發送這部分的數據,而且不用在發送隊列中排隊,而接收方可以對緊急模式采取特殊的處理。這種方式數據不容易接受被阻塞,服務器端程序會優先接受這些緊急的數據,而不用進行排隊處理。在TCP報文中定義了兩個字段來標示緊急模式,一個URG標志,該標志表示報文中有緊急數據,另一個標志是緊急指針,它標示緊急數據在傳輸數據中偏移位置。如下圖所示:


圖片


漏洞分析 


下面我們對幾個CVSS評分較高的漏洞進行分析:


1、CVE-2020-17437


CVE-2020-17437存在于uIP協議棧的uip.c文件的uip_process函數中,該函數主要是處理ip/tcp報文,下圖是uIP協議棧對TCP報文中帶有TCP_URG緊急指針標識時的處理代碼,如果編譯時配置了UIP_URGDATA,則程序會走到下面的if分支,對緊急指針數據進行專門處理。


但是在默認情況下,UIP_URGDATA并沒有配置。代碼會進入到else分支,程序會跳過處理緊急指針數據,并修改uip_len的數值。程序在修改uip_len的時候并沒有判斷緊急指針的值,當uip_len的值特別小,而緊急指針的值urgp特別大時,就會引起整數溢出,導致設備重啟或者是越界讀寫。


圖片


2、CVE-2020-24338


該漏洞出現在picoTCP/IP協議棧中解析域名label的pico_dns_decompress_name()函數中,該函數具體實現如下代碼所示:


圖片


第95、96行初始化iterator,name指向待解壓縮的labels,dest_iterator指向存放解壓出來的labels的緩沖區,大小為256字節。第97行開始為while循環,讀取到字符串結尾空字節退出。第98行,通過iterator&0xC0判斷label類型,如果為壓縮label,則通過packet定位到普通label所在的位置,如果為普通label直接進入else代碼塊中,第107行,調用memcpy將普通label拷貝到dest_iterator中。我們知道dest_iterator緩沖區大小只有256字節,而while循環退出條件為讀到字符串結尾空字節,因此當name長度超過256字節時,導致dest_iterator緩沖區溢出。


3、CVE-2020-24336


該漏洞出現在contiki協議棧中的ip64_dns64_4to6()中,該函數功能是將ipv4類型的DNS數據包轉換成ipv6類型的DNS數據包,關鍵代碼如下:


圖片


遍歷Answer區段并更新到ipv6類型的Answer區段中。從第209行開始轉換資源記錄,具體實現代碼如下所示:


圖片


首先判斷TYPE是否是DNS_TYPE_A,DNS_TYPE_A表示該資源記錄為ipv4主機地址,然后將對應區段拷貝到acopy中。第220行,從資源記錄中直接取RDLENGTH,前文已介紹,該區段表征RDATA的長度。第227行,判斷len長度是否等于4,這里正常情況,len應該為4,因為ipv4地址長度為4個字節。如果len不等于4,則進入else語句中,直接調用memcpy進行RDATA數據拷貝。這里是存在問題的,Ipv4主機地址長度不等于4,并沒有驗證主機地址的合理性而且len最大為0xFFFF,直接拷貝可能導致緩沖區溢出。


4、CVE-2020-25111


在使用Nut/Net協議棧的設備中,NutDnsGetResourceAll()是處理DNS請求的函數,其中處理DNS答復的函數是DecodeDnsQuestion(),處理域標簽的函數是ScanName(),漏洞就出現在ScanName()函數中。如下圖所示,cp為指向域名第一個字節的指針(即第一個域標簽的長度字節),*npp為即將被解析的域名buffer,通過strlen()將整個域名長度賦值給rc,然后基于rc分配*npp buffer,之后通過一個while,循環處理每一個label。問題顯而易見,cp是攻擊者可控的,由此可以控制*npp的大小。而對于標簽的長度,即len變量,直接從數據包中得到,并沒有做任何邊界檢查,然后通過while循環處理。因此可以對len設置任意的值,即攻擊者對*npp buffer可控的長度。由此可以在堆中造成越界寫,這可導致遠程代碼執行(RCE)。


圖片


5、CVE-2020-17443


CVE-2020-17443存在于PicoTCP協議棧pico_icmp6.c文件中。問題代碼位于pico_icmp6_send_echoreply()函數中,該函數的主要功能是回復ICMPv6應答數據包以響應對端的ICMPv6Echo(ping)請求。


圖片


我們可以看到,第68行,replay結構的緩沖大小基于echo的報文中transport_len變量。在第84行,程序從echo->payload向reply->payload地址復制了長度為echo->transport_len- 8大小的數據。


注意,如果echo->transport_len小于 8,echo->transport_len - 8會導致整數溢出,memcpy操作會導致緩沖區溢出。


在PicoTCP協議棧攻擊者通過構造惡意的ICMPv6數據包,這個惡意的數據包ICMP報頭小于8,會導致設備重啟或拒絕服務。


漏洞驗證


漏洞驗證視頻請查看ADLab公眾號


參考鏈接:


[1] https://www.forescout.com/research-labs/amnesia33/[2]https://www.securityweek.com/amnesia33-vulnerabilities-tcpip-stacks-expose-millions-devices-attacks

[3] https://www.zdnet.com/article/amnesia33-vulnerabilities-impact-millions-of-smart-and-industrial-devices/

[4] https://tools.ietf.org/html/rfc1035

[5] https://us-cert.cisa.gov/ics/advisories/icsa-20-343-01


啟明星辰積極防御實驗室(ADLab)


ADLab成立于1999年,是中國安全行業最早成立的攻防技術研究實驗室之一,微軟MAPP計劃核心成員,“黑雀攻擊”概念首推者。截止目前,ADLab已通過CVE累計發布安全漏洞近1100個,通過 CNVD/CNNVD累計發布安全漏洞900余個,持續保持國際網絡安全領域一流水準。實驗室研究方向涵蓋操作系統與應用系統安全研究、移動智能終端安全研究、物聯網智能設備安全研究、Web安全研究、工控系統安全研究、云安全研究。研究成果應用于產品核心技術研究、國家重點科技項目攻關、專業安全服務等。


adlab.jpg