JAVA的安全模型不同於傳統的安全方法,傳統的安全方法中,大多數作業系統允許應用程式充分訪問系統資源,在作業系統不提供安全保護的機器裡,運行環境不能被信任。為了彌補這個缺陷,安全性原則經常要求在應用程式執行之前對應用程式建立信任,例如要求程式員在執行從網上獲得的應用程式前,先檢查病毒和原始碼中不安全的代碼。這種方法有2個問題:
(1)確定程式是否安全的檢查很複雜很浪費時間,很少有程式員願意花時間讀程式的原始碼,然後再將它編譯成本地機器碼以保證程式是安全的。
(2)病毒檢查要不斷維護以保證有效性。
JAVA的安全模型是不同的,為了防止使用者系統受到通過網路下載的不安全程式的破壞,JAVA提供了1個自訂的可以在裡面運行JAVA程式的“沙箱”。JAVA的安全模型使得JAVA成為適合於網路環境的技術。JAVA的安全性允許使用者從Internet或Intranet上引入或運行applet,applet的行動被限制於它的“沙箱”,applet可以在沙箱裡做任何事情,但不能讀或修改沙箱外的任何資料,沙箱可以禁止不安全程式的很多活動,如:
1.對硬碟進行讀寫。
2.和別的主機(不包括程式所在的主機)進行網路連接。
3.建立1個新過程。
4.載入1個新的動態庫並直接調用本地方法。
“沙箱”模型的思想是在信任的環境中運行不信任的代碼,這樣即使使用者不小心引入了不安全的applet,applet也不會對系統造成破壞。
“沙箱”模型
“沙箱”安全模型是內建於JAVA結構的,它主要由以下幾部分構成:
1.內建於JAVA虛擬機器和語言的安全特性。
2.類的載入結構。
3.類檔案校正器。
4.安全管理器和JAVA API。
下面分別進行闡述。
1.1 內建於JAVA虛擬機器和語言的安全特性
JAVA語言有一些機制使得JAVA程式很穩健,這些機制也是JAVA虛擬機器(JVM)的特點,它們是:
1.安全的類型轉換。在C、C++中,可以通過指標進行任意的類型轉換,但常常帶來不安全性,而在JAVA中,運行時系統對對象的處理要進行類型相容性檢查,以防止不安全的轉換。
2.沒有指標。指標是C和C++中最靈活、也最容易產生錯誤的資料類型。由指標所進行的記憶體位址操作常會造成不可預知的錯誤,同時通過指標對某個記憶體位址進行顯示類型轉換後,可以訪問1個C++中的私人成員,從而破壞安全性,造成系統的崩潰。而JAVA對指標進行完全的控制,程式員不能直接進行任何指標操作。
3.自動的垃圾收集。在C中,程式員通過庫函數malloc()和free()來分配和釋放記憶體,C++中則通過運算子new和delete來分配和釋放記憶體。再次釋放已釋放的記憶體塊或未被分配的記憶體塊,會造成系統的崩潰;同樣,忘記釋放不再使用的記憶體塊也會逐漸耗盡系統資源。而在JAVA中,所有的資料結構都是對象,通過運算子new為它們分配記憶體堆。通過new得到對象的處理權,而實際分配給對象的記憶體可能隨程式運行而改變,JAVA對此自動進行管理並且進行垃圾收集,有效地防止了由於程式員的誤操作而導致的錯誤,並且更好地利用了系統資源。
4.數組界限檢查。若程式中有數組訪問,JVM就會檢查數組訪問是否越界,從而防止了由數組越界引起的錯誤。
5.檢查null引用。若使用的引用為null,JVM就會拋出1個例外。
1.2 類載入器結構
類載入器結構在沙箱模型中起了重要作用。在虛擬機器中,類載入器負責引入、定義運行程式的類和介面的位元據。在虛擬機器中可能有不止1個類載入器。
1個JAVA程式能使用2種類型的類載入器:原始的類載入器和類載入器對象。原始的類載入器是JVM實現的1部分,它通常從本地硬碟載入安全的類,包括JAVA API的類。運行時,JAVA應用程式安裝類載入器對象,類載入器對象使用JAVA語言編寫,編譯成類檔案後,載入到虛擬機器,像其他的對象一樣初始化。類載入器對象用於以自訂的方式載入類,例如通過網路下載類檔案。JVM把通過原始的類載入器載入的任何類都視為安全的,無論這個類是否是JAVA API的1部分。而將通過類載入器對象載入的類視為可懷疑的,預設情況下視為不安全的。
JAVA的結構可以在1個應用程式中建立多個命名空間,命名空間是由1個特定的類載入器載入的類名的集合。JVM為每1個類載入器維持1個命名空間,這個命名空間裡有由那個類載入器載入的所有類的名字。由不同類載入器載入的類在不同的命名空間裡,沒有程式的直接允許,這些類不能彼此訪問。編寫程式時,可以將來源不同的類放在不同的命名空間裡,用這種方式,就可以使用JAVA的類載入器結構控制來源不同的代碼間的相互作用,就可以防止不安全的程式碼訪問、破壞安全的程式碼。對於Applet,也是同樣的道理,通過將來源不同的Applet類檔案放在不同的命名空間,防止不安全的程式碼破壞安全的程式碼。
在“沙箱”結構中,類載入器結構是防止不安全的程式碼的第一道圍牆,它的作用主要有2方面:
1.防止不安全的程式碼訪問、破壞安全的程式碼。
2.防止不安全的程式碼冒充安全的類。
這2方面作用是通過下述方法實現的:
1.將代碼分放在多個命名空間中,並在不同命名空間的代碼之間設定“屏障”。類載入器結構是通過命名空間來防止不安全的程式碼訪問、破壞安全的程式碼。命名空間在載入到不同命名空間中的類之間設定了1個“屏障”。在JVM中,同一命名空間中的類可以直接相互作用,不同命名空間中的類甚至不能檢測到對方的存在,除非程式允許它們相互作用。
2.保護可信任類庫(像JAVA API)的邊界。如果類載入器載入1個類,這個類用它的名字來冒充是JAVA API的1部分(例如,類名為java.lang.virus),類載入器就傳遞請求給原始類載入器,如果原始類載入器不能載入這個類,類載入器就拋出安全例外,並拒絕載入這個類。
1.3 類檔案校正器
每一個JVM都有1個類檔案校正器,用來保證載入的類檔案具有正確的內部結構。如果類檔案校正器發現類檔案有錯誤,它就拋出1個例外。
類檔案校正器能協助檢查出類使用起來是否安全。因為類檔案是由位元據構成的,JVM不知道這個類檔案是否是由駭客產生的,是否有可能破壞虛擬機器的完整性,所以虛擬機器對引入的位元組碼進行校正是很重要的。類檔案校正器校正的過程可以分為2個階段:階段1發生在類剛載入以後,類檔案校正器檢查類檔案的內部結構,包括校正所含的位元組碼的完整性;階段2發生在位元組碼執行的時候,位元組碼校正器確定符號引用的類、域和方法是否存在1.3.1內部檢查
在階段1,類檔案校正器檢查類檔案是否正確組成、內部是否一致、是否遵循JAVA程式設計語言的限制、含有的位元組碼是否能由JVM安全執行,如果類檔案校正器檢查出錯誤,它就會拋出1個錯誤,類檔案就不再被程式使用。
1.檢查格式和內部一致性
在階段1,校正器除了檢查位元組碼的完整性,還要檢查類檔案的格式和內部一致性。例如,每一個類檔案都必須以同樣的4位元組數字0xCAFEBASE開頭,這樣類檔案校正器可能檢查的第一件事就是引入的檔案是否以0xCAFEBASE開頭。
類檔案校正器還要校正類檔案的長度是否與類檔案中所記錄的長度一致,也即校正類檔案是否完整,是否被截去一部分或者被添加。類檔案校正器還要檢查類是否遵循Java語言的規定,如除了Object類,所有的類都必須有1個父類等。
2.位元組碼校正
一旦類檔案校正器成功地完成格式和內部一致性的檢查,就開始對位元組碼進行校正。通過對代表類方法的位元組碼流進行資料流分析,進行作業碼是否有效及作業碼是否有有效運算元等的檢查,以驗證位元組碼流是否可以由虛擬機器安全執行。
1.3.2符號引用的校正
符號引用是給出了引用項的名字和其它資訊的字串,這些資訊足以用來區分類、域或方法。符號引用的校正用來驗證引用是否有效,如果引用無效(例如,如果類不能載入,或者類存在但不含有要引用的域或方法),類檔案校正器就會拋出1個錯誤。
1.4 安全管理器和JAVA API
安全管理器定義了“沙箱”的外部邊界。安全管理器是類java.lang.SecurityManager的子類,它是自訂的。
JAVA API類在採取一些行動時,通常需要安全管理器檢查這個行動是否安全,這些行動包括:
1.接受來自於特定主機的socket串連。
2.修改線程(改變線程優先順序,結束線程等)。
3.開放對於特定主機的socket串連。
4.建立1個新的類載入器。
5.刪除特定的檔案。
6.建立新的過程。
7.程式退出。
8.調用含有本地方法的動態庫。
9.等待串連。
10.從特定的包載入類。
11.給特定的包中添加1個新類。
12.訪問或修改系統特性。
13.訪問特定的系統特性。
14.讀檔案。
15.寫檔案。
由於在執行上述動作前需要安全管理器進行檢查,JAVA API不執行安全管理器建立的安全措施所禁止的任何動作。
JAVA API執行1個可能不安全活動的過程,通常分為2步:首先,JAVA API代碼檢查安全管理器是否已安裝。如果沒有安裝,就無法進行第2步的檢查,則直接執行可能不安全的代碼;如果安裝了,就繼續執行第2步的檢查,調用安全管理器中合適的檢查方法對動作進行檢查,如果動作被禁止,檢查方法就拋出1個安全例外,不再執行不安全的活動;如果動作被允許,檢查方法返回,JAVA API方法繼續執行動作。
結束語
安全的可靠性是和代價成正比的,安全的可靠性越高,為安全付出的代價也越高,因此安全的可靠性也並不是越高越好,應該與被保護的資訊的價值相當。電腦或網路的安全性原則應該是多方面的,僅僅有1個運行下載的JAVA代碼的“沙箱”是不夠的,還應包括人員、機器等本身的安全,例如機器是否設定有口令、僱員是否是商業間諜等。但是JAVA安全模型的好處在於一旦建立,就可以為程式員做很多事情,程式員不必擔心程式是否安全,JAVA的安全結構已經對程式是否安全進行了確定,如果代碼不安全,利用“沙箱”結構就可以保護資訊免受破壞。