熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

Java安全

2013-11-23 19:48:23  來源: Java高級技術 

  Java
  如果要用Java來開發安全程序坦白地說第一步(在學習了Java之後)就是要閱讀兩本有關Java安全的教材即Gong []和McGraw [](後一本特別要看第節)還應該看一下Sun發布的安全代碼指南有一組描述Java安全模型的幻燈片可以從 免費獲取
  
  下面是基於Gong []McGraw []和Sun的指南的若干關鍵要點
  
  
  不要使用公共域或變量把它們聲明為私有的並提供訪問函數以限制對它們的訪問
  
  除非有很好的理由把方法都設為私有的(如果確實沒這樣做說清楚其理由)這些非私有的方法必須保護自己因為它們可能會接收到受污染的數據(除非已經用其它方式對它們進行了保護)
  
  避免使用靜態域變量這樣的變量附著在類(而非類的實例)上而類可以被其它類所定位其結果就是靜態域變量可以被其它類找到因此很難保證它們的安全
  
  永遠不要把可變對象返回給潛在有惡意的代碼(因為代碼可能會改變它)注意數組是可變的(即使數組的內容不可變)所以不要返回一個含有敏感數據的內部數組的引用
  
  永遠不要直接保存用戶給定的可變對象(包括對象的數組)否則用戶可以把對象交給安全代碼讓安全代碼檢查對象並在安全代碼試圖使用數據時改變數據應該在內部存儲數組前復制它們而且要小心(例如警惕用戶編寫的復制例程)
  
  不要依賴於初始化有好幾種方法給未初始化的對象分配內存
  
  除非有很好的理由應該使每件事都是確定的如果某個類或方法不是確定的攻擊者就可以用某種危險而無法預知的方法來擴展它注意作為安全性的交換這會帶來可擴展性的喪失
  
  不要在安全性上依賴包的范圍若干類如javalang缺省是關閉的而且某些Java虛擬機(JVM)會讓你關閉其它包否則Java類是沒有關閉的因此攻擊者可以向包中引入一個新類並用此新類來訪問你以為保護了的信息
  
  不要使用內部類在內部類轉換為字節代碼時內部類會轉換為可以訪問包中任意類的類更糟的是被封裝類的私有域靜悄悄地變成非私有的允許內部類訪問!
  
  最小化特權如果可能完全不要請求任何特殊的許可McGraw更進一步地推薦不要標記任何代碼我認為可以標記代碼(這樣用戶可以決定只有列表上的發送者可以運行標記過的代碼但在編寫程序時要使程序不需要沙箱設置之外的權限如果一定要有更大的權限審讀代碼就會特別困難
  
  如果一定要標記代碼應該把它們都放在一個檔案文件裡這裡最好引用McGraw []的原文
  
  此規則的目的是防止攻擊者使用混合匹配攻擊構建新applet或庫把某些標記類與有惡意的類連接在一起或者把根本意識不到會被一起使用的標記類連接在一起通過把一組類標記在一起就可以使這種攻擊更困難現有的代碼標記系統在防止混合匹配攻擊上做得還不夠所以這一規則還不能完全防止此類攻擊但使用單個答案沒什麼壞處
  
  應該使類不可被復制Java的類復制機制允許攻擊者不運行構建函數就實例化某個類要使類不可被復制只要在每個類裡定義如下方法 public final void clone() throws javalangCloneNotSupportedException {
   throw new javalangCloneNotSupportedException();
   }
  
  
  如果確實需要使類可被復制那麼可以采用幾個保護措施來防止攻擊者重新定義復制方法如果是定義自己的復制方法只需要使它是確定的如果不是定義自己的復制方法至少可以通過增加如下內容來防止復制方法被惡意地重載 public final void clone() throws javalangCloneNotSupportedException {
   superclone();
   }
  
  
  應該使類不可序列化系列化運行攻擊者看到對象的內部狀態甚至私有部分要防止這一點需要在類裡增加如下方法 private final void writeObject(ObjectOutputStream out)
   throws javaioIOException {
   throw new javaioIOException(Object cannot be serialized);
   }
  
  
  甚至在序列化沒問題的情況下也應該對包含直接處理系統資源的域和包含與地址空間有關信息的域使用臨時關鍵字否則解除類的序列化就會允許不適當的訪問可能還需要把敏感信息標識為臨時的
  
  如果對類定義了自己的序列化方法就不應該把內部數組傳遞給需要數組的DataInput/DataOuput方法其理由在於所有的DataInput/DataOuput方法都可以被重載如果某個可序列化的類向某個DataOutput(write(byte [] b))方法直接傳遞了一個私有數組那麼攻擊者就可以構建子類ObjectOutputStream並重載write(byte [] b)方法從而可以訪問並修改那個私有數組注意缺省的序列化並沒有把私有字節數組域暴露給DataInput/DataOutput字節數組方法
  
  應該使類不可被解除序列化即使類不可被序列化它依然可以被解除序列化攻擊者可以構建一個字節序列使它碰巧是被解除序列化的某個類實例而且具有攻擊者選定的值換句化話說解除序列化是一種公共的構建函數允許攻擊者選擇對象的狀態 顯然是一個危險的操作! 要防止這一點需要在類裡增加如下方法 private final void readObject(ObjectInputStream in)
   throws javaioIOException {
   throw new javaioIOException(Class cannot be deserialized);
   }
  
  
  不要通過名稱來比較類畢竟攻擊者可以用相同的名稱定義類而且一不小心就會授予這些類不恰當的權限因此下面是一個判斷某個對象是否含有某個給定類的錯誤方法的例子 if (objgetClass()getName()equals(Foo)) {
  
  
  如果要判斷兩個對象是否含有完全相同的類不要對雙方使用getClass()並使用==操作符進行比較而應該使用如下形式 if (agetClass() == bgetClass()) {
  
  如果確實需要判斷某個對象是否含有某個給定類名需要嚴格按照規范並確保使用當前名稱空間(當前類的ClassLoader所在名稱空間)因此應該使用如下形式 if (objgetClass() == thisgetClassLoader()loadClass(Foo)) {
  
  本原則來自McGraw和Felten而且確實是個好原則要補充的是盡可能地避免比較類值通常是個好注意通常最好是盡力設計類的方法和接口從而完全不必要做這些事盡管如此實際上無法完全做到所以知道這些技巧還是很重要的
  
  不要把秘密(密鑰密碼或算法)存儲在代碼或數據裡有惡意的JVM可以迅速看到這一數據打亂代碼並不能在認真的攻擊者面前實際隱藏代碼

From:http://tw.wingwit.com/Article/program/Java/gj/201311/27480.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.