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

探索Java應用程序的安全需求

2013-11-23 19:12:22  來源: Java核心技術 

  我們知道維護應用程序的安全並不簡單不過我們也清楚完全可以采取一些措施來緩解安全缺陷帶來的風險如果我們是網絡工程師就可以將精力投入網絡分區和包過濾器方面的知識如果用C語言編程我們就保護程序以防止緩沖區溢出如果用Java編程我們就考慮在安全管理器的保護之下運行應用程序每種情況下我們都用最佳實踐中獲得的知識來戰勝無意造成的系統故障

  Java應用程序的安全條款是本文所討論內容的依據我們的討論把重點放在Java安全管理器方面這是Java安全架構主題中的一個很小的子集

  安全管理器是 javalangSecurityManager類或擴展自該類的一個類且它在運行時檢查某些應用程序操作的權限一旦受到安全管理器的控制應用程序就只能執行那些由相關安全策略特別准許的操作默認情況下該策略是在純文本 策略文件 中指定的所涉及的操作包括將文件寫入特定目錄寫協同屬性建立到特定主機的網絡連接這裡列出的只是其中的一小部分僅用一個簡單的JVM命令行選項即可迫使Java應用程序在一個安全管理器下運行而且安全策略文件可以由任何文本編輯器輕松創建

  雖然編輯這樣一個安全策略文件並添加各種相關規則並不難不過獲得策略制訂權會更具有挑戰性而且盡管沒人可以為我們提供這樣的策略制訂權但工具能幫助我們理解那個策略應該是什麼開發並使用這樣的工具是我們即將著手的工作一旦我們有了它所發現的更寬泛更細粒度的策略就可以在開發產品運行時策略時將其作為起點或者為了更好地理解和認識應用程序的安全需求而研究它

  本文的核心代碼是一個通用的安全管理器要使用它就需要有Sun的JSE JVM 為了從特定的Java系統類中獲得私有成員數據從安全管理器對Java Reflecition API的依賴性中派生JSE (Java Standard Edition)的需求由於缺乏對管理器運行所需的某有成員數據的公共訪問因而需要使用Reflection API使用私有成員反射的後果就是管理器與其運行所在的的JVM內部緊密相關但這算不上什麼嚴重的後果因為管理器是一個開發工具而不是產品組件一旦管理器提出一個策略制訂起點我們就可以采用那個策略並在任何現代JVM上運行遵從它的應用程序

