姜 斌,張 君
(1.杭州電子科技大學通信工程學院,浙江杭州310018;2.浙江省電子信息產(chǎn)品檢驗所,浙江 杭州310007)
隨著信息技術(shù)的飛速發(fā)展,信息安全事件已經(jīng)深入到人們生活的方方面面[1]。調(diào)查表明,在各類信息安全事件當中,惡意代碼是最重要的安全威脅之一[2]。惡意代碼要傳播,必須要進行幾個特定的操作,以最典型的病毒和木馬為例,其在傳播的過程中,必然要改寫其它可執(zhí)行文件,以達到感染的目的。因此,如果能有效檢測到病毒木馬對其它可執(zhí)行文件的篡改,則可以遏止病毒木馬的傳播過程。基于這種思想,本文提出了一種可執(zhí)行文件防篡改方法。這種方法的基本思想是:在任何一個可執(zhí)行文件運行之前,先檢查其是否被篡改。如果被篡改了,則說明該文件不可信,拒絕其執(zhí)行;如果沒有被篡改,則允許其執(zhí)行。由此達到防止被篡改的(惡意)軟件運行的目的。Linux平臺下的實驗結(jié)果表明達到了預期效果。
要實現(xiàn)可執(zhí)行文件防篡改架構(gòu),有兩個關(guān)鍵步驟:第一步,在任何一個可執(zhí)行文件運行之前,先捕獲其運行請求;第二步,在捕獲到運行請求之后,判定該文件是否被篡改。要實現(xiàn)第一步,可以采用鉤子機制。在Windows平臺下采用相應(yīng)的Hook函數(shù)即可,Linux平臺下,則可以通過Linux安全模塊(Linux Security Module,LSM)實現(xiàn);要實現(xiàn)第二步,只要計算可執(zhí)行文件的哈希值即可。如果可執(zhí)行文件的當前哈希值與該文件的預期哈希值是一致的,則說明文件沒有被篡改,是可信的;否則說明被篡改,是不可信的。
LSM是一個輕量級通用的訪問控制框架。它通過在內(nèi)核當中的特點位置增加檢測點,并在檢測點插入鉤子函數(shù)。這樣,當用戶需要施加額外的訪問控制的時候,可以改寫這些鉤子函數(shù),從而獲得安全增強[3]。一個訪問文件節(jié)點inode的訪問過程如圖1所示。在經(jīng)過了錯誤檢查、訪問控制DAC檢查之后,就在Linux內(nèi)核試圖對內(nèi)核對象進行訪問之前,LSM鉤子調(diào)用一個LSM模塊所提供的函數(shù)。該函數(shù)根據(jù)策略引擎進行判斷,要么允許此次訪問,要么拒絕訪問并強制返回一個錯誤。在LSM當中,對如下一些內(nèi)核對象插入了安全鉤子:任務(wù)鉤子、程序鉤子、文件系統(tǒng)鉤子、管道/文件/socket相關(guān)鉤子;文件操作鉤子;網(wǎng)絡(luò)數(shù)據(jù)包相關(guān)鉤子;網(wǎng)絡(luò)設(shè)備相關(guān)鉤子;信號量/共享內(nèi)存/消息隊列鉤子;單個消息鉤子等。可見,LSM的功能還是比較強大的。
圖1 LSM的掛鉤結(jié)構(gòu)(以文件訪問為例)
在LSM的基礎(chǔ)上,Linux平臺下可執(zhí)行文件防篡改架構(gòu)如圖2所示。
圖2 Linux平臺下可執(zhí)行文件防篡改架構(gòu)
整個架構(gòu)的工作流程是這樣的:(1)首先,某個可執(zhí)行文件被用戶運行;(2)LSM鉤子截獲到該文件的運行請求;(3)相應(yīng)的LSM鉤子函數(shù)被執(zhí)行。該函數(shù)將解析請求運行文件的詳細信息——包括絕對路徑文件名、參數(shù)等等;(4)根據(jù)步驟(3)當中獲取的可執(zhí)行文件絕對路徑文件名,計算該文件的當前哈希值;(5)獲取該文件的預期哈希值(通常保存在外部的U盤當中);(6)將文件的當前哈希值與預期哈希值相比較,如果兩者一致,則允許該可執(zhí)行文件的運行,否則拒絕其運行。
在圖2的架構(gòu)當中,為了截獲可執(zhí)行文件的運行請求,需要進行LSM鉤子設(shè)置,這是通過設(shè)置bprm_check_security函數(shù)鉤子實現(xiàn)的。bprm_check_security鉤子函數(shù)原型是:
int(*bprm_check_security)(struct linux_binprm*bprm)。其中,參數(shù)bprm包含了基本的linux_binprm結(jié)構(gòu)體信息,例如:要執(zhí)行的應(yīng)用程序的真實名稱、命令行參數(shù)信息等等。通過在LSM內(nèi)核模塊文件當中添加如下代碼,可以設(shè)置bprm_check_security鉤子:
static struct security_operations jetway_security_ops={.bprm_check_security=appprotec_check_security,};
這樣,任何時候當某個應(yīng)用程序開始運行之后,在Linux內(nèi)核調(diào)用實際的加載器加載其運行之前,會自動轉(zhuǎn)到定義的appprotec_check_security函數(shù)。appprotec_check_security首先根據(jù)參數(shù)“struct linux_binprm*bprm”獲取文件的相關(guān)信息,特別是其絕對路徑文件名、參數(shù)信息等,其中bprm->interp就給出了絕對路徑文件名;然后,內(nèi)核根據(jù)獲取的絕對路徑文件名打開相應(yīng)的文件,計算其哈希(MD5);最后,內(nèi)核從U盤讀取該文件的預期哈希:如果兩者不一致,則返回-1拒絕文件的運行;否則返回0允許其運行。
在圖2的架構(gòu)當中,進行哈希值比較的時候,需要從U盤讀取文件的預期哈希值。這就需要編寫特定的USB驅(qū)動。為什么不直接使用Linux自帶的USB驅(qū)動呢?這是因為:需要對U盤進行判定,只有是特定的U盤,才相信其存儲的預期哈希值,否則如果讀取任意U盤的話,那攻擊者完全可以偽造假的預期哈希值從而使得架構(gòu)失去作用。從U盤讀取預期哈希值的過程是:首先從內(nèi)核判定插入的U盤是不是允許的U盤(這可以通過id號,以及特殊扇區(qū)的特殊信息來保證),如果是允許的U盤,則讀取U盤內(nèi)部名為expectedhash的文件,并解析該文件獲取預期哈希值。
USB本身有4種傳輸方式:等時傳輸、中斷傳輸、控制傳輸和猝發(fā)傳輸。USB使用1ms的時間幀來傳輸數(shù)據(jù)。在每次傳輸之前,HC產(chǎn)生一個幀頭Start Of Frame。每次傳輸?shù)臅r候,如果有等時數(shù)據(jù)存在,則等時數(shù)據(jù)最先被傳輸。HCD需要確保:有足夠的時間用來完成所有的等時傳輸和中斷傳輸數(shù)據(jù),然后使用剩下的時間來完成控制傳輸和猝發(fā)傳輸數(shù)據(jù)[4]。根據(jù)上述USB驅(qū)動特點,就可以對USB驅(qū)動框架進行填寫,開發(fā)實際的USB驅(qū)動了。描述USB驅(qū)動程序的結(jié)構(gòu)體是系統(tǒng)定義的標準結(jié)構(gòu)struct usb_driver,在struct usb_driver中,name用來告訴內(nèi)核模塊的名字;probe和disconnect是函數(shù)指針,當設(shè)備與在id_table中的變量信息匹配時,函數(shù)被調(diào)用;id_table用來告訴內(nèi)核模塊支持的設(shè)備。更詳細的USB開發(fā)可以參見文獻4、5。
Linux Redhat內(nèi)核2.4上實現(xiàn)了一個原型系統(tǒng),構(gòu)造了一個名為appproect.ko的LSM驅(qū)動,在其中實現(xiàn)了int(*bprm_check_security)(struct linux_binprm*bprm)鉤子。在root權(quán)限下,使用“insmod appprotect.ko”加載的內(nèi)核,然后插入具有預期哈希信息的U盤。啟動/bin/ls,可以發(fā)現(xiàn),正常列出了文件和目錄信息;之后,使用編輯器更改/bin/ls當中任意位置的任意個字節(jié),再次運行,系統(tǒng)顯示“operation not permitted”。實驗達到了預期結(jié)果。
經(jīng)過多次實驗統(tǒng)計,系統(tǒng)引起約1%的額外負載,這主要是計算哈希值所引起的。不過,1%的負載對系統(tǒng)性能影響不大,可以接受,用戶幾乎感受不到時間的延遲。
首先需要指出的是,雖然本文在Linux平臺實現(xiàn)的原型系統(tǒng),但該架構(gòu)仍然可以應(yīng)用到Windows平臺上面。當應(yīng)用到Windows平臺時,其基本流程類似于Linux平臺(如圖2所示),唯一不同的是,Linux平臺采用LSM捕獲可執(zhí)行文件運行請求,而在Windows平臺下,可以通過設(shè)置Windows鉤子的方法來達到相同目的。要設(shè)置Windows鉤子,可以調(diào)用SetWindowsHookEx()函數(shù)。其次需要指出的是,本文提出的方法是在可執(zhí)行文件運行之前,先判定該文件是否已經(jīng)被篡改。也就是說,本文的方法并不能“阻止篡改”,而只能“發(fā)現(xiàn)篡改”,并在“發(fā)現(xiàn)篡改”之后,調(diào)用備份文件進行主動恢復,從而達到保護的目的。之所以不采用“阻止篡改”的方法,是由于采用“阻止篡改”的方法,就需要判定當執(zhí)行寫入操作時,執(zhí)行寫入的進程究竟是一個正常進程,還是一個病毒或者木馬進程,而這種判定從理論上是不可行的:因為不存在一個算法,能夠判定任意一個文件是否是病毒或者木馬?;谶@種原因,才采用了“發(fā)現(xiàn)篡改”的方法。注意到在架構(gòu)當中,任何一個可執(zhí)行文件在剛剛發(fā)出執(zhí)行請求,而并沒有創(chuàng)建進程實體之前,其完整性就被檢查了,因而這種方案不僅能夠發(fā)現(xiàn)對文件的篡改,而且能夠有效避免系統(tǒng)感染病毒或者木馬,保證了系統(tǒng)的安全性。
本文提出了一種可執(zhí)行文件防篡改框架,該框架在任何一個可執(zhí)行文件實際運行之前,先通過計算哈希值判定其是否被非法篡改。如果被篡改,則禁止其運行;否則允許其運行。本文以Linux平臺為基礎(chǔ),實現(xiàn)了一個原型系統(tǒng),達到了預期效果。下一步,該架構(gòu)可以進一步擴展,即:在可執(zhí)行文件進行完整性哈希比較時,針對指定的配置文件進行完整性比較。
[1] 國際計算機網(wǎng)絡(luò)應(yīng)急技術(shù)處理協(xié)調(diào)中心.CNCERT互聯(lián)網(wǎng)安全威脅報告[EB/OL].http://www.cert.org.cn/UserFiles/File/201101monthly.pdf,2011 -02 -01.
[2] 國際計算機網(wǎng)絡(luò)應(yīng)急技術(shù)處理協(xié)調(diào)中心.CNCERT互聯(lián)網(wǎng)安全威脅報告[EB/OL].http://www.cert.org.cn/UserFiles/File/201102monthly.pdf,2011 -03 -01.
[3] Wright C,Cowan C,Smalley S,et al.Linux Security Modules:General Security Support for the Linux Kernel[C].San Francisco:Proceedings of the 11thUSENIX Security Symposium,2002:1-14.
[4] Intel.Universal Host Controller Interface(UHCI)Design Guide [EB/OL].http://download.intel.com/technology/usb/UHCI11D.pdf,2011 -05 -31.
[5] Corbet J,Rubini A,Kroah-Hartman G.Linux Device Drivers(Third Edition)[M].O’Reilly Media Press:Cambridge Massachusetts,2005:10 -14,50 -64.