CVE-2020-10611:在 TRIANGLE MICROWORKS SCADA 數據網關上實現代碼執行
DNP3簡介
如果您不是ICS / SCADA系統的普通用戶,則可能不熟悉分布式網絡協議3(DNP3)通信協議集。DNP3主要用于SCADA主站,遠程終端單元(RTU)和智能電氣設備(IED)之間的通信。它的采用主要是在公用事業領域,包括電力和水。它提供了豐富的功能集,包括數據分段,錯誤檢查和通用數據類型,這使該協議比舊的ICS協議更強大。相對于網絡的OSI模型,DNP3定義了第2層(數據鏈路)協議。該協議還定義了類似于OSI層4的傳輸層和類似于OSI層7的應用層。
GTWLib.dll庫中有兩個漏洞可用于利用該服務。
錯誤1:公開未初始化的內存
當報告給定類型的DNP3數據集描述符元素的數據時,首先將給定元素的值添加到輸出緩沖區。然后,將輸出緩沖區光標增加一個用戶指定的最大大小值。不會檢查max-size值,以確保對于給定類型來說max-size值不會太大。設置類型UINT(類型代碼:2)的元素的最大尺寸字段時,輸出值尺寸為恒定尺寸4,而輸出緩沖區光標仍按用戶定義的最大尺寸遞增。隨著完整的輸出緩沖區在響應中發送,這將泄漏比向請求實體添加到輸出緩沖區更多的數據。
結合沒有將輸出緩沖區初始化為常量值(malloc使用)的事實,這導致公開了與分配的緩沖區相對應的內存的先前內容。
錯誤2:更新數據集原型時的類型混淆
數據集描述符允許用戶定義自定義數據類型。為了允許類型重用,DNP3標準允許數據集描述符合并數據集原型。數據集原型定義了一個由原始數據類型列表組成的子類型。數據集描述符可以包含對數據集原型的引用,以合并嵌入式數據結構。
修改數據集元素的內容時,其內容將根據存儲在基礎數據集中的類型進行更新。但是,不會檢查以確定元素的類型在上一次修改和當前修改之間是否已更改。值更新時,其當前值被視為存儲在基礎數據集原型中的值。
當字符串(類型代碼為5的OSTR類型)被更新時,將檢查是否已經分配了緩沖區來保存字符串的內容。如果存在指向緩沖區的指針,realloc則用于修改分配以適應新要求的大小。
在以下一系列交互中:
1-創建數據集原型以指定雙 精度值(FLT類型代碼4和大小8)
2-使用原型創建數據集描述符
3-將數據集描述符的float元素的當前值設置為0x9090909090909090
4 -將原型成員的類型更改為OSTR
5-修改現值
用戶控制的值被視為指針,然后將其重新分配給用戶控制的大小。這導致了觸發任意的原語realloc:
realloc(controlled_ptr, controlled_size)
where 1 <= controlled_size <= 0x100.
開發
指針泄漏
DNP3輸出緩沖區的分配大小可以配置,默認大小為0x800。如果攻擊者可以控制0x800大小的緩沖區中先前包含的數據,則可以使用Bug 1(如上所述)泄漏該緩沖區中的大多數字節。
當匯總來自數據集描述符的“當前值”時,將分配一個表示當前值的0x28大小的項目數組。根據基礎數據集元素的類型,指針可以駐留在項目中。
通過創建具有51個元素的數據集描述符,0x33*0x28==0x7f8當為所請求的當前值提供答案時,將分配的緩沖區。如果輸出緩沖區的分配回收了以前包含此數據項數組的緩沖區,則指向用戶控制的數據的指針將泄漏。
內存損壞
使用針對錯誤2所述的技術并了解指針泄漏帶來的受控指針,攻擊者可以制作指針并觸發這些緩沖區的重分配以創建懸空指針。這允許從現在釋放的緩沖區中讀取值。緩沖區被另一個對象回收后,攻擊者可以使用相同的技術再次分配該緩沖區。攻擊者可以使用懸空指針重復泄漏緩沖區內存的內容。
使用懸掛指針從已知對象中泄漏數據還可以通過函數指針和vptrs揭示DLL的基地址。
首先,攻擊者釋放了他們在先前步驟中泄漏的緩沖區之一的內容。然后,它們觸發相同大小的分配。接下來,他們用假對象填充分配。至此,他們已經用有效載荷回收了該對象。最后,觸發類型混淆條件以劫持控制流。
在這種情況下使用的受害對象類型是保存數據集原型本身的數據收集類。
利用緩解措施
至于漏洞利用緩解措施,指針泄漏會繞過ASLR,并且在此二進制文件中未啟用CFG。其他緩解措施在此UAF方案中不相關。
結論
Triangle MicroWorks將這些錯誤修補為 CVE-2020-10611 和 CVE-2020-10613。您還可以在ICS-CERT咨詢ICSA-20-105-03上引用這些錯誤 。該修復程序的一部分包括在網關中禁用數據集。再次感謝Tobias Scharnowski,Niklas Breitfeld和Ali Abbasi提供了本文所包含的許多信息。他們的DNP3攻擊演示當然是Pwn2Own Miami的亮點,我們希望在未來的比賽中能看到他們。