無處藏身的Use-after-Free/Double Free漏洞 —— Pinpoint檢測MySQL記
分享一篇最近源傘科技 @時清凱 研究員用我司Pinpoint源代碼分析器探索MySQL代碼漏洞的隨記。這是我們在自動化漏洞發現的道路上前進的又一小步。
--------------
MySQL 是目前最流行的開源關係型資料庫管理系統,據統計,其流行程度在2016年及2017年在數百種資料庫管理系統中以微弱的差距排名第二[1],其歷史悠久,至今已有573個發行版本以及眾多直接與間接貢獻者[2]。任何一個其中的軟體漏洞都將影響數億甚至更多人的生命財產安全。
Use-after-Free/Double Free是眾所周知的高危漏洞,根據研究者對CVE中Chromium browser漏洞統計,該種類型的漏洞數量遠遠超過堆棧溢出,並比其它漏洞類型更為危險:88%的Use-after-Free/Double Free被標記為極為關鍵和重要的安全漏洞[3]。然而,由於該類漏洞的複雜性,學術界與工業界對其沒有有效的(即精確又高效的)自動化檢測方法。
當世界最流行的開源關係型資料庫管理系統遇到如此危險的高危漏洞,又缺乏有效檢測工具時,其危險程度可想而知。況且,MySQL包含超過200萬行的C/C++代碼,精確的自動化分析困難:或分析及慢,遠遠超過一次nightly building的時間;或分析結果不精確,產生大量的誤報。我們的自動化檢測工具突破了困難,在1.5小時內完成了對MySQL Server的掃描,精準定位了其中兩個Use-after-Free/Double Free漏洞,並獲得了開發者的確認。
Bug#87200
如上圖所示,該bug的產生是由於開發者在第2750行調用my_free(buf)後,未重置buf為null造成的,這個釋放後的內存的指針,將從該函數返回,從而影響系統安全。
在於開發者討論過程中,開發者認為其在my_free函數中,對buf進行了特殊的操作,因此即使使用my_free(buf)後,buf的使用也是安全的。然而,MySQL提供了兩套my_free函數,分別針對不同的運行環境,其中一個my_free函數如下將會直接調用my_raw_free函數,my_raw_free函數直接調用free函數,沒有任何保護操作,因此開發者最終確認是一個真實的問題。
Bug#87203
相比上一個bug,該bug要複雜許多,其存在於一個長約1000行的函數之中,該bug也跨越了500餘行,數個複雜的循環結構。
如上圖所示,一個nonnull指針被釋放以後,由goto語句跳轉到write_buffers標記處,如下圖所示:
write_buffers處是一個loop循環,其中有多個異常處理代碼片段,會直接跳轉到func_exit標記處,其中將對再次對nonnull指針進行free操作。
該bug的複雜程度不僅可以從其跨越的代碼行數看出,從開發者的回復中也可見一斑,開發者如是說 「We did a lot of analysis…this remains as Not a Bug」。可想而知,即使在擁有精準的檢測工具的情形下,開發者仍然很難確認bug,難以想像,如果沒有這樣的檢測工具,這樣的漏洞會影響我們多久。當然,在與開發者交流的過程中,我們也發現了很多可以改進的地方,比如增加bug報告的可讀性,讓開發者更加相信自動化檢測工具的結果,實實在在的接受自動化檢測工具,而不是在第一時間否定bug的真實性。
[1] https://db-engines.com/en/ranking
[2] https://github.com/mysql/mysql-server
[3] Lee B, Song C, Jang Y, et al. Preventing Use-after-free
with Dangling Pointers Nullification[C]//NDSS. 2015.推薦閱讀:
※什麼是模糊測試:詩人、情報員和預言家(Defensics)
※漏洞提交級別說明
※漏洞挖掘高級方法
※做安全研究挖不到漏洞,很迷惘?
※安卓開發/反編譯工具中多存在嚴重漏洞