文/黃震
程序補丁是用于修復(fù)程序漏洞的通用方法。然而,用程序補丁來修復(fù)漏洞有一個經(jīng)常被忽略的缺陷——漏洞尚未修復(fù)窗口(pre-patch window),即從一個漏洞被發(fā)現(xiàn)到其相應(yīng)的補丁發(fā)布之間的時間窗。在漏洞尚未修復(fù)窗口,攻擊者可以針對漏洞發(fā)起攻擊。漏洞尚未修復(fù)窗口的存在是因為程序員手工分析漏洞、編制和測試程序補丁需要一定的時間。盡管有大量研究致力于程序補丁的自動生成技術(shù),目前此技術(shù)仍未被實際使用。文章作者通過對131 個最近公開的程序漏洞和相應(yīng)的補丁進行分析,發(fā)現(xiàn)漏洞尚未修復(fù)窗口平均長達52 天。而且由于分析漏洞和編制程序補丁有一定的復(fù)雜性,總體來說漏洞尚未修復(fù)窗口很難人工縮短。即使軟件開發(fā)商可以對其已知但尚未修復(fù)的程序漏洞進行保密,來降低這些漏洞被惡意利用(exploit)的風險,呈出不窮的零日漏洞仍然可以被攻擊者使用[1][2]。
為了解決使用程序補丁來修復(fù)漏洞的這一個缺陷,軟件用戶經(jīng)常使用“程序漏洞臨時解決方案”(configuration workaround)來暫時防止程序漏洞在修復(fù)前被惡意利用。程序漏洞臨時解決方案通過直接讓用戶修改與漏洞代碼相關(guān)的程序配置參數(shù)來禁止執(zhí)行含有漏洞的代碼。舉例而言,具有嚴重危害的Android Stagefright漏洞在2015 年被發(fā)現(xiàn),有超過十億的智能移動設(shè)備受到其影響。雖然這個漏洞在當年4 月就被發(fā)現(xiàn),相應(yīng)的補丁直到8 月仍未發(fā)布。幸運的是,通過修改Android MMS 客戶端的配置來禁止自動下載短信圖片,用戶可以防止此漏洞被惡意短信攻擊。使用程序漏洞臨時解決方案,用戶可以犧牲少許的程序功能來換取對嚴重漏洞的保護。所以一些知名軟件開發(fā)商如Microsoft 會在發(fā)布補丁前公開程序漏洞臨時解決方案[3][4],如果相應(yīng)的漏洞有對應(yīng)的程序漏洞臨時解決方案,以保護程序用戶不受針對漏洞的攻擊。然而程序配置參數(shù)是設(shè)計用于讓用戶靈活調(diào)整程序的功能行為,而非提供安全保護,所以絕大多數(shù)漏洞并無與之對應(yīng)的程序漏洞臨時解決方案。
受到程序漏洞臨時解決方案的啟發(fā),作者提出快速漏洞屏蔽方案SWRR(Security Workarounds for Rapid Response)來縮小或消除漏洞尚未修復(fù)窗口[2]。SWRR 可以被自動生成為大部分漏洞提供臨時解決方案。設(shè)計SWRR 的一個主要難題是怎樣讓SWRR 適用于還未發(fā)現(xiàn)的漏洞。因為事先并不知道漏洞在何處,SWRR 必須適用于任何潛在的漏洞。另外一個難題是漏洞可能和任何類型的程序功能相關(guān) ,出現(xiàn)在程序代碼里的任何一個位置。而每個SWRR 應(yīng)該確保程序在應(yīng)用這個SWRR 之后仍然能夠繼續(xù)運行。因此,作者在設(shè)計SWRR 時著重考慮簡單性、通用性、和非介入性(unobtrusiveness),而不依賴于任何關(guān)于目標程序本身和漏洞的假設(shè)。其中非介入性是指不影響目標程序的主要功能。
讓SWRR 通用性強和具有非介入性的關(guān)鍵點是利用目標程序自身的出錯處理代碼(error-handling code),因為出錯處理代碼的設(shè)計目的就是讓程序在意外錯誤發(fā)生之后能恢復(fù)正常、繼續(xù)運行。基于此關(guān)鍵點,作者設(shè)計并開發(fā)了Talos 解決方案[2]。Talos 使用靜態(tài)程序分析來識別目標程序已有的出錯處理代碼,自動生成SWRR 并添加SWRR 到目標程序。一旦某個漏洞即將被利用,與此漏洞相應(yīng)的SWRR 就改變程序執(zhí)行流程去調(diào)用出錯處理代碼,來防止漏洞被利用,從而屏蔽這個漏洞。使用Talos,軟件開發(fā)人員可以將SWRR 在軟件開發(fā)階段直接植入程序,或以補丁形式針對特定漏洞來發(fā)布。如圖 1 所示,這種植入式的SWRR 可以讓用戶修改配置參數(shù)來動態(tài)啟動或關(guān)閉用戶指定的SWRR。

