當入侵者在系統取得一定權限後,他們通常會在系統中植入惡意代碼,並利用這些代碼為日後的入侵提供方便。增加或修改 ELF 文件正是入侵者植入惡意代碼的常用途徑。本文將描述一種 Linux 下 ELF 文件的代碼簽名及驗證機制的設計與實現,這種機制能有效防止基於 ELF 文件的惡意代碼的入侵,並同時提供了靈活的分級驗證機制,使系統在安全性與效率方面取得最佳平衡。
1、引言
隨著 Linux 的不斷發展,已有越來越多的人開始推廣和使用 Linux,其安全性也受到越來越多的挑戰。ELF(Executable and Linkable Format)[1] 作為 Linux 下最主要的可執行二進制文件格式,自然成了病毒及各種惡意代碼的攻擊目標。事實證明,有不少 Linux 下的病毒程序就是通過直接修改 ELF 文件的方法來實現入侵的 [10]。傳統的 Unix 系統(包括 Linux)並不會對執行的代碼進行完整性和合法性檢測,因而讓很多病毒程序以及木馬程序有機可乘。
代碼簽名驗證是一種能夠有效的防止病毒以及其他惡意代碼入侵的方法。對於 Linux 下的代碼簽名驗證機制,早幾年就已經有人研究。文[2]提出了在安裝時進行簽名驗證的方法,並通過修改 chmod 系統調用控制文件的可執行屬性,但這種方法無法檢測程序安裝後對代碼的任何修改,有一定的局限性。文 [3] [4] [5] 描述的都是在執行時進行簽名驗證的方法,其中 [4] [5] 采用了緩存已驗證文件的策略,使效率較 [3] 有很大提高。但是,它們將所有 ELF 文件 "一視同仁",沒有主次輕重之分,缺少靈活性。
本文提出了一種改進的基於 ELF 文件格式的代碼簽名驗證機制,通過提供更加靈活的分級驗證方式,進一步提高驗證效率,並且使系統在安全性與效率方面取得平衡。
2、簽名驗證原理
我們采用完全符合 PKCS [8] 系列標准的簽名驗證算法,並兼容所有符合 X509 格式的證書,以 RSA [6 ][7] 非對稱密鑰體制為基礎來完成對 ELF 文件代碼的簽名驗證。
2.1 簽名
設被簽名的數據為 m,其數字摘要為 h。
h = Hash(m)
其中,Hash 是哈希單向散列算法,如 MD5、SHA-1 等。
設 p,q,d 為簽名者的私有數據,他們都包含在簽名者的私鑰 SK 中;n,e 為簽名者的公開數據,並且都包含在簽名者的公鑰 PK 中。這些數據滿足以下要求:
n = pq 其中 p ≠ q,p q 均為大素數;e,d∈RZn 並且 e = d-1,ed ≡ 1mod(n);這裡,(n) = (p-1)(q-1)。那麼,使用簽名者私鑰對 h進行加密即可得到簽名值 s:
s = E(x) = hdmod n
2.2 驗證
設被驗證數據為m′,其數字摘要為h′。
h′ = Hash(m′)
假設我們已經取得簽名者的真實公鑰PK,然後我們使用PK中的公開數據e對s進行解密計算,得到還原的數字摘要h′′,這裡h′′就相當於是○1式中的h。
h′′ = D(s) = se mod n
現在,我們比較 h′和 h′′是否完全相同。如果相同則驗證通過,否則驗證失敗。
3、設計與實現
為了便於描述,我們引入以下幾個基本概念:
1. 完全摘要值--指對 ELF 文件的所有數據以及簽名相關數據計算出來的摘要值;
2. 不完全摘要值--指對 ELF 文件的一部分重要數據(主要是 ELF 文件頭)以及簽名相關數據計算出來的摘要值;
3. 完全簽名值--指對完全摘要值加密所得到的簽名值;
4. 不完全簽名值--指對不完全摘要值加密所得到的簽名值;
5. 系統驗證級別--指系統級的驗證級別,它適用於系統中所有的 ELF 文件;
6. 文件驗證級別--指單個 ELF 文件的驗證級別,它只適用於指定的某個 ELF 文件。
簽名相關數據是指原始文件大小、簽名者公鑰標識 ID、簽名算法、簽名時間以及簽名者基本信息等數據。
3.1 簽名策略
對 ELF 文件的簽名是通過簽名工具完成的,與操作系統核心無關,同時也和平台無關。簽名過程完全遵循第二節中所描述的標准和原理。
首先,我們通過 ○1 式計算得到兩種摘要值:不完全摘要值(hpart)和完全摘要值(hcomp)。然後再通過 2 式使用簽名者私鑰(SKsign)加密摘要值,從而得到兩種簽名值:不完全簽名值(spart)和完全簽名值(scomp)。
最後,我們將不完全簽名值和完全簽名值按照固定的格式組合在一起,並放在被簽名文件的末尾。如圖 3-1 所示(括號中的數字表示該字段所占字節數)。
3.2 驗證策略
對被執行 ELF 文件簽名值的驗證是根據"系統驗證級別"和該文件的 "文件驗證級別" 二者進行的。"文件驗證級別" 是為單個文件設置的驗證級別,共分為 3 個級別,分別由 0~2 表示。"文件驗證級別"保存在每個文件的 inode 節點標志中,系統管理員可以根據需要設置文件的驗證級別
"系統驗證級別" 分為四級,分別由 0~3 表示。"系統驗證級別" 通過 PROC 文件系統來進行控制,可以由管理員根據需要進行設置。
3.3 驗證算法
當用戶請求執行某個 ELF 文件時,系統將根據圖 3-2 所示的流程來判斷如何驗證該文件的簽名值。為了提高系統效率,我們將分別為已驗證過 "不完全簽名值" 和 "完全簽名值" 的 ELF 文件維護相應的緩存,當再次請求執行這些文件時,就可以不必重復驗證其簽名值了。
圖 3-2 中,"驗證不完全簽名值" 和 "驗證完全簽名值" 兩項都是整個驗證過程的重要步驟。簽名值的驗證與簽名值的生成相對應,驗證時首先要根據相應的數據通過 3 式計算出摘要值(h′part 或 h′comp),然後再使用簽名者的公鑰(PKsign)通過 ○4 式解密相應的簽名值,得到的對應的摘要值(h′′part或h′′comp)。最後比較 h′和h′′是否完全一致,一致則驗證通過,不一致則驗證失敗。
3.4 公鑰管理
在解密簽名數據時,需要用到簽名者的證書公鑰。由於可能存在多個簽名者簽發的代碼,因此也就存在多個簽名者的證書。為了節省系統開銷,盡量減小對系統性能的影響,我們必須高效地管理這些證書公鑰。為此,我們在系統核心空間中維護了一個信任公鑰鏈表,所有被信任者的公鑰都將被放在該公鑰鏈表中。當系統驗證代碼的簽名值時,就可以直接從公鑰鏈表中取得相應的公鑰。如果公鑰鏈表中沒有相應的公鑰,則表示該代碼的簽名者不被信任,因而驗證失敗。系統中的被信任公鑰是可配置的,系統在啟動時將根據配置文件自動初始化核心公鑰鏈表,系統管理員也可以隨時對其刷新或者修改。
3.5 軟件結構
本機制的實現主要包括用戶空間的簽名驗證工具和核心空間的簽名驗證機制模塊兩個部分。其中,用戶空間的簽名驗證工具是本機制的輔助工具,其主要功能是對 ELF 文件進行簽名和設置,同時也可對 ELF 文件的簽名值進行驗證,在此不再贅述;核心空間的簽名驗證機制模塊可以分為驗證策略模塊以及公鑰管理模塊。
3.5.1 驗證策略模塊
驗證策略模塊負責執行簽名值的驗證策略,同時負責管理已驗證文件的緩存鏈表。當用戶請求執行 ELF 文件時,該模塊就會執行如圖 3-2 所示的驗證策略。
驗證簽名值時,系統將首先查詢已驗證文件緩存鏈表,如果發現被驗證文件已經被驗證過,那麼就不必再進行重復驗證,直接采用上次的驗證結果。如果緩存鏈表中沒有被執行文件,那麼就向公鑰管理模塊請求簽名者公鑰,然後再驗證其簽名值。如果驗證正確,則說明被執行文件是完整和可信的,就讓其執行;否則就禁止執行。
另外,為了保證已驗證文件緩存鏈表和實際文件的一致性,我們必須監視 ELF 文件的修改情況,當某一 ELF 文件被修改時,我們應當立即清除已驗證文件緩存鏈表中與該文件相關的驗證結果。
3.5.2 公鑰管理模塊
公鑰管理模塊主要負責對信任公鑰鏈表進行管理,如:初始化鏈表,獲取、添加以及刪除公鑰節點等。
信任公鑰鏈表由一系列的公鑰節點組成,如圖 3-3 所示。
其中 key_id 是對應公鑰的 MD5 哈希值,長度為 16 個字節。從理論上說,不同公鑰的 key_id 相同的概率接近於 2 128 分之一。在很大范圍內,我都可以認為 key_id 和公鑰是一一對應的。因此,我們將 key_id 作為每個公鑰的唯一標識。
3.6 性能測試
表 3-3 是一組簡單的測試數據,這些數據是通過多次執行後取得的平均值。從中可以看出,通過使用分級機制和緩存機制,系統開銷增加不到 5%,大大減小了對系統性能的影響。
4、結束語
代碼簽名及驗證的主要目的是防止執行病毒以及木馬程序等惡意代碼,提高操作系統的安全性;同時也是為了保護軟件開發者以及使用者的利益,軟件開發者可以防止他人冒名頂替,而軟件使用者也可以確認軟件的真實性和完整性。
目前,也有很多系統采用安裝時驗證代碼簽名的機制,如微軟的 windows 系列操作系統。但是,僅僅在安裝時驗證代碼簽名存在很大的局限性,它無法檢測程序安裝後對代碼的任何修改。因此,采用執行時驗證代碼簽名的機制將大大提高系統的安全性。但安全性增強的同時卻導致了系統效率的降低。為了取得安全性與效率的平衡,本文提出了分級驗證的機制。對安全要求高的系統,