默認Java安全管理器

  現代文獻中所編寫討論及引用的絕大多數Java代碼都代表著在不受安全管理器限制的情況下運行的應用程序因而這種應用程序對所有的機器資源包括磁盤網絡和應用程序關閉等有完全訪權限不過這種寬泛的訪問權限很容易受到限制僅通過在JVM命令行上設置Djavasecuritymanager 選項就可以迫使應用程序在默認的Java安全管理器下運行

  看一下下面這個簡單的應用程序其目的是讀取和打印用戶的主目錄

  public class PrintHome { public static void main(String[] argv) { Systemoutprintln(SystemgetProperty(userhome)); } }

  編譯代碼並讓它在默認安全管理器的限制下運行

  $ cd $HOME/Projects/CustomSecurityManager $ javac PrintHomejava $ java Djavasecuritymanager PrintHome Exception in thread main javasecurityAccessControlException: access denied (javautilPropertyPermission userhome read) at PrintHomemain(PrintHomejava:)

  上面的應用程序中未能獲得並打印 userhome屬性而且出於代碼可讀性方面的考慮我們省略了棧跟蹤中的絕大部分該應用程序未能執行是因為隨著缺省安全策略運行的缺省安全管理器禁止訪問userhome屬性這個特權必須在運行策略文件中具體給出

  創建一個包含單一規則的策略文件policytxt

  grant codeBase file:/home/cid/Projects/CustomSecurityManager/{ permission javautilPropertyPermission userhome read;

  重新運行該應用程序對策略文件的引用解決了對userhome的讀訪問問題

  $ java Djavasecuritypolicy=policytxt Djavasecuritymanager PrintHome /home/cid

  注意到我們通過設置系統屬性javasecuritypolicy=policytxt來將JVM引用到策略文件中我們還假定PrintHome類位於/home/cid/Projects/CustomSecurityManager目錄中policytxt 文件中的規則允許任何包含在那個目錄中文件的代碼去讀取系統屬性userhome結果規則允許PrintHome像預期的那樣運行包含代碼的文件就稱其為代碼庫因此代碼庫就是一個類文件或jar文件

安全策略剖析工具ProfilingSecurityManager

  正如我們前面提到的創建一個安全策略文件並不難即使像 策略池 這樣的實用工具可提供協助而且在策略文件中允許有很強大的 語法快捷方式它允許創建有表現力的高效的規則使用這種高級規則符號我們可以指定比如說遞歸引用整個目錄樹的代碼庫URL這種遞歸 URL 規范不僅非常有用方便而且能夠向代碼閱讀者屏蔽掉應用程序對資源需求的真實細粒度的深度這正是我們尋求的細節

  因此我們的目標是雙方面的首先我們希望在安全策略的限制下運行應用程序或者至少說我們希望確定該應用程序的安全需求其次我們需要一種程序性的方法來確定那些需求

  帶著這些目標我們來介紹定制的安全管理器secmgrProfilingSecurityManager這個類擴展了javalangSecurityManager但未實施本文至此所討論的安全策略不過據說它會實施此類安全策略如果應用程序可以獲得在運行時訪問它所請求的一切內容的權利那麼我們可接受這種說法將其轉換成運行時安全策略的起點這樣一來我們的兩個目標就都可以實現

  為了使用ProfilingSecurityManager首先編譯並有策略地將其放在自己的jar文件中(源代碼可以在 資源 這一節找到)單獨將ProfilingSecurityManager放到它自己的jar文件中將允許我們過濾並取消由一些源於它自己jar文件代碼庫的活動所產生的輸出規則ProfilingSecurityManager通過以下代碼可以知道自己獨有的代碼庫

  if( urltoString()equals(thisCodeSourceURLString) ) { return null; }

  從而可以避免自身報告同時編譯該工具並將其制成 jar

  $ mkdir p classes lib $ rm rf classes/* lib/* $ javac d classes ProfilingSecurityManagerjava $ jar cf lib/psmjar C classes secmgr/manager $ rm rf classes/secmgr/manager

  在我們繼續講下去之前應該講一下如何激活ProfilingSecurityManager 使之成為應用程序安全管理器回想前面我們通過設置一個無對應屬性值的系統屬性Djavasecuritymanager來促使應用程序在缺省的Java安全管理器限制下運行我們需要進一步推廣這種措施並通過給系統屬性賦值將定制安全管理器指定為安全管理器Djavasecuritymanager=secmgrProfingSecurityManager因此被激活之後ProfilingSecurityManager將寫入Systemout策略文件中需要的這些規則允許應用程序在無需拋出安全違反異常的情況下運行然而這些規則不能被處理成最終可用的形式直到應用程序在ProfilingSecurityManager下完成其運行為止為什麼呢?因為我們知道僅在那時應用程序才完成了以檢查資源為目的的請求訪問所以為了使應用程序在ProfilingSecurityManager下完成運行時處理並整理這些規則我們提供了一個簡單的Perl腳本parsecodebasepl(見 示例代碼)以便以易於閱讀的格式聚集格式化輸出由代碼庫分類並組合的規則

  好了我們現在用指定為安全管理器的ProfilingSecurityManager 和由parsecodebasepl處理的規則輸出來運行簡單的 PrintHome 程序會產生如下結果

  $ java cp :lib/psmjar Djavasecuritymanager=secmgrProfilingSecurityManager
PrintHome > rawout $ parsecodebasepl < rawout > policytxt $ cat policytxt grant codeBase file:/home/cid/Projects/CustomSecurityManager/ { permission javautilPropertyPermission userhome read; }; $ java cp Djavasecuritymanager Djavasecuritypolicy=policytxt PrintHome /home/cid

  我們再次看到ProfilingSecurityManager同時滿足了我們的兩個設計目標


    我們的應用程序使用定義良好特定於應用程序的策略在安全管理器下運行
    我們通過編程的方式確定了那個策略

  ProfilingSecurityManager是如何工作的呢?ProfilingSecurityManager重寫了javalangSecurityManager 的 checkPermission 方法的兩個版本這個方法的兩種形式是用於檢查應用程序請求訪問哪個資源或活動的中央樞紐被重寫的checkPermission方法總是不需丟棄異常而返回——本意是允許訪問—不過條件是它們必須建立並輸出規則以允許為其操作負責的活動能首先得到調用

一個更復雜的例子剖析Tomcat Web應用程序

  先將那個簡單實例暫且擱置我們來觀察ProfilingSecurityManager的一個復雜應用剖析Tomcat Web應用程序通過傳送 security 選項到標准啟動腳本Tomcat可在默認Java安全管理器下運行

  $ $CATALINA_HOME/bin/startupsh security

  傳送 security 選項到startupsh 會導致對擁有同樣security 選項的$CATALINA_HOME/bin/catalinash 的調用$CATALINA_HOME/bin/catalinash 實際上是調用Java來運行Tomcat 引導類orgapachecatalinastartupBootstrap 的一種腳本在這種情況下將進一步受到$CATALINA_HOME/conf/catalinapolicy中所規定默認策略的限制如果我們將調用停留在此處Tomcat將在由默認提供策略所限制的默認Java安全管理器下運行不過為了剖析Tomcat以及它可能包含的Web應用程序我們需要稍微多做一些工作為了用ProfilingSecurityManager剖析Web應用程序我們必須開發新的Tomcat啟動腳本新啟動腳本是一個臨時設備而且僅用於剖析之後被廢棄

  為 $CATALINA_HOME/bin/catalinash做一個備份副本在腳本頂部附近的 $CATALINA_HOME/bin/catalinash 中近插入shell命令set x 然後啟動Tomcat保存顯示的shell執行命令到一個包含臨時啟動腳本的文件中停止Tomcat編輯臨時腳本指定ProfilingSecurityManager 為安全管理器並修改類路徑來定位它

  以下是在Linux操作系統下的Tomcat 我們為使用 ProfilingSecurityManager進行編輯之前的臨時啟動腳本略經調整和格式化

  #!/bin/sh log=$CATALINA_HOME/logs/catalinaout /java/jdk/jdk_/bin/java \ Djavautilloggingmanager=orgapachejuliClassLoaderLogManager \ Djnfigfile=/home/tomcat/tomcat/conf/loggingproperties \ Djavaendorseddirs=/home/tomcat/tomcat/common/endorsed \ classpath :/home/tomcat/tomcat/bin/bootstrapjar:\ /home/tomcat/tomcat/bin/commonsloggingapijar \ Djavasecuritymanager \ Djavasecuritypolicy==/home/tomcat/tomcat/conf/catalinapolicy \ Dcatalinabase=/home/tomcat/tomcat \ Dcatalinahome=/home/tomcat/tomcat \ Djavaiotmpdir=/home/tomcat/tomcat/temp \ orgapachecatalinastartupBootstrap start >> $log \ >& &

  為了使用 ProfilingSecurityManager而進行編輯後該啟動腳本如下所示

  #!/bin/sh log=$CATALINA_HOME/logs/catalinaout PATHTOPSM=$HOME/lib/psmjar # make sure the profiler jar file is here /java/jdk/jdk_/bin/java \ Djavautilloggingmanager=orgapachejuliClassLoaderLogManager \ Djnfigfile=/home/tomcat/tomcat/conf/loggingproperties \ Djavaendorseddirs=/home/tomcat/tomcat/common/endorsed \ classpath $PATHTOPSM:/home/tomcat/tomcat/bin/bootstrapjar:\ /home/tomcat/tomcat/bin/commonsloggingapijar \ Djavasecuritymanager=secmgrmanagerProfilingSecurityManager \ Djavasecuritypolicy==/home/tomcat/tomcat/conf/catalinapolicy \ Dcatalinabase=/home/tomcat/tomcat \ Dcatalinahome=/home/tomcat/tomcat \ Djavaiotmpdir=/home/tomcat/tomcat/temp \ orgapachecatalinastartupBootstrap start >> $log \ >& &

  這兩個腳本的不同點在於新臨時版本


    增加了類路徑以指向ProfilingSecurityManager類的位置即$HOME/lib/psmjar 中
    Djavasecuritymanager參數中指定ProfilingSecurityManager為安全管理器

  現在我們可以開始剖析了用臨時啟動腳本啟動 Tomcat 促使相關web應用程序覆蓋那些會在生產中被覆蓋的代碼以此考驗它們的速度用代碼覆蓋Web應用程序是一個公認的難以實現的命令而且可能僅有部分可以實現停止Tomcat通過parsecodebasepl運行$CATALINA_HOME/logs/catalinaout 如下所示同時將處理過的規則保存到到 policytxt中

  $ parsecodebasepl < $CATALINA_HOME/logs/catalinaout > policytxt

  清單 處理由Tomcat和其中所包含的任意已執行Web應用程序生成的規則

  注意 ProfilingSecurityManager只能為那些在剖析過程中執行的代碼生成規則它會探測理論上可以在隨機運行實例中觸及的所有代碼分支而不檢查類文件中的字節碼這樣的字節碼分析可能是將來的一個研究領域我們將加以補充但它不能替換由 ProfilingSecurityManager 做的運行時分析

  對隨Tomcat提供的策略文件 $CATALINA_HOME/conf/catalinapolicy 的檢查表明Tomcat  (Catalina)系統代碼庫獲得了所有平台的權限事實上ProfilingSecurityManager會發現Tomcat系統類的這些相同規則但會以細粒度的方式指定它們ProfilingSecurityManager發現的關於Tomcat系統類的規則應從policytxt中手動刪除

  刪除了 Tomcat系統規則後仍然保留在policytxt中的規則就是生產安全策略的起點這些規則表示Web應用程序的安全需求應仔細檢查這些規則中的每一條以了解其用途並確保它與我們的應用程序目標相一致確信有好的草案策略時為$CATALINA_HOME/conf/catalinapolicy做一個備份副本並從 policytxt中將新草案規則整合進來然後用security 選項集回復到原來的 Tomcat 啟動腳本繼續測試

結束語

  在Java安全管理器下運行應用程序可以增加代碼的健壯性而且雖然獲得安全策略制訂權是一項艱巨的挑戰不過這樣做會讓我們安心因為代碼將在我們所規定的安全約束的限制下運行ProfilingSecurityManager可以為我們提供對應用程序所請求訪問的資源集的充分可見度從而幫助我們獲得策略制訂權

資源


    示例代碼 本文引用的示例代碼包括 ProfilingSecurityManager 和 parsecodebasepl
    Subverting Java Access Protection for Unit Testing 主要討論Java 映射基礎
    Tomcat: The Definitive Guide 額外的一些Tomcat 安全性的詳細介紹
    Java Permissions list
    Java 安全性架構文檔

  作者簡介

Mark Petrovic是一位技術專家和軟件開發人員


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