圖1 植入式SWRR
Talos 使用創(chuàng)新的啟發(fā)式規(guī)則(heuristics),通過靜態(tài)程序分析來識別出錯處理代碼。這些啟發(fā)式規(guī)則有以下四個。
第一,錯誤記錄函數(shù)(error-logging function):當應(yīng)用程序遭遇錯誤時,經(jīng)常會調(diào)用錯誤記錄函數(shù)來記錄與錯誤相關(guān)的信息。通過識別程序?qū)﹀e誤記錄函數(shù)的調(diào)用(如圖1 所示),Talos 可以發(fā)現(xiàn)出錯處理代碼。
第二, NULL 返回值:如果沒能發(fā)現(xiàn)對出錯記錄函數(shù)的調(diào)用,Talos 會查看目標函數(shù)的返回值類型是否是指針類型。通常一個返回值為指針類型的函數(shù)會返回NULL來向其調(diào)用者指明有錯誤發(fā)生。

圖2 出錯處理代碼調(diào)用出錯記錄函數(shù)
第三,錯誤傳遞:很多時候一個函數(shù)會使用其調(diào)用另一函數(shù)的返回值作為自己的返回值,這就相當于是把錯誤沿著調(diào)用鏈(call chain)向上傳遞。這種出錯傳遞有三種方式:直接使用、轉(zhuǎn)換后上傳、和轉(zhuǎn)換后下傳。Talos 可以識別所有這三種錯誤傳遞方式。
第四,間接保護:如果一個函數(shù)的所有調(diào)用者都可以被SWRR 保護,Talos 可以通過植入在這些調(diào)用者里的SWRR 來保護這個函數(shù)。
Talos 是基于LLVM[5]開發(fā)的,可以自動識別用C/C++編寫的目標程序中的出錯處理代碼,生成SWRR,以及將SWRR 植入目標程序。作者團隊評估了SWRR 的安全性、有效覆蓋率、和性能開銷。
第一,為了評估SWRR 的安全性,作者測試了SWRR 是否能成功保護五個流行應(yīng)用軟件中的11 個實際的程序漏洞。這五個應(yīng)用軟件包括web server,web cache/proxy,ftp server,和database engine,平均含有95176 行程序源代碼和1349 個函數(shù)。通過詳細分析這11 個漏洞和Talos 為它們生成和植入的SWRR,作者發(fā)現(xiàn)這些SWRR 能夠成功屏蔽這些漏洞,而且絕大多數(shù)SWRR 具有非介入性。
第二,為了評估SWRR 的有效覆蓋率,作者測試Talos 能在這5 個應(yīng)用軟件中的多少個函數(shù)里識別出錯處理代碼,和可以用SWRR 來保護其中多少個函數(shù)。結(jié)果顯示平均而言Talos 生成的SWRR 能為75%的函數(shù)提供保護。而在這些SWRR 中,71%具有非介入性。總體而言,SWRR 能夠比現(xiàn)有的程序漏洞臨時解決方案提供多達兩倍的有效覆蓋率。
第三,作者測試了植入的SWRR 帶來的性能開銷。平均而言,SWRR 增加了1.3%的運行開銷。
在此項目中,作者提出了SWRR 的概念來縮短或消除漏洞尚未修復(fù)窗口 ,并設(shè)計實現(xiàn)了Talos,一個可以自動生成和植入SWRR到應(yīng)用軟件源代碼的工具。作者已經(jīng)開源了Talos的代碼[6]。Talos 使用新穎的啟發(fā)式規(guī)則,通過靜態(tài)程序分析來識別目標程序中已有的錯誤處理代碼,以用于生成SWRR。作者將Talos 應(yīng)用于5 個流行應(yīng)用軟件,結(jié)果發(fā)現(xiàn)SWRR 能夠屏蔽75%的潛在程序漏洞。這表明SWRR 的有效覆蓋率是用戶常用的程序漏洞臨時解決方案的兩倍。通過用這五個軟件中的11 個實際程序漏洞來測試SWRR,作者發(fā)現(xiàn)所有這些漏洞都能被SWRR 成功屏蔽,其中8 個SWRR 不影響除與漏洞直接相關(guān)的代碼外的軟件全部功能或主要功能。