




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第13章 移動代碼安全 13.1 引言 13.2 移動代碼安全技術 13.3 Java安全 13.1 引 言 移動代碼又稱移動代理、可下載代碼、可執行內容、遠程代碼等等,它是指在本地執行的遠程代碼。傳統系統中,執行的代碼都是駐留在執行代碼的主機上,而對于移動代碼,執行的代碼則是來自遠程主機。 Carzaniga等人1將移動代碼進行了分類并與傳統的基于客戶機服務器技術的分布式系統作了比較: (1) 客戶機服務器模型:客戶機和服務器位于不同的主機上,由客戶機向服務器發送請求;處理請求所需的資源和代碼都位于服務器端。 (2) 即時響應代碼(Code-on-Demand):客戶機擁有完成某項操作的資源
2、,但沒有如何完成這項操作的代碼,客戶機通過向遠程服務器發送請求,由服務器將代碼發送給客戶機。這種類型的移動代碼包括:Java應用程序、ActiveX控件、MIMI Tcl擴展和Postscript等。 (3) 遠程計算:客戶機擁有描述某項服務的代碼,而執行代碼所需的資源位于遠程服務器上。客戶機把代碼發送到服務器上,由服務器執行代碼并把結果回送到客戶機。 (4) 移動代理:客戶機進程在執行期間為了完成某項服務需要訪問一些資源,而這些資源位于遠程服務器上,于是客戶機把客戶機進程移植到服務器端并由服務器完成服務。客戶機進程會一直停留在服務器上直到下一個客戶機進程移植過來。 Java應用程序(Appl
3、et)和代理(Agent)是移動代碼中的兩種主要形式。Java應用程序是用戶把代碼從遠程主機下載到本地執行。這種技術在Web瀏覽器中嵌入了Java虛擬機。這樣,Web發布者就可以向用戶提供動畫、游戲等動態內容,而不僅僅提供靜態的HTML頁面或依賴于帶寬的CGI交互式內容。而代理則相反,用戶是把代碼發送到網絡上以完成用戶所需的某項任務。最早的移動代理系統之一是Telescript。 從上面的討論可以看出,移動代碼是由一方生成,但在另一方控制的環境中運行的代碼。這就會帶來安全問題。如對于Java應用程序,用戶在執行它來實現某些操作的同時要承擔惡意代碼破壞系統的風險,而代理則要保護其代碼免受惡意主機
4、的利用。13.2 移動代碼安全技術 移動代碼會導致安全問題的本質在于在運行代碼時需要訪問系統資源,而代碼卻是來自于另一臺,甚至是不可信的主機。即代碼提供者和代碼運行者之間可能是互不信任的。移動代碼易受到以下幾種類型的攻擊2: (1) 泄漏用戶或主機的機密信息; (2) 拒絕服務:使合法用戶無法獲得資源; (3) 破壞或修改數據; (4) 惡作劇攻擊:如在用戶屏幕上顯示圖片或在用戶主機上播放音樂等。移動代碼安全需要考慮以下幾個方面:(1) 訪問控制:規定誰可以使用代碼;(2) 用戶認證:識別合法用戶;(3) 數據完整性:保證代碼在傳輸過程中未被修改過;(4) 不可抵賴:發送者和接收方不能否認使用
5、過代碼;(5) 數據機密性:保護敏感數據;(6) 審計:跟蹤移動代碼的使用。 在前面提到,移動代碼安全可以從兩個方面考慮:一是惡意代碼對本地系統的破壞;二是遠程惡意主機對代理的非法使用。接下來,我們將從惡意代碼和惡意主機兩個方面來討論移動代碼的安全技術3。 13.2.1 惡意代碼 對于Java應用程序類的移動代碼,一般的操作是用戶下載可執行格式的二進制Applet然后運行。這就很容易帶來安全問題:用戶必須允許不可信的代碼在本機運行,而這些代碼可能會隨機寫內存,從而導致系統崩潰;代碼甚至可以讀、修改以至刪除用戶個人文件。 在運行Applet之前進行認證可以解決這個問題。通過認證,用戶就可以確定它
6、所運行的代碼來自于特定的可信源。但是這種方法帶來了兩個問題: (1) 嚴重限制了用戶可以運行的Applet(必須來自可信源),而不可信服務器也可提供有用的、好的代碼; (2) 更重要的是來自可信源的代碼可能存在bug,從而對用戶系統帶來惡劣的影響。 對這個問題的理想解決方法就是阻止不安全的行為。接下來討論三種解決惡意代碼問題的技術:安全解釋器、故障隔離和代碼驗證。 1安全解釋器 直接運行二進制代碼是很危險的,解決這個問題的常用方法是不使用編譯好的可執行代碼,而采用解釋移動代碼的方法。在這種情況下,解釋器能很好地控制Applet并能檢查每一條指令和每一個狀態以決定是否執行Applet。這樣,系統
7、的安全性就在于實現解釋器的安全策略的正確性上。安全解釋器包括Safe-Tcl、Safe-Tcl擴展、Java等等。 2故障隔離 采用安全的解釋器系統能很好地解決惡意代碼的問題。但是,相對編譯的機器碼而言,解釋器存在嚴重的性能缺陷:執行Java Applet比執行一般的二進制代碼要慢得多。為此可以轉而采用一種稱為“沙盒”(sandbox)的方法來獲得安全。 在沙盒模式中,下載的不可信代碼的操作將嚴格局限于沙盒中。沙盒是由運行代碼的主機特別為移動代碼分配的地址空間,如Web瀏覽器特別為Java Applet分配的區域。這時,移動代碼可以在沙盒中運行,但不會超出沙盒的界限。例如,Applet不能讀取
8、或修改存儲在用戶系統上的文件。在某種情況下,即使用戶偶然引入了一個敵意的Applet,這個Applet也不能破壞用戶的系統。因此這種沙盒模式為移動代碼提供了一個受限的運行環境,在此環境中可以運行從開放網絡中獲得的不被完全信任的代碼(如Applet等)。 實現沙盒有兩種方法: (1) 插入對地址進行條件檢查的操作,如果地址非法則產生異常; (2) 簡單覆蓋對應沙盒地址的高比特位。 第一種方法更適合調試,而第二種方法系統開銷小一些。 采用沙盒模式的主要缺點是可下載的代碼不再是與平臺無關的,而與操作平臺無關原本是Java系統的主要設計目標之一。 3代碼驗證 第三種技術是一種稱為證明攜帶碼PCC(Pr
9、oof-Carrying Code)的技術4。采用這種技術時,移動代碼主機為Applet確定安全策略,然后以Edinburgh邏輯結構(Logical Framework:用來發布安全策略和對證明進行編碼)對安全策略編碼并發布這個策略。Java Applet作者的任務不僅是把Applet編譯成機器代碼,還要產生一個安全證明(Safety Proof),用來證明這個代碼符合安全策略中指定的安全規則(Safety Rules)。 當用戶下載代碼后,它只要驗證代碼中的證明,看是否合法并滿足安全規則就行。如果是則加載代碼并運行它。 這種方法是否有效的關鍵在于哪些程序特性可以用LF表示和證實。PCC已成
10、功應用于最小和最大CPU周期限制、內存的安全使用、網絡帶寬消耗以及類型安全中。此外,為C語言的安全子集開發了PCC編譯器,它可以自動生成安全證明。 PCC是一種很有前景的方法,但是,它也存在一些缺點:PCC與平臺有關;LF編碼的安全策略和安全證明必須和操作系統以及機器硬件密切聯系。更多信息可以參考網站:/pcc.html。 13.2.2 惡意主機 在討論了惡意代碼問題之后,我們開始討論惡意主機問題。在移動代理編程中,用戶所關心的是其代理能否被正確執行。如一個購物代理可能會攜帶電子現金,一個主機就可能會欺騙代理使它為某些商品支付高價錢,甚至竊取代
11、理內的金錢。這都是用戶所要面對的安全問題。 主機為了執行代理,需要訪問代理代碼和狀態,那么如何保證敏感數據的機密性,或者說如何保證代理算法被忠實地執行呢?Chess13等人認為保護移動代理的限制有: (1) 要對代理代碼或狀態的任意部分保密,就必須采取加密; (2) 我們無法阻止拒絕服務攻擊,因為攻擊者不需要專門可信硬件的幫助就可以任意修改代理代碼或終止代理。 由此可見,要解決惡意主機問題就要從以下兩個方面著手: (1) 能夠檢驗篡改; (2) 能阻止機密信息泄漏。 1檢測篡改 我們無法采用技術途徑來使代理不受破壞,但是如果能明確地識別出惡意主機,那么法律的、社會的威脅就可能阻止惡意主機的操作
12、員破壞代理。識別惡意主機還可能使代理的所有者因代理的損失而獲得某種程度的補償。 下面將介紹檢測惡意主機的技術,這些技術都是基于公開密鑰基礎設施的,它們允許用戶、主機和代理之間相互認證。這些技術主要是要證明一個主機確實是惡意主機,因此,采用數字簽名非常重要。 (1) 執行跟蹤??梢酝ㄟ^產生代理程序執行跡的方法來檢測篡改。首先,將代理代碼的指令分成兩類:只依賴于代理內部狀態的指令以及其結果依賴于和計算環境交互的指令。對于前一類指令,服務器只有在代理的任一變量的值發生變化時,才在執行跡中記錄其新值;對于后一類指令,不但要記錄這些新值,還需要對這些值進行數字簽名。 一旦執行完畢,服務器就計算整個執行跡
13、的密碼散列值并將它返回給代理的所有者。這時,如果代理所有者懷疑在執行代理時有違規操作,它就可以要求出示執行跡,那么主機執行代理時就必須生成執行跡(執行跡的散列值可被驗證),然后檢驗執行跡就可確定: 主機是否錯誤地執行了只依賴于內部狀態的指令; 主機執行代理過程中,在與計算環境交互時是否欺騙了代理。 這種方法在實際的操作中存在兩個問題: (a) 這種方法在主機違規操作時不會向代理所有者發出警報,而只有在所有者懷疑時提供一種可驗證的識別方法; (b) 在需要生成執行跡時,服務器需要保存所有的執行跡,這就給服務器帶來了非常高的負擔。 (2) 認證部分結果。Yee4提出了兩種檢測惡意主機篡改代理的方法
14、。第一種方法是采用部分結果認證碼(PRAC),發送代理的同時發送一組密鑰k1、k2、kn。在第i個服務器,代理使用密鑰ki對其執行結果進行簽名并由此產生PARC;在轉移到下一個服務器之前,代理把ki從狀態中刪除。這樣,一個惡意主機就不能偽造來自前一個服務器的部分結果,最糟糕的情況也僅僅是把這些部分結果從代理中移除。 PRACs允許代理所有者(同時擁有k1、k2、kn)自動地對返回代理中包含的每一部分結果進行密碼驗證。這些消息可以保證非常好的前向完整性:設移動代理訪問一系列的服務器S=s1、s2、sn,而第一個惡意服務器為sc,則對于ic,服務器si的部分結果不是偽造的。 當服務器僅僅通過與正在
15、運行的代理進行欺詐性的交互實現篡改時,上述方案就無法自動檢測到。此外,只有在代理所有者懷疑主機時才會產生PRAC所有的PRAC都是密碼有效的,但有些可能在語義上無效。 Yee提出了一種投機的方法來檢測語義上的篡改。對于程序x,設y為x的執行跡。主機執行完代理后把y發送給代理所有者,由所有者驗證y。由于執行跡可能會很大,因此傳輸它的帶寬開銷會非常大。從而,主機把y編碼成全息樣片y。樣片y具有如下特性:代理所有者只需要檢查y某些位就能確信其正確與否。這樣,服務器就可以采用哈希樹的方案將樣片散列成一個小的根值,然后把根值返回給代理所有者,由所有者判斷y是否正確。這種方法的主要缺點是服務器的負荷問題。
16、構造全息樣片y是一個全NP問題(不存在多項式時間算法解的一類問題,全NP問題則是最為困難的一類),在執行跡y大到很難傳輸到代理所有者時,構造y是不能實現的。 2保密 在有些情況下,事后檢測是不適當的或是不能解決問題的。如有時候采用法律行動的代價比篡改帶來的經濟損失更大;有些時候,代理發送數字簽名,但由于某些原因其私鑰已被泄漏。為此,Sander和Tschudin13提出了一種理論上的方案以允許代理對惡意主機保留一些機密。 方案的本質是這樣的:代理程序計算某個函數f,主機為代理計算f(x)但不需要知道f的任何實質性的內容。協議描述如下: (1) 代理所有者加密f; (2) 所有者創建程序P(E(
17、f)來實現E(f),并把它放在代理中; (3) 代理到達遠程主機,在遠程主機上計算P(E(f)(x),并把值返回給所有者; (4) 所有者解密P(E(f)(x)并獲得f(x)。 其中,E為某個加密函數。協議的基本思想是把基本算法轉化成雜亂算法,使其結果只對代理所有者有意義。 3總結 相比惡意代碼而言,惡意主機問題更難以處理,目前還沒有實際的、在計算上可行的方法用來檢測篡改,而一些可以用來證明發生了篡改的技術也會大大增加服務器的負荷。此外,在一個不友好的環境中運行代理時,有沒有可能為代理提供某種類型的機密性還是一個未知數。這些問題的存在或許可以解釋移動代理為什么得不到廣泛應用。13.3 Java
18、 安 全 13.3.1 Java綜述 Java語言是Sun Microsystems公司開發的。在Sun Microsystems公司提供的技術報告5中稱:“Java是一種簡單的、面向對象的、適合網絡編程的、解釋的、健壯的、安全的、與結構無關的、可移植的、高性能的、多線程的動態語言。” 簡單:Java是一種易于使用的編程語言,其簡單性體現在以下幾個方面: (1) 它和C+類似(C+程序員可以很快掌握Java編程技術); (2) 它摒棄了C+中許多很少用、很難理解和容易混淆的特性,如操作符重載等; (3) Java實現了自動垃圾收集,從而簡化了Java編程。在C和C+中,一個復雜的操作是內存管理
19、:內存分配和內存釋放。通過自動垃圾收集(周期性的釋放沒有被引用的內存)不但可以使編程簡單化,還可大大地減少程序中的bug; (4) Java程序很小,易于通過網絡下載。 面向對象:和C+一樣,Java是一種面向對象的編程語言。 適合網絡編程:Java擁有廣泛的、能輕易處理TCP/IP協議的運行庫,因此相比C和C+而言,Java更容易創建網絡連接。Java應用程序通過URL打開和訪問網絡上的對象與編程人員訪問本地文件系統一樣簡單。 健壯性:Java能檢查程序在編譯和運行時的錯誤。類型檢查可以檢查出許多開發早期出現的錯誤;Java沒有采用C+中的指針算法而實現了真數組,從而避免了覆蓋內存和破壞數據
20、的可能。 安全:設計Java是為了用于分布式網絡環境,因此安全在這里就顯得非常重要。本節的后續內容將詳細介紹Java的安全實現以及其潛在的安全威脅。 與結構無關:Java程序是在網絡上傳播和應用的,而網絡上的不同主機的CPU、操作系統結構等等都不盡相同,為了使Java應用程序能在網絡上的任何一臺主機上運行,編譯器必須產生一個與結構無關的文件格式只要處理器上有Java虛擬機系統,此文件格式的代碼就可以在此處理器上運行。Java的做法是讓編譯器生成與特定計算機體系結構無關的字節碼指令,這些字節碼指令在任何機器上都很容易解釋,并能很容易地翻譯成本機機器代碼。 可移植:與體系結構無關的特性使得Java
21、應用程序可以在配備了Java解釋器和運行環境的任何計算機系統上運行,這為Java應用程序便于移植打下了良好基礎。但僅僅如此還不夠,不同操作系統基本數據類型的設計實現是不同的,如在Windows 3.1中整數(int)為16位,在Windows 95中為32位,而在DEC Alpha中卻為64位。這不利于代碼的移植。為此,Java定義了獨立于平臺的基本數據類型及其運算,從而使得Java數據在任何硬件平臺上都是一致的。其次,Java編譯器本身是用Java語言編寫的,而運算系統是用ANSI C語言寫的。總之,在Java語言規范中沒有任何與具體實現相關的內容。 解釋:Java是一種解釋性語言,其解釋器
22、可以將Java字節碼翻譯成本地機器指令并運行,而不需要存儲字節碼。 高性能:由于解釋字節碼的性能一般都是比較高的,從而Java可以在運行時直接將字節碼翻譯成機器指令。Sun Microsystems的SPARCStation 10在翻譯代碼時,可以在每秒鐘內調用300 000個方法,這和直接生成機器目標代碼C/C+的性能不相上下。 多線程:Java提供了一個內建的機制來提供對多個并發子任務的支持。 動態:在C+程序設計過程中,每當在類中增加一個實例變量或一種成員函數后,引用該類的所有子類都必須重新編譯,否則將導致程序崩潰,而Java是一種動態語言,它不是把所有的類靜態地編譯成機器碼,而是由程序
23、動態地裝入運行過程中所需要的類。 13.3.2 Java底層安全性實現 1. 底層安全 Java解釋器通過以下幾種方式實現底層安全: 1) 通過發布源代碼獲得安全 如果需要,Java解釋器和編譯器均可獲得完整的源代碼。對Java源代碼可以執行安全審計。 2) 通過明確定義獲得安全 Java語言的定義非常嚴格: 保證所有的基本類型使用指定的長度; 所有的操作必須按指定的順序執行。 明確的定義可以保證兩個(正確的)Java編譯器執行同一個程序不會得到兩個不同的結果。 3) 通過摒棄指針獲得安全 Java摒棄了C語言中的指針算法,因此編程人員無法偽造指針來訪問內存。對類文件中所有方法和實例變量的引用
24、都是通過符號名來實現的,這就可以避免在C語言中利用指針非法訪問內存而提升權限一類的攻擊,如緩沖區溢出等。 4) 通過垃圾收集獲得安全 在C/C+中,編程人員經常面對的問題是內存分配和釋放。當釋放內存不當,如沒有釋放不再使用的內存或兩次釋放同一內存區會導致安全問題。Java通過自動垃圾收集(周期性地釋放沒有被引用的內存)來避免這些問題。 5) 通過在編譯時的嚴格檢查獲得安全 Java編譯器在編譯時要進行詳盡的、嚴格的檢查以盡可能地檢測編程中的錯誤。Java語言是強類型的: 在運行期,如果不進行明確的檢查不能把對象分配給某個子類; 要檢查所有對方法和變量的引用以確保對象具有合適的類型。 整數不能轉
25、換為對象,對象也不能轉換為整數。 編譯器還要確保程序沒有訪問未初始化的本地變量。 2. 類文件驗證 雖然編譯器可對類型進行詳盡的檢查,但攻擊者仍然可能通過使用專門的編譯器實現攻擊。如HotJava瀏覽器是下載已經編譯好的類文件,它無法確定下載的字節碼是由可信的Java編譯器編譯的還是由某個有惡意企圖的編譯器編譯的。 在編譯時實現對類型的檢查還存在版本不一致的問題。如用戶編譯好了一個類,假設 PurchaseStockOptions是TradingClass的一個子類。但是在類編譯完后,TradingClass的定義可能會發生變化:某個方法不用了或方法的參數改變了;變量類型變了。而且,方法或變量
26、也可能從公有變成私有。 為此,所有外來的類文件都需要經過一個驗證器,由驗證器確保類文件具有正確的格式。 字節碼驗證器同樣可以增強解釋器的性能。利用字節碼驗證,解釋器就不用對每一條解釋的指令進行檢查,而會認為這些檢查都已經在此之前完成了。如解釋器能肯定代碼遵守以下限制: 代碼中不存在緩沖區溢出; 所有的寄存器訪問和存儲都是合法的; 所有字節碼的參數都是正確的; 不存在非法的數據轉換。 驗證器獨立于Java編譯器,它使用戶可以放心的從防火墻之外下載Java代碼。 下面詳細介紹驗證器的驗證過程,其中提到的類文件格式的具體細節可參考參考資料5: (1) 驗證的第一步發生在將類讀入解釋器時。這一步要確保
27、類文件具有類文件的格式:開始的幾個字節必須包含正確的魔幻數;所有可驗證的屬性都具有正確的長度;類文件的末尾不能被截斷,也不能添加額外的字節;常數存儲庫不能包含不可識別的信息。 (2) 第二步更進一步驗證類文件的格式: 確保final類沒有被繼承,final方法沒有被覆蓋; 每個類必須有一個超類; 確保常數存儲庫滿足一定的限制,如其中的類引用必須包含一個指向存儲庫中的一個unicode字符串引用的域。 常數存儲庫中所有的域引用和方法引用都必須有合法的名字、合法的類和合法的類型簽名。(3) 這一步是類驗證中最復雜的一步,在這一步中需要驗證每一個方法的字節碼。這一步要保證: 堆棧的大小和它包含的對象
28、類型保持不變; 除非已知包含了一個適當類型的值,否則不能訪問寄存器; 以適當的參數調用方法; 以適當類型的值修改域; 所有的操作碼在堆棧和寄存器中具有適當類型的參數。在“字節碼驗證”中我們將進一步描述這一步的細節。 (4) 在第三步中,除非有必要,否則不會裝載類文件。如一個方法調用另一個返回foobarType類型對象的方法時,如果立即把同一類型的域分配給返回的對象,驗證器就不會驗證foobarType類型是否存在;如果把anotherType類型的域分配給返回的對象,則必須裝載foobarType和anotherType的定義以確保foobarType是anotherType的一個子類。 引
29、用類的指令第一次執行時,驗證器需: 如果還沒有裝載這個類則裝載; 驗證當前正在執行的類是否被允許引用給定的類。 指令第一次調用方法或訪問、修改域時,驗證器需: 確保方法或域存在于給定的類中; 檢查方法或域是否具有要求的簽名; 檢查當前正在執行的方法是否有權訪問給定的方法或域。 這一步中,驗證器不需要檢查堆棧中對象的類型,因為在第三步中已經執行了這項檢查。 在執行完驗證后,字節碼流中的指令就會被另一種形式的指令所代替。如操作碼new被new_quick代替。這個替換的指令表示已經執行了對這個指令的驗證,不需要再次驗證了。 3字節碼驗證 類文件驗證的第三步是字節碼驗證,這是類文件驗證過程中最復雜的
30、一步。首先,把組成虛指令的字節分成一系列的指令,每一個指令開始位置的偏移量保存在一個位表中。然后,驗證器再次掃描這些字節并解析指令。這一步中把每個指令轉換成一個結構。檢查每個指令的參數(如果有的話)以確保它們是合理的: 所有的流程控制指令必須到達一個指令的開始,不允許有到達指令內部的分支。類似的,不允許出現到達代碼開始前或代碼結束后的分支。 所有的寄存器引用必須是引用合法的寄存器。除方法指明的所能用的寄存器外,代碼不能訪問和修改任何其它的寄存器。 所有對常數存儲庫的引用必須是引用適當類型的條目。如操作碼ldc1只能用于整數、浮點數或string類型,而操作碼getfield必須引用一個域。 代
31、碼不能在某個指令中間結束。 對每一個異常處理程序,其起始點和結束點都必須指向一個指令的開始。異常處理器的偏移必須是合法的指令;起始點必須在結束點之前。 對每一條指令,在執行之前,驗證器要跟蹤堆棧和寄存器的內容。對于堆棧,需要知道堆棧的長度和堆棧中元素的類型;對于寄存器,需要知道寄存器內容的類型或寄存器內的值是合法的。在確定堆棧中值的類型時,字節碼驗證器不需要區分不同的整數類型(如byte、short和char)。 接下來初始化數據流分析器。對于第一條指令,編號較小的寄存器包含方法類型簽名所指示的類型;堆棧為空;所有其它的寄存器包含非法值;對于其它指令,指示該指令沒有被訪問,還沒有其堆?;蚣拇嫫?/p>
32、的信息。 最后,運行數據流分析器。對每一條指令都有一個“changed”位來表示這個指令是否需要查看。最初只有第一條指令設置了“changed”位。數據流分析器執行如下循環: (1) 找到一個設置了“changed”位的虛擬機器指令,如果沒有找到,則表示該方法已被驗證。清“changed”位。 (2) 仿真指令對堆棧和寄存器的影響: 如果指令要使用來自堆棧的值,需確保堆棧中有足夠的元素,并且堆棧頂端元素具有適當的類型,否則,驗證失敗。 如果指令使用了寄存器,需確保指定的寄存器包含了適當類型的值,否則,驗證失敗。 如果指令要把值壓入堆棧,往堆棧頂端加入指示的類型,需確保堆棧有足夠的空間存放新元素
33、。 如果指令需要修改寄存器,需說明寄存器當前包含了新的類型。 (3) 確定跟隨在當前指令后面的虛擬機器指令。后續指令可能是: 如果當前指令不是無條件goto、return或throw,則為下一條指令;如果可以離開最后一條指令,則這一步失敗。 有條件或無條件轉移的目標。 當前指令所有的異常處理程序。 (4) 在當前指令的末尾,把堆棧和寄存器的狀態合并到下一條指令中。在異常處理的情況下,需要更改堆棧使得堆棧包含一個單一的對象,其異常類型由異常處理器信息指明。 如果下一條指令是第一次訪問,則在執行下一條指令之前指明:由第(2)步和第(3)步計算得到的堆棧和寄存器的值是堆棧和寄存器的狀態;設置下一條指
34、令的“changed”位。 如果指令以前訪問過,則把第(2)步和第(3)步計算得到的堆棧和寄存器的值合并到已有的值中;如果有改動則設置“changed”位。 (5) 回到第(1)步。 字節流分析器對某些指令和數據類型,如長整數、構建函數、異常處理程序、Try/Finally等的具體驗證過程可參考參考資料6。 13.3.3 Java的沙盒模型 傳統的操作系統允許應用程序對機器有完全的訪問,因此不能信任運行環境。為此,安全策略一般要求在運行一個程序之前,需要在某種程度上信任程序。如在運行從Web上下載的程序之前,安全策略要求對程序進行病毒檢查以及檢查源代碼以發現惡意代碼。這種方法存在兩個問題: (
35、1) 建立對應用程序信任的檢查在實際操作中非常復雜,且非常費時間。一般人們不會花時間去研讀源代碼以發現隱藏在其中的惡意行為。 (2) 要使病毒檢查有效,需要及時地維護:病毒庫要及時更新、掃描程序要安裝在每一臺計算機上等等。 Java采用了一種新的方法:沙盒。Java把Applet的所有操作都嚴格限制在一個稱之為“沙盒”(一個由Web瀏覽器專門為這個Applet分配的地址空間)的區域內。Applet在其沙盒內可以做任何事,但超出此邊界就不能有任何操作。沙盒模型實現了在一個信任環境中運行不信任的代碼的功能。這樣,即使用戶運行了一個惡意的Applet,也不會給用戶帶來什么損失。沙盒由幾個不同的系統操
36、作組成,下面將逐一介紹。 1類裝載程序ClassLoader Java運行時有兩種不同的方式來裝載一個新的類。其默認機制是從本地機器上的文件中裝載一個類,這種機制不需要類裝載程序ClassLoader。另一種方式是通過網絡等裝載一個類,這時需要一個相關的類裝載程序ClassLoader,由ClassLoader負責將類的原始數據(如網絡上傳輸的字節)轉化成表示那個類的內部數據結構。 類裝載程序除了要完成從網絡上獲得一個Applet的可執行代碼外,還實施了命名空間的體系結構。一個命名空間規定了一個Applet能訪問JVM(Java虛擬機)的其它哪些部分。通過為本地磁盤上的可信任代碼維護一個單獨的
37、命名空間,類裝載程序可以防止不可信的Applet獲得對系統可信部分(往往需要更多特權才能訪問)的訪問權。 從網絡上下載的Applet不能創建其自己的類裝載程序,也不能調用系統類裝載程序中的方法。 2驗證器 在運行一個新下載的Applet之前,類裝載程序要調用驗證器進行類文件驗證。 3安全管理器 安全管理器增強沙盒的邊界。在Applet試圖執行可能導致本地機器崩潰或訪問信息的操作時,JVM首先向安全管理器詢問此操作是否可以安全地執行。只有安全管理器準許了這項操作,虛擬機才能執行,否則,虛擬機將產生一個安全異常并向Java控制臺寫出錯信息。下面列舉了安全管理器禁止不可信Applet執行的部分操作:
38、 對本地文件的讀寫; 刪除文件; 執行操作系統命令或本地代碼; 載入一個直接調用本地方法的新的動態庫; 與不是此Applet源主機的機器建立連接; 建立一個新的進程。 一個應用程序或Web瀏覽器只能有一個安全管理器,這可保證所有的訪問檢查都是由一個執行單一安全策略的安全管理器來完成的。安全管理器在啟動時載入,它不能被擴展、重載或替代。顯然,Applet不能創建其自身的安全管理器。 4語言特性 在Java底層安全性實現一節中,我們可以看出,Java具有許多可以保護安全系統完整性,并防止某些常見攻擊的特性。 13.3.4 擴展Java安全 Java沙盒模型可以保護終端用戶機器和網絡計算資源不受惡意
39、Applet的破壞和進行信息竊取,從而用戶可以運行來自網絡上的不可信代碼而不會有安全風險。但是沙盒模型沒有涉及其它的一些安全和保密性問題: 認證可以幫助確認一個Applet確實來自其聲明的主機; 數字簽名和認證過的Applet可以提升為可信Applet,從而可以在較少的安全限制前提下運行; 加密可以保證Applet客戶端和Internet上服務器之間傳輸數據的機密性。 1簽署JAR文件 所有的網絡化系統都容易受到潛在的中間人攻擊。在這種攻擊中,客戶端與網絡上的合法服務器進行連接并請求某種操作;而攻擊者,即這里所說的中間人竊聽到這些請求后就等待服務器的響應,然后截獲響應并向客戶端發送一個偽造的應
40、答;這時客戶端就會根據這些偽造的信息進行某種操作,或者運行攻擊者提供的程序而使攻擊者獲得對機器的訪問權。如攻擊者可觀察一個基于Internet的銀行站點;當客戶端訪問其提供付款服務的頁面時,攻擊者就可以截獲銀行的響應,而把一個可以模仿銀行服務并可竊取用戶信用卡副本和銀行賬號的惡意Applet作為響應發送給客戶。 通過對Applet使用“數字簽名”可以阻止這種攻擊。首先,把所有Java代碼和相關文件捆綁成一個Java檔案(JAR);然后根據JAR的內容利用數字簽名算法產生一個用字符串表示的數字簽名。通過驗證其數字簽名就可以確定這個JAR的來源,從而有效地防止了中間人攻擊。 JAR文件從某種程度上
41、還可幫助解決另外一個問題。目前,許多Java Applet需要很長時間才能下載下來。這和當前的Internet協議有關。 目前的Internet協議每次只請求和傳送一個文件,每請求一個文件需要一定的開銷,而一個頁面和Java Applet一般都由許多小文件組成,從而可能使得請求文件和等待響應的時間比真正傳輸信息的時間還要長。采用JAR文件后,把Applet和Web頁所需要的所有信息捆綁成一個文件,從而請求整個頁面就只需要一個請求。對于大部分的頁面,這可大大減少下載時間。 2靈活的策略 數字簽名可以賦予Java Applet某種可信度,從而可以放寬對某些Applet的Java安全限制。如上面提到
42、的家庭銀行Applet,如果采用了數字簽名,它就可以在用戶硬盤上建立自己目錄以存儲賬號、信用卡號、口令、個人身份號碼PIN和其它經常要用的信息,這時的終端用戶不必經常性地重輸這些信息。 數字簽名過的Applet可以創建自己的環境。如果終端用戶已提前指示Java系統某個特定的Web發布者是可信的,而且某個來自此Web發布者并簽名了的Applet被驗證通過,則Java安全管理器就可允許這個Applet的操作超出其沙盒的范圍,也就是說,把這個Applet看成一個普通的應用程序。 安全管理器還可以根據對特定Web發布者的信任程度或對整個Internet的信任程度而執行不同的控制策略。如一個安全意識很強
43、的用戶可能將系統配置成簽名了的Applet只能在沙盒范圍內執行;未簽名的Applet根本就不允許執行。另外一個用戶可能將系統配置成銀行Applet只能訪問硬盤上的某個特定目錄,而一個網絡游戲Applet可以訪問另外一個目錄,同時所有其它的Applet只能在沙盒的范圍內執行。 3審計 審計是另一個重要的安全要素。審計軟件將維護系統上發生的每一件事的記錄。當出現錯誤時(無論是偶然還是由于bug,或者是由于攻擊造成的),系統管理員和安全人員就可以根據審計跡推測出所發生的事,從而可以幫助他們確定如何防止錯誤的再次發生。雖然審計不能阻止事故和攻擊,但在錯誤發生后,它是把事情弄清楚的重要工具。 目前版本的
44、Java審計功能很有限,還沒有管理員可以依賴的審計能力,而且其記錄的特征很不詳細。 4加密 雖然沙盒模型和對Applet的數字簽名可以阻止惡意Applet的破壞和中間人攻擊,但在Internet上,Applet和服務器之間的信息傳輸仍然易遭到竊聽。這是因為Internet本身就是一個不安全的傳輸煤質。攻擊者在Internet的關鍵點可以獲得經過該關鍵點的所有的信息。由此,攻擊者可以偵聽出入一個銀行的所有流量,也可以只獲取通過的信用卡號和其它一些信息。為了防止這種攻擊,我們需要對Applet和服務器之間的所有流量進行加密,從而使它不可讀。 13.3.5 Java安全開發建議 雖然Sun聲稱Jav
45、a是一種安全語言,而且Java也采用了一些安全結構以及內建了一些安全特性,但是Java仍無法避免安全問題,其應用程序中仍存在大量的安全漏洞和隱患。為了使用Java開發安全的程序,可參考以下建議101112。 1) 限制對類、方法和變量的訪問 把類、方法和變量聲明為公有會給攻擊者提供潛在的入口。為此:(a) 不要使用公共域或變量,把它們聲明為私有的,并提供訪問函數以限制對它們的訪問;(b) 除非有很好的理由,否則把方法都設為私有的(如果確實沒這樣做,說清楚其理由)。非私有的方法可能會接收受污染的數據,因此必須保護這些方法(除非已經用其它方式對它們進行了保護)。 2) 避免使用靜態域變量 靜態域變
46、量是附著在類而非類的實例上,而類可以被其它類所定位,其結果就是可以通過其它類找到靜態域變量,這就很難保證它們的安全。 3) 永遠不要把可變對象返回給潛在的有惡意代碼(因為代碼可能會改變它) 注意,數組是可變的(即使數組的內容不可變),所以不要返回一個含有敏感數據的內部數組的引用。 4) 永遠不要直接保存用戶給定的可變對象(包括對象的數組) 如果直接保存用戶給定的可變對象,用戶可以把對象交給安全代碼,讓安全代碼“檢查”對象,并在安全代碼試圖使用數據時改變數據。應該在內部存儲數組前復制它們,而且要小心(例如,警惕用戶編寫的復制例程)。 5) 不要依賴于初始化 許多Java開發人員認為如果不運行構建
47、器就無法為一個對象分配內存,這是不對的,事實上有許多方法可以為未初始化的對象分配內存。避免這個問題的一個簡單方法就是書寫自己的類,從而在對象進行某項操作前驗證對象。其做法為 使所有的變量為私有。如果要允許外部代碼訪問一個對象內的變量,可以通過set和get方法來實現(這就使外部代碼不能訪問未初始化的對象)。 為每一個對象添加一個新的私有布爾變量initialized。 在返回之前讓每一個構建器設置初始化的變量作為最后一個操作。 在進行進一步操作之前,讓每一個nonconstructor方法驗證initialized為真。 如果自己書寫的類具有靜態的初始化程序,則需要在類的層次做同樣的操作。也就
48、是說,對于任何一個具有靜態初始化程序的類,需要: 使所有的靜態變量私有。如果要允許外部代碼訪問類中的靜態變量,可以通過靜態set和get方法來實現(這就使外部代碼不能訪問未初始化的靜態變量)。 為類添加一個新的私有靜態布爾變量classInitialized。 在返回之前讓靜態構建器設置初始化的變量作為最后一步操作。 在進行進一步操作之前,讓每一個靜態方法和每一個構建器驗證classInitialized為真。 6) 除非有很好的理由,否則使每件事都final(終結) 如果某個類或方法不是final的,攻擊者就可以用某種危險且無法預知的方法來擴展它。注意,作為安全性的交換,這會帶來可擴展性的喪
49、失。 7) 不要在安全性上依賴包的范圍 在同一個包內可以訪問沒有明確標記為public、private或protected的類、方法和變量。Java類不是關閉的,因此,攻擊者可以向包中引入一個新類,并用此新類來訪問用戶以為保護了的信息。(某些類,如java.lang,缺省是關閉的,而且某些Java虛擬機(JVM)會讓用戶關閉其它包,但最好假設包不是關閉的。) 8) 不要使用內部類 有些Java語言的書上稱只有封裝內部類的類才可以訪問被封裝的內部類,這是不正確的,因為Java字節碼沒有內部類的概念,在內部類轉換為字節代碼時,會被轉換為這個包中任意代碼可以訪問的類。更糟的是,被封裝類的私有域會靜悄
50、悄地變成非私有的,從而允許內部類訪問! 9) 最小化特權和避免標記代碼 運行沒有標記的代碼不需要任何專門的特權。沒有專門特權的代碼不會帶來什么危害,為此應避免標記代碼。但是有時代碼需要獲得和使用特權以執行某種危險的操作,此時應使代碼特權最小化,同時應更仔細地審閱特權代碼。 10) 如果一定要標記代碼,應該把它們都放在一個檔案文件里 此規則的目的是防止攻擊者使用混合匹配攻擊。在混合匹配攻擊中,攻擊者構建新Applet或庫,把某些標記類與有惡意的類連接在一起,或把根本意識不到會被一起使用的標記類連接在一起。通過把一組類標記在一起,就可以使這種攻擊更高明?,F有的代碼標記系統在防止混合匹配攻擊上做得還不夠,所以這一規則還不能完全防止此類攻擊。但使用單個檔案沒什么壞處。 11) 使類不可被復制 Java的類復制機制允許攻擊者不運行構建函數就實例化某個類。只要在每個類里定義如下方法就可使類不可被復制: public final void c
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年現代教育技術專業考試試卷及答案
- 2025年人工智能技術與應用考試試卷及答案
- 2025年人力資源管理師考試卷及答案
- 2025年辯論技巧與公共演講考試試題及答案
- 2025年電子商務運營管理職業資格考試卷及答案
- 2025年情境領導理論知識考試題目及答案
- 七級數學期末測試題及答案
- 裝卸合作協議書合同
- 2025年紅外線氣體分析儀合作協議書
- 2025年麻醉臨床信息系統項目發展計劃
- 麻家梁煤礦8.0Mt-a新井設計- 厚煤層富水頂板控水開采技術
- 鐵路防脹知識培訓
- 2025年浙江湖州市城市投資發展集團有限公司招聘筆試參考題庫附帶答案詳解
- 2025年高空車作業考試題及答案
- 非遺文化產業發展-深度研究
- 2024年認證行業法律法規及認證基礎知識答案
- (一模)2025年深圳市高三年級第一次調研考試 英語試卷(含標準答案)
- 越南投資環境評價與重點投資區域研究
- 神經內科緊急護理人力資源調配演練記錄
- 丙酸鉻、淀粉酶對黃羽肉雞生長性能、抗氧化和腸道健康的影響
- 光伏發電新能源課件
評論
0/150
提交評論