【缺陷周話】第11期:釋放後使用(UAF)
1、釋放後使用
當動態分配的記憶體釋放時,該記憶體的內容是不確定的,有可能保持完整並可以被訪問,因為什麼時候重新分配或回收釋放的記憶體塊是記憶體管理程式決定的,但是,也可能該記憶體的內容已經被改變,導致意外的程式行為。因此,當記憶體釋放之後,保證不再對它進行寫入或讀取。詳細請參見 CWE ID 416: Use After Free。
2、 釋放後使用的危害
由記憶體管理不當導致的問題是 C/C++ 程式中常見的漏洞。釋放後使用會導致可被利用的潛在風險,包括程式異常終止、任意程式碼執行和拒絕服務攻擊等。2018年1月至11月,CVE 中共有134條漏洞資訊與其相關。部分漏洞如下:
CVE | 漏洞概述 |
---|---|
CVE-2018-1000051 | Artifex Mupdf 版本的 fz_keep_key_storable 中存在一個釋放後使用漏洞,可導致拒絕服務或程式碼執行問題。通過誘騙受害者開啟一個特殊構造的 PDF 檔案,該漏洞即可遭利用。 |
CVE-2018-17474 | 谷歌 Chrome 瀏覽器70.0.3538.67 之前版本 Blink 引擎的 HTMLImportsController 中存在一個釋放後使用漏洞,很有可能導致遠端攻擊者通過一個特殊構造的 HTML 頁面利用堆損壞問題。 |
CVE-2018-15924 | Adobe Acrobat 和 Reader 2018.011.20063及之前版本、2017.011.30102 及之前版本、2015.006.30452 及之前版本中存在釋放後使用漏洞。遠端攻擊者可利用該漏洞執行任意程式碼。 |
3、示例程式碼
示例源於 Samate Juliet TestSuite for C/C++ v1.3 (https://samate.nist.gov/SARD/testsuite.php),原始檔名:CWE416_Use_After_Free__malloc_free_char_01.c。
3.1缺陷程式碼
在示例程式碼中,在第29行使用 malloc() 進行記憶體分配,並在第35行使用 free() 對分配的記憶體進行了釋放,當在第37行對已經釋放的記憶體進行讀取時,導致釋放後使用問題。
使用360程式碼衛士對上述示例程式碼進行檢測,可以檢出“釋放後使用”缺陷,顯示等級為高。如圖1所示:
圖1:釋放後使用檢測示例
3.2 修復程式碼
在上述修復程式碼中,Samate 給出的修復方式為:在第30行使用 malloc()進行記憶體分配,並在第36行處使用 free() 進行釋放,釋放後不在對該記憶體進行其他操作。
使用360程式碼衛士對修復後的程式碼進行檢測,可以看到已不存在“釋放後使用”缺陷。如圖2:
圖2:修復後檢測結果
4 、如何避免釋放後使用
要避免釋放後使用,需要注意以下幾點:
(1) 釋放記憶體時請務必置空指標,雖然這種方法針對多重或複雜資料結構利用的有效性有限,但可以從一定程度上規避一部分問題。 (2) 在迴圈語句中進行記憶體分配或釋放時,需謹慎確認是否存在問題。 (3) 使用原始碼靜態分析工具進行自動化的檢測,可以有效的發現原始碼中的釋放後使用問題。