dwys0343

          技術整理

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            1 Posts :: 16 Stories :: 0 Comments :: 0 Trackbacks

          本文是來自 Sun 官方站點的一篇關于如何編寫安全的 Java 代碼的指南 , 開發者在編寫一般代碼時,可以參照本文的指南:

          ????????? 靜態字段
          ?????????
          縮小作用域
          ?????????
          公共方法和字段
          ?????????
          保護包
          ?????????equals
          方法
          ?????????
          如果可能使對象不可改變
          ?????????
          不要返回指向包含敏感數據的內部數組的引用
          ?????????
          不要直接存儲用戶提供的數組
          ?????????
          序列化
          ?????????
          原生函數
          ?????????
          清除敏感信息

          靜態字段
          ?????????
          避免使用非 final 的公共靜態變量
          應盡可能地避免使用非 final 公共靜態變量,因為無法判斷代碼有無權限改變這些變量值。
          ?????????
          一般地,應謹慎使用易變的靜態狀態,因為這可能導致設想中相互獨立的子系統之間發生不可預知的交互。

          縮小作用域
          作為一個慣例,盡可能縮小方法和字段的作用域。檢查包訪問權限的成員能否改成私有的,保護類型的成員可否改成包訪問權限的或者私有的,等等。

          公共方法 / 字段
          避免使用公共變量,而是使用訪問器方法訪問這些變量。用這種方式,如果需要,可能增加集中安全控制。
          對于任何公共方法,如果它們能夠訪問或修改任何敏感內部狀態,務必使它們包含安全控制。
          參考如下代碼段,該代碼段中不可信任代碼可能設置 TimeZone 的值:

          private static TimeZone??defaultZone = null;

          ??????public static synchronized void setDefault(TimeZone zone)
          ??????{
          ??????????defaultZone = zone;
          ??????}



          保護包
          有時需要在全局防止包被不可信任代碼訪問,本節描述了一些防護技術:
          ?????????
          防止包注入:如果不可信任代碼想要訪問類的包保護成員,可以嘗試在被攻擊的包內定義自己的新類用以獲取這些成員的訪問權。防止這類攻擊的方式有兩種:
          1.????????
          通過向 java.security.properties 文件中加入如下文字防止包內被注入惡意類。

          ??????????...
          package.definition=Package#1 [,Package#2,...,Package#n]

          ...



          這會導致當試圖在包內定義新類時類裝載器的 defineClass 方法會拋出異常,除非賦予代碼一下權限:

          ...
          RuntimePermission("defineClassInPackage."+package)

          ...



          2.????????
          另一種方式是通過將包內的類加入到封裝的 Jar 文件里。
          (參看 http://java.sun.com/j2se/sdk/1.2/docs/guide/extensions/spec.html
          ????
          通過使用這種技巧,代碼無法獲得擴展包的權限,因此也無須修改 java.security.properties 文件。
          ?????????
          防止包訪問:通過限制包訪問并僅賦予特定代碼訪問權限防止不可信任代碼對包成員的訪問。通過向 java.security.properties 文件中加入如下文字可以達到這一目的:

          ??????...
          package.access=Package#1 [,Package#2,...,Package#n]

          ...



          這會導致當試圖在包內定義新類時類裝載器的 defineClass 方法會拋出異常,除非賦予代碼一下權限:

          ...
          RuntimePermission("defineClassInPackage."+package)

          ...



          如果可能使對象不可改變
          如果可能,使對象不可改變。如果不可能,使得它們可以被克隆并返回一個副本。如果返回的對象是數組、向量或哈希表等,牢記這些對象不能被改變,調用者修改這些對象的內容可能導致安全漏洞。此外,因為不用上鎖,不可改變性能夠提高并發性。參考 Clear sensitive information 了解該慣例的例外情況。

          不要返回指向包含敏感數據的內部數組的引用
          該慣例僅僅是不可變慣例的變型,在這兒提出是因為常常在這里犯錯。即使數組中包含不可變的對象(如字符串),也要返回一個副本這樣調用者不能修改數組中的字符串。不要傳回一個數組,而是數組的拷貝。

          不要直接在用戶提供的數組里存儲
          該慣例僅僅是不可變慣例的另一個變型。使用對象數組的構造器和方法,比如說 PubicKey 數組,應當在將數組存儲到內部之前克隆數組,而不是直接將數組引用賦給同樣類型的內部變量。缺少這個警惕,用戶對外部數組做得任何變動(在使用討論中的構造器創建對象后)可能意外地更改對象的內部狀態,即使該對象可能是無法改變的

          序列化
          當對對象序列化時,直到它被反序列化,它不在 Java 運行時環境的控制之下,因此也不在 Java 平臺提供的安全控制范圍內。
          在實現 Serializable 時務必將以下事宜牢記在心:
          ?????????transient

          在包含系統資源的直接句柄和相對地址空間信息的字段前使用 transient 關鍵字。 如果資源,如文件句柄,不被聲明為 transient ,該對象在序列化狀態下可能會被修改,從而使得被反序列化后獲取對資源的不當訪問。

          ?????????
          特定類的序列化 / 反序列化方法

          為了確保反序列化對象不包含違反一些不變量集合的狀態,類應該定義自己的反序列化方法并使用 ObjectInputValidation 接口驗證這些變量。

          如果一個類定義了自己的序列化方法,它就不能向任何 DataInput/DataOuput 方法傳遞內部數組。所有的 DataInput/DataOuput 方法都能被重寫。注意默認序列化不會向 DataInput/DataOuput 字節數組方法暴露私有字節數組字段。

          如果 Serializable 類直接向 DataOutput(write(byte [] b)) 方法傳遞了一個私有數組,那么黑客可以創建 ObjectOutputStream 的子類并覆蓋 write(byte [] b) 方法,這樣他可以訪問并修改私有數組。下面示例說明了這個問題。
          你的類 :

          ??????public class YourClass implements Serializable {

          ????????????private byte [] internalArray;
          ....
          private synchronized void writeObject(ObjectOutputStream stream) {
          ?...

          ?????????????? stream.write(internalArray);
          ????????????????...
          }
          }



          黑客代碼

          ?????? public class HackerObjectOutputStream extends ObjectOutputStream{
          ????????????public void write (byte [] b) {
          ?????????????? Modify b
          ??????}
          }
          ?...
          ???????????? YourClass yc = new YourClass();
          ??????????????...
          ?
          ???????????? HackerObjectOutputStream hoos = new HackerObjectOutputStream();

          ??????????????hoos.writeObject(yc);



          ?????????
          字節流加密

          保護虛擬機外的字節流的另一方式是對序列化包產生的流進行加密。字節流加密防止解碼或讀取被序列化的對象的私有狀態。如果決定加密,應該管理好密鑰,密鑰的存放地點以及將密鑰交付給反序列化程序的方式等。

          ?????????
          需要提防的其他事宜

          如果不可信任代碼無法創建對象,務必確保不可信任代碼也不能反序列化對象。切記對對象反序列化是創建對象的另一途徑。
          比如說,如果一個 applet 創建了一個 frame ,在該 frame 上創建了警告標簽。如果該 frame 被另一應用程序序列化并被一個 applet 反序列化,務必使該 frame 出現時帶有同一個警告標簽。

          原生方法
          應從以下幾個方面檢查原生方法:
          ?????????
          它們返回什么
          ?????????
          它們需要什么參數
          ?????????
          它們是否繞過了安全檢查
          ?????????
          它們是否是公共的,私有的等
          ?????????
          它們是否包含能繞過包邊界的方法調用,從而繞過包保護

          清除敏感信息
          當保存敏感信息時,如機密,盡量保存在如數組這樣的可變數據類型中,而不是保存在字符串這樣的不可變對象中,這樣使得敏感信息可以盡早顯式地被清除。不要指望 Java 平臺的自動垃圾回收來做這種清除,因為回收器可能不會清除這段內存,或者很久后才會回收。盡早清除信息使得來自虛擬機外部的堆檢查攻擊變得困難。

          posted on 2006-12-29 22:37 特蘭克斯 閱讀(184) 評論(0)  編輯  收藏 所屬分類: J2SE
          主站蜘蛛池模板: 密云县| 巩留县| 鲁甸县| 济南市| 莲花县| 绥宁县| 逊克县| 尼勒克县| 云阳县| 保山市| 濮阳市| 邻水| 丰宁| 卢龙县| 孟连| 玛纳斯县| 平利县| 浮山县| 黔西| 沈阳市| 镇宁| 花莲县| 云龙县| 孝感市| 葫芦岛市| 河间市| 化隆| 资源县| 开鲁县| 雅江县| 通州区| 芜湖县| 仲巴县| 宣武区| 海伦市| 丹江口市| 格尔木市| 定西市| 吉木乃县| 海原县| 鞍山市|