崔曉龍, 簡川杰, 劉 欣, 張 敏
(北京科技大學(xué)計算機(jī)與通信工程學(xué)院,北京 100083)
隨著計算機(jī)應(yīng)用的發(fā)展和普及,人們越來越多地利用計算機(jī)來存儲和處理各種數(shù)據(jù),其中不乏大量的敏感數(shù)據(jù),惡意獲取這些數(shù)據(jù)將對安全造成極大的威脅?;ヂ?lián)網(wǎng)上惡意應(yīng)用程序數(shù)量每年都在快速增長,由惡意軟件引起的本地感染已經(jīng)達(dá)到了相當(dāng)龐大的數(shù)量并呈現(xiàn)逐年上升的態(tài)勢,黑客通常將惡意應(yīng)用程序偽裝為普通應(yīng)用程序,將其發(fā)布到網(wǎng)絡(luò)上,欺騙計算機(jī)用戶偶然在本地下載和執(zhí)行這些應(yīng)用程序,給黑客獲得未經(jīng)授權(quán)訪問高權(quán)限系統(tǒng)資源的機(jī)會,并獲取或操縱存儲在用戶計算機(jī)上的敏感數(shù)據(jù)。
計算機(jī)系統(tǒng)面臨不同種類惡意程序或代碼的威脅,沙箱技術(shù)將為解決這類問題提供一種可行性方案。將網(wǎng)絡(luò)上安全性未知的程序運(yùn)行在一個虛擬空間,該虛擬空間與真實系統(tǒng)環(huán)境類似,同時將未知程序和真實環(huán)境隔離,如果在程序運(yùn)行過程中發(fā)現(xiàn)異常,則認(rèn)為該未知程序是惡意程序,將該程序標(biāo)志下來后,對運(yùn)行環(huán)境進(jìn)行回滾操作以恢復(fù)到原來的狀態(tài),這樣,無論病毒或者惡意程序如何運(yùn)行,都無法對實際系統(tǒng)造成損害和威脅[1]。在沙箱運(yùn)行過程中,用戶希望沙箱所占用的額外開銷盡可能地小,這樣用戶將感受不到沙箱的存在。
早期的一些沙箱機(jī)制并不存在于Linux 系統(tǒng)中,比如Janus和Mapbox都是出現(xiàn)在Solaris系統(tǒng)上,它們都為Linux 上的沙箱機(jī)制提供了一些可借鑒的思路[2]。
Janus是最早基于系統(tǒng)調(diào)用插入的沙箱機(jī)制之一,當(dāng)調(diào)用要檢查的系統(tǒng)時,Janus將跟蹤進(jìn)程置于休眠狀態(tài)并檢查其配置文件(也可以稱為安全策略),以決定是否允許當(dāng)前系統(tǒng)調(diào)用。Janus 和本文實現(xiàn)的工具之間存在根本性差異,它在Solaris 操作系統(tǒng)中使用proc接口實現(xiàn),因為ptrace系統(tǒng)調(diào)用易受競爭條件的影響,并且在使用ptrace時中止系統(tǒng)調(diào)用很麻煩;另外,對于所有進(jìn)程只有一個安全配置文件,用戶僅能建立一個全局安全策略;Janus不會解析相關(guān)路徑并相應(yīng)地檢查系統(tǒng)調(diào)用,而是中止所有試圖使用相對路徑訪問資源的系統(tǒng)調(diào)用[3]。
Bluebox使用系統(tǒng)調(diào)用插入來捕獲系統(tǒng)調(diào)用,通過使用ptrace接口強(qiáng)制執(zhí)行以前指定的安全規(guī)則。它不允許用戶通過圖形界面交互生成安全策略,使用預(yù)先設(shè)置的靜態(tài)安全策略,這樣用戶就不能恢復(fù)由不良靜態(tài)策略所造成的結(jié)果[4]。
Mapbox是一個基于系統(tǒng)調(diào)用插入的工具,它在指定和執(zhí)行安全規(guī)則方面的工作方式截然不同。它是為Solaris操作系統(tǒng)實現(xiàn)的,它利用Solaris操作系統(tǒng)的系統(tǒng)調(diào)用攔截接口(proc)來跟蹤和操作系統(tǒng)調(diào)用[5]。Mapbox不是為不同的流程提供策略文件,而是對許多應(yīng)用程序的行為進(jìn)行分類,并將類似的應(yīng)用程序行為分組在一起,以便根據(jù)它們的預(yù)期功能對每類應(yīng)用程序?qū)嵤┌踩?guī)則。當(dāng)計劃使用Mapbox 運(yùn)行程序時,用戶配置策略文件并為目標(biāo)程序分配一個或多個行為類,這些行為類指定目標(biāo)程序可以訪問哪些系統(tǒng)資源[6]。例如,目標(biāo)應(yīng)用程序在Mapbox 中標(biāo)記了reader,則意味著它只能讀取指定的某些文件,并不能執(zhí)行任何寫入操作或網(wǎng)絡(luò)操作。
SELinux是Linux中強(qiáng)制訪問控制安全模塊,它與Linux 內(nèi)核集成,如Ubuntu 或Red Hat Enterprise。SELinux主要作用就是最大限度地減小系統(tǒng)中服務(wù)進(jìn)程可訪問的資源(最小權(quán)限原則),如果用戶不希望在任何時候運(yùn)行SELinux,那么每次想要運(yùn)行沙箱應(yīng)用程序時,在系統(tǒng)啟用和禁用SELinux 都會很麻煩。此外,對于臨時系統(tǒng)用戶配置ACL策略通常很困難。它不允許以交互方式生成安全策略,不能為用戶提供跟蹤應(yīng)用程序活動或詳細(xì)日志記錄以進(jìn)行執(zhí)行后的分析[7]。
Seccomp機(jī)制用于限制應(yīng)用程序可使用系統(tǒng)調(diào)用,增加系統(tǒng)的安全性。啟用了Seccomp模式,則目標(biāo)進(jìn)程將在其功能非常有限的安全狀態(tài)下運(yùn)行。Seccomp是一種可擴(kuò)展的工具,可以白名單形式過濾系統(tǒng)調(diào)用,性能上也較好[8]。
用戶直接在操作系統(tǒng)運(yùn)行未知程序是一個相當(dāng)危險的操作,存在系統(tǒng)資源惡意被消耗的風(fēng)險,考慮惡意程序在運(yùn)行過程中的特點,沙箱主要功能設(shè)計如圖1所示。
圖1 沙箱主要功能設(shè)計
作為一款安全工具,沙箱應(yīng)該具有以下特性:異常行為和(或)系統(tǒng)入侵檢測、富有表現(xiàn)力的安全策略、交互式安全策略生成、易用性、用于執(zhí)行后分析的日志記錄功能。
沙箱要實現(xiàn)的功能:
(1)限制未知程序的運(yùn)行時間。
(2)限制未知程序的運(yùn)行內(nèi)存。
(3)及時了解程序的運(yùn)行狀態(tài)。
(4)阻止未知程序運(yùn)行時出現(xiàn)危險操作。
程序運(yùn)行時間分為用戶可感知的程序運(yùn)行時間和程序所實際占用的CPU 時間。之所以存在兩種不同的時間是因為用戶使用的操作系統(tǒng)大多數(shù)是分時多任務(wù)操作系統(tǒng),盡管目前大多數(shù)系統(tǒng)都是多核心CPU,但目前只考慮單核心CPU這種簡單的情況,大多情況下這種操作系統(tǒng)內(nèi)的進(jìn)程并不是一下就運(yùn)行完成的,可能存在被進(jìn)程調(diào)度的情況,因為任意時刻只可能存在一個正在運(yùn)行的進(jìn)程,其他進(jìn)程就需要等待,所以一個進(jìn)程的實際運(yùn)行時間可能會大于該進(jìn)程占用CPU運(yùn)行的時間。在限制程序的運(yùn)行時間時需要清楚限制的是程序運(yùn)行的實際時間還是程序運(yùn)行所占用的CPU時間。
給沙箱運(yùn)行的程序設(shè)置一個較寬松的運(yùn)行時間,以確保程序可正常運(yùn)行又不讓惡意程序有占用較多的系統(tǒng)資源的機(jī)會。
進(jìn)程實際運(yùn)行所占用的物理內(nèi)存包含進(jìn)程使用系統(tǒng)提供的動態(tài)鏈接庫部分的內(nèi)存,把所有的進(jìn)程實際占用的物理內(nèi)存加起來可能會超過機(jī)器的實際物理內(nèi)存。在對內(nèi)存進(jìn)行限制的時候,可根據(jù)自身系統(tǒng)情況考慮一個限制沙箱內(nèi)程序使用的內(nèi)存值,確保程序能夠正常運(yùn)行又不至于消耗過多的系統(tǒng)資源。
沙箱需要能監(jiān)控其中運(yùn)行的未知程序的行為,對未知程序進(jìn)程狀態(tài)進(jìn)行跟蹤,需要了解進(jìn)程到底是運(yùn)行結(jié)束成功返回還是由于資源限制而導(dǎo)致進(jìn)程提前結(jié)束,或者是進(jìn)程要調(diào)用某個沙箱限制了的系統(tǒng)調(diào)用而被提前結(jié)束,這些行為都應(yīng)該由沙箱監(jiān)控,這就要對進(jìn)程和資源進(jìn)行監(jiān)控,并且記錄進(jìn)程結(jié)束時候的返回值。
沙箱中進(jìn)程的資源限制可以通過對進(jìn)程的CPU占用時間和進(jìn)程內(nèi)存占用的限制來實現(xiàn),而安全性限制需通過限制系統(tǒng)調(diào)用來進(jìn)行。一些危險、常見可執(zhí)行系統(tǒng)命令函數(shù)如remove、system 等以及網(wǎng)絡(luò)通信操作相關(guān)函數(shù)都需進(jìn)行限制,否則有可能導(dǎo)致系統(tǒng)的關(guān)鍵信息泄露,這些都可以通過使用Seccomp 限制相關(guān)的系統(tǒng)調(diào)用來實現(xiàn)。
沙箱接受通過命令行傳入未知來源的程序路徑作為參數(shù),并在加載指定的安全策略之后,開始嘗試運(yùn)行該未知來源的程序。沙箱主要工作流程如圖2 所示。
圖2 沙箱工作流程圖
沙箱安全機(jī)制是沙箱最重要的功能,通過過濾系統(tǒng)調(diào)用來實現(xiàn)。系統(tǒng)調(diào)用是操作系統(tǒng)實現(xiàn)并提供給用戶來讓用戶能夠?qū)Φ讓佑布崿F(xiàn)控制的一種編程接口[9]。當(dāng)一個進(jìn)程要調(diào)用系統(tǒng)的時候,操作系統(tǒng)會把相關(guān)參數(shù)放到CPU的寄存器中,比如系統(tǒng)調(diào)用號存在EAX寄存器中,EBX、ECX 和EDX 再分別存放一些其他的參數(shù),調(diào)用軟中斷(int 0x80),讓CPU切換到內(nèi)核態(tài)并開始執(zhí)行對應(yīng)的內(nèi)核函數(shù)。
3.2.1 限制系統(tǒng)調(diào)用
Seccomp調(diào)用之后會作用于整個父進(jìn)程和fork出來的子進(jìn)程,只有在加載Seccomp的策略之后,沙箱才開始fork父進(jìn)程執(zhí)行未知程序。實現(xiàn)本沙箱時采用的是在加載Seccomp策略之后執(zhí)行execve函數(shù)去執(zhí)行未知程序,這個順序也是Seccomp的安全策略所要求的。因為后面執(zhí)行程序需要使用到execve 這個系統(tǒng)調(diào)用,所以Seccomp也不能完全限制了execve 系統(tǒng)調(diào)用,本沙箱選擇對execve 系統(tǒng)調(diào)用進(jìn)行參數(shù)的過濾,以此來限制execve[10]。
3.2.2 加載Seccomp
Seccomp是一種侵入式的加載策略,如果程序已經(jīng)執(zhí)行結(jié)束之后再加載Seccomp 策略毫無意義,所以應(yīng)該在execve之前加載Seccomp。由于Seccomp 采用白名單加載策略,如果execve 在Seccomp 之后的話就需要把Seccomp也加入系統(tǒng)調(diào)用的白名單里面,但是execve是一個很危險的系統(tǒng)調(diào)用,如果不加以限制那這很明顯是一個“繞過”[11]。Seccomp 可對系統(tǒng)調(diào)用的參數(shù)進(jìn)行限制,通過對execve 系統(tǒng)調(diào)用的傳入?yún)?shù)進(jìn)行一定的限制,只能執(zhí)行沙箱所限制的文件路徑的文件。如圖3 所示,在加載Seccomp 策略的函數(shù)Seccomp_rule_add,第2 個參數(shù)不滿足策略的進(jìn)程直接被kill掉;第3 個參數(shù)過濾的系統(tǒng)調(diào)用是execve;第4個參數(shù)需要過濾幾個參數(shù),“1”表示只過濾1 個參數(shù);后面的參數(shù)則是需要過濾的參數(shù),如果第4 個參數(shù)為“1”,則表示有1 個需要過濾的參數(shù),圖3 中是execve系統(tǒng)調(diào)用的第1 個參數(shù)被過濾。
圖3 限制execve系統(tǒng)調(diào)用參數(shù)流程圖
3.2.3 白名單機(jī)制
完成了加載Seccomp 時機(jī)的設(shè)計,要設(shè)計加載Seccomp時需要考慮哪些系統(tǒng)調(diào)用。對一些常見程序用strace 命令進(jìn)行分析,得出如表1 所示的系統(tǒng)調(diào)用的白名單[12]。
表1 系統(tǒng)調(diào)用白名單
除了execve系統(tǒng)調(diào)用需要過濾參數(shù),write系統(tǒng)調(diào)用也要進(jìn)行參數(shù)的過濾。write系統(tǒng)調(diào)用中有一個參數(shù)是用來表示寫入的文件描述符,該參數(shù)為“0”“1”和“2”的時候,分別表示stdin、stdout 和stderr,大于3 表示某個已打開文件的文件描述符的值。之所以要限制write系統(tǒng)調(diào)用,是因為沙箱需要防止沙箱中的進(jìn)程任意寫文件,該操作是危險的。如圖4 所示,和前面類似,這里限制了write系統(tǒng)調(diào)用的第1 個參數(shù)要小于等于2,即限制文件描述只能使用標(biāo)準(zhǔn)的輸入(stdin)和輸出(stdout)。
圖4 限制write系統(tǒng)調(diào)用參數(shù)流程圖
3.2.4 權(quán)限控制機(jī)制
Linux訪問控制權(quán)限分為3 組,分別為user、group和others。user是對文件所有者設(shè)定的權(quán)限;group 是對文件所屬組下面用戶設(shè)定的權(quán)限;others 是對既不是文件所有者也不是文件所屬組下面的用戶設(shè)定的權(quán)限。其中root用戶的權(quán)限是最高的,其他用戶的權(quán)限是可以劃分的。Linux下一切皆文件,所以進(jìn)程同樣也是有權(quán)限劃分的,每個用戶都有一個UID 的值,文件組也有一個GID的值,一個運(yùn)行中的進(jìn)程在運(yùn)行時會有UID和GID的值來標(biāo)識,進(jìn)程中也可以調(diào)用setuid和setgid函數(shù)分別來改變當(dāng)前進(jìn)程的UID 和GID 值,不過調(diào)用這兩個函數(shù)首先需要有root用戶的權(quán)限。如圖5 所示,沙箱采用了NOBODY 用戶的GID 和UID,這是權(quán)限非常低的用戶,采用這個用戶來運(yùn)行沙箱進(jìn)程,可以進(jìn)一步避免在沙箱中運(yùn)行未知程序帶來的危害。
圖5 設(shè)置進(jìn)程UID和GID流程圖
在Ubuntu18.04 對沙箱進(jìn)行安全和性能兩方面的測試:安全測試主要包含2 個程序,一個正常的安全程序和一個存在惡意系統(tǒng)調(diào)用的程序,分別運(yùn)行在操作系統(tǒng)和沙箱中進(jìn)行對比;性能測試選擇一個特殊的測試程序,即一個存在大量系統(tǒng)調(diào)用的程序,分別運(yùn)行在本沙箱、其他沙箱和直接運(yùn)行在操作系統(tǒng)中進(jìn)行時間的對比。
對安全性的測試,用一個正常的測試程序和一個包含惡意代碼的程序分別在操作系統(tǒng)上直接運(yùn)行和通過沙箱運(yùn)行來進(jìn)行對比。
將正常測試程序直接運(yùn)行在操作系統(tǒng)和沙箱,正常程序在操作系統(tǒng)環(huán)境和沙箱環(huán)境中均能正常的運(yùn)行。正常程序直接在操作系統(tǒng)中運(yùn)行效果如圖6所示。
圖6 正常測試程序直接運(yùn)行
在沙箱環(huán)境中運(yùn)行效果如圖7 所示,說明沙箱對操作系統(tǒng)運(yùn)行正常程序進(jìn)行了較好的模擬。
圖7 正常測試程序在沙箱中運(yùn)行
將包含惡意代碼的程序在操作系統(tǒng)中運(yùn)行,可以發(fā)現(xiàn)該惡意程序代碼運(yùn)行成功,并獲取機(jī)器的shell,運(yùn)行效果如圖8 所示。
圖8 包含惡意代碼的程序直接運(yùn)行
將包含惡意代碼的程序運(yùn)行在沙箱之中,可見,惡意程序被檢測出來,隨后進(jìn)程停止運(yùn)行,運(yùn)行效果如圖9 所示,沙箱環(huán)境達(dá)到了發(fā)現(xiàn)惡意程序并中止進(jìn)程的效果。
圖9 包含惡意代碼的程序在沙箱中運(yùn)行
通過對比運(yùn)行可以發(fā)現(xiàn),沙箱可以阻止惡意程序的執(zhí)行,并不影響正常程序的運(yùn)行,保護(hù)系統(tǒng)正常運(yùn)行不受影響。
對性能測試,選擇使用一個存在大量系統(tǒng)調(diào)用的程序分別運(yùn)行在本沙箱、一個使用ptrace 實現(xiàn)的沙箱和直接運(yùn)行在操作系統(tǒng)上,對比運(yùn)行時間。時間獲取采用wait3()函數(shù)獲取子進(jìn)程運(yùn)行時間,分別對3 個測試進(jìn)行多次子進(jìn)程運(yùn)行來測試大量系統(tǒng)調(diào)用的程序的運(yùn)行時間。進(jìn)程運(yùn)行時間見表2,可見,使用ptrace 實現(xiàn)的沙箱在存在大量系統(tǒng)調(diào)用的時候進(jìn)程運(yùn)行時間會較長,而本沙箱在系統(tǒng)調(diào)用量較大的時候程序的執(zhí)行效率比不使用沙箱時略低。
表2 各種沙箱實現(xiàn)的性能對比
基于多種安全機(jī)制實現(xiàn)一個安全、輕量級的應(yīng)用程序沙箱,以幫助Linux 系統(tǒng)用戶能夠安全使用應(yīng)用程序。通過仔細(xì)研究Linux 內(nèi)核提供的不同安全機(jī)制,選擇使用Linux 的Seccomp 接口,使一個進(jìn)程能夠操作并完全控制另一個進(jìn)程,結(jié)合多種安全機(jī)制實現(xiàn)一個沙箱系統(tǒng),該系統(tǒng)根據(jù)定義的安全策略去檢測未知程序運(yùn)行時是否存在危險行為,檢測到危險行為的進(jìn)程將被終止,正常的進(jìn)程就仿佛運(yùn)行在操作系統(tǒng),可以正常運(yùn)行結(jié)束且效率不會受到較大影響。