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。
其中,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:
2.2驗證
設被驗證資料為m′,其數字摘要為h′。
h′ = Hash(m′)
假設我們已經取得簽名者的真實公開金鑰PK,然後我們使用PK中的公開資料e對s進行解密計算,得到還原的數字摘要h′′,這裡h′′就相當於是○1式中的h。
現在,我們比較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-1 程式碼簽署過程及簽名值存放
3.2 驗證策略
對被執行ELF檔案簽名值的驗證是根據"系統驗證層級"和該檔案的"檔案驗證層級"二者進行的。"檔案驗證層級"是為單個檔案設定的驗證層級,共分為3個層級,分別由0~2表示。"檔案驗證層級"儲存在每個檔案的inode節點標誌中,系統管理員可以根據需要設定檔案的驗證層級。"檔案驗證層級"的具體含義如表3-1所示。
表3-1:檔案驗證層級
層級 |
名稱 |
說明 |
0 |
無保護級 |
不驗證該檔案的簽名值。 |
1 |
中保護級 |
驗證該檔案的不完全簽名值。 |
2 |
高保護級 |
驗證該檔案的完全簽名值。 |
"系統驗證層級"分為四級,分別由0~3表示。"系統驗證層級"通過PROC檔案系統來進行控制,可以由管理員根據需要進行設定。"系統驗證層級"的具體含義如表3-2所示。
表3-2:系統驗證層級
層級 |
名稱 |
說明 |
0 |
無保護級 |
執行所有程式,不進行任何驗證。 |
1 |
低保護級 |
根據"檔案驗證層級"驗證被執行檔案的簽名值。 |
2 |
中保護級 |
"檔案驗證層級"為0時,根據"系統驗證層級"驗證被執行檔案的簽名值; "檔案驗證層級"不為0時,根據"檔案驗證層級"驗證被執行檔案的簽名值。 |
3 |
高保護級 |
驗證所有被執行檔案的完全簽名值。 |
3.3驗證演算法
當使用者請求執行某個ELF檔案時,系統將根據圖3-2所示的流程來判斷如何驗證該檔案的簽名值。為了提高系統效率,我們將分別為已驗證過"不完全簽名值"和"完全簽名值"的ELF檔案維護相應的緩衝,當再次請求執行這些檔案時,就可以不必重複驗證其簽名值了。
圖3-2:系統級簽名值驗證機制
圖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所示。
圖3-3 核心公開金鑰鏈表
其中key_id是對應公開金鑰的MD5雜湊值,長度為16個位元組。從理論上說,不同公開金鑰的key_id相同的機率接近於2128分之一。在很大範圍內,我都可以認為key_id和公開金鑰是一一對應的。因此,我們將key_id作為每個公開金鑰的唯一標識。
3.6效能測試
表3-3是一組簡單的測試資料,這些資料是通過多次執行後取得的平均值。從中可以看出,通過使用分級機制和緩衝機制,系統開銷增加不到5%,大大減小了對系統效能的影響。
表3-3 驗證簽名的系統開銷
被執行檔案 |
ls / |
gcc test.c |
不驗證簽名值 |
1489μs |
567041μs |
驗證不完全簽名值 |
無緩衝 |
3264μs |
569763μs |
有緩衝 |
1513μs |
567054μs |
驗證完全簽名值 |
無緩衝 |
8955μs |
683295μs |
有緩衝 |
1547μs |
567482μs |
|
|
|
|
環境:CPU PIV 1.7G,Kernel linux-2.4.18,簽名密鑰長度為1024位。
4 結束語
程式碼簽署及驗證的主要目的是防止執行病毒以及木馬程式等惡意代碼,提高作業系統的安全性;同時也是為了保護軟體開發人員以及使用者的利益,軟體開發人員可以防止他人冒名頂替,而軟體使用者也可以確認軟體的真實性和完整性。
目前,也有很多系統採用安裝時驗證程式碼簽署的機制,如微軟的windows系列作業系統。但是,僅僅在安裝時驗證程式碼簽署存在很大的局限性,它無法檢測程式安裝後對代碼的任何修改。因此,採用執行時驗證程式碼簽署的機制將大大提高系統的安全性。但安全性增強同時卻導致了系統效率的降低。為了取得安全性與效率的平衡,本文提出了分級驗證的機制。對安全要求高的系統,則犧牲一定的效率來提高系統安全性;對安全性要求較低的系統,則犧牲一定的安全性來提高系統效率。
參考資料
- Tool Interface Standard (TIS) Portable Formats Specification Version 1.1:TIS Committee,October 1993
- Juha-Petri K?rn? and Mika Leppinen:Signing executables in Linux. April 7th,1998
- WLF tutorial,http://libeccio.dia.unisa.it/ wlf/wlf_tutorial.html
- W.A. Arbaugh,G.Ballintijn,L.van Doorn:Signed Executables for Linux. Tech. Report CS-TR-4259. University of Maryland,June 4,2001
- Luigi Catuogno and Ivan Visconti:A Format-Independent Architecture for Run-Time Integrity Checking of Executable Code. Dipartimento di Informatica ed Applicazioni Università di Salerno Via S. Allende,84081 Baronissi (SA),Italy
- OpenSSL cryptographic library man page,http://www.openssl.org/docs/crypto/crypto.html
- OpenSSL SSL/TLS library man page,http://www.openssl.org/docs/ssl/ssl.html
- PKCS : Public-Key Cryptography Standards. http://www.rsasecurity.com/rsalabs/ pkcs/
- Tigran Aivazian:Linux Kernel Internals. tigran@veritas.com,22 August,2000
- LINUX VIRUSES - ELF FILE FORMAT:Marius Van Oers AVERT-NAI Labs,Gatwickstraat 25,1043 GL Amsterdam,The Netherlands,Europe
關於作者 吳志剛,Linux 愛好者,從事過核心安全機制的研究和開發。通過 alex_wzg@yahoo.com.cn 可以和他聯絡。 |