標籤:self because 原則 table rar 使用者輸入 gpo 在伺服器 目標
轉載作品,可以轉載,但是請標註出處地址:http://www.cnblogs.com/yiwangzhibujian/p/6207212.html
一、文章的目的
這是一篇對Java安全管理器入門的文章,目的是簡單瞭解什麼是SecurityManager,對管理器進行簡單配置,解決簡單問題。
比如在閱讀源碼的時候,發現這樣的代碼,想瞭解是做什麼的:
1 SecurityManager security = System.getSecurityManager();2 if (security != null) {3 security.checkWrite(name);4 }
亦或者在本機運行正常,在伺服器運行報錯,想解決問題:
1 Exception in thread "main" java.security.AccessControlException: access denied (java.lang.RuntimePermission createSecurityManager)2 at java.security.AccessControlContext.checkPermission(AccessControlContext.java:374)3 at java.security.AccessController.checkPermission(AccessController.java:549)4 at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)5 at java.lang.SecurityManager.<init>(SecurityManager.java:282)6 at xia.study._01Thread.ThreadTest.creatThread1(ThreadTest.java:18)7 at xia.study._01Thread.ThreadTest.main(ThreadTest.java:13)
這時候具備一些SecurityManager的基礎知識還是有必要的。
二、SecurityManager應用情境
當運行未知的Java程式的時候,該程式可能有惡意代碼(刪除系統檔案、重啟系統等),為了防止運行惡意代碼對系統產生影響,需要對啟動並執行代碼的許可權進行控制,這時候就要啟用Java安全管理器。
三、管理器設定檔3.1 預設設定檔
預設的安全管理器設定檔是 $JAVA_HOME/jre/lib/security/java.policy,即當未指定設定檔時,將會使用該配置。內容如下:
1 // Standard extensions get all permissions by default 2 3 grant codeBase "file:${{java.ext.dirs}}/*" { 4 permission java.security.AllPermission; 5 }; 6 7 // default permissions granted to all domains 8 9 grant { 10 // Allows any thread to stop itself using the java.lang.Thread.stop()11 // method that takes no argument.12 // Note that this permission is granted by default only to remain13 // backwards compatible.14 // It is strongly recommended that you either remove this permission15 // from this policy file or further restrict it to code sources16 // that you specify, because Thread.stop() is potentially unsafe.17 // See the API specification of java.lang.Thread.stop() for more 18 // information.19 permission java.lang.RuntimePermission "stopThread";20 21 // allows anyone to listen on un-privileged ports22 permission java.net.SocketPermission "localhost:1024-", "listen";23 24 // "standard" properies that can be read by anyone25 26 permission java.util.PropertyPermission "java.version", "read";27 permission java.util.PropertyPermission "java.vendor", "read";28 permission java.util.PropertyPermission "java.vendor.url", "read";29 permission java.util.PropertyPermission "java.class.version", "read";30 permission java.util.PropertyPermission "os.name", "read";31 permission java.util.PropertyPermission "os.version", "read";32 permission java.util.PropertyPermission "os.arch", "read";33 permission java.util.PropertyPermission "file.separator", "read";34 permission java.util.PropertyPermission "path.separator", "read";35 permission java.util.PropertyPermission "line.separator", "read";36 37 permission java.util.PropertyPermission "java.specification.version", "read";38 permission java.util.PropertyPermission "java.specification.vendor", "read";39 permission java.util.PropertyPermission "java.specification.name", "read";40 41 permission java.util.PropertyPermission "java.vm.specification.version", "read";42 permission java.util.PropertyPermission "java.vm.specification.vendor", "read";43 permission java.util.PropertyPermission "java.vm.specification.name", "read";44 permission java.util.PropertyPermission "java.vm.version", "read";45 permission java.util.PropertyPermission "java.vm.vendor", "read";46 permission java.util.PropertyPermission "java.vm.name", "read";47 };
3.2 設定檔詳解
詳解見第五部分,此處知道有這個設定檔即可。
四、啟動安全管理器
啟動安全管理有兩種方式,建議使用啟動參數方式。
4.1 啟動參數方式
啟動程式的時候通過附加參數啟動安全管理器:
-Djava.security.manager
若要同時指定設定檔的位置那麼樣本如下:
-Djava.security.manager -Djava.security.policy="E:/java.policy"
4.2 編碼方式啟動
也可以通過編碼方式啟動,不過不建議:
System.setSecurityManager(new SecurityManager());
通過參數啟動,本質上也是通過編碼啟動,不過參數啟動使用靈活,項目啟動源碼如下(sun.misc.Launcher):
1 // Finally, install a security manager if requested 2 String s = System.getProperty("java.security.manager"); 3 if (s != null) { 4 SecurityManager sm = null; 5 if ("".equals(s) || "default".equals(s)) { 6 sm = new java.lang.SecurityManager(); 7 } else { 8 try { 9 sm = (SecurityManager)loader.loadClass(s).newInstance();10 } catch (IllegalAccessException e) {11 } catch (InstantiationException e) {12 } catch (ClassNotFoundException e) {13 } catch (ClassCastException e) {14 }15 }16 if (sm != null) {17 System.setSecurityManager(sm);18 } else {19 throw new InternalError(20 "Could not create SecurityManager: " + s);21 }22 }
可以發現將會建立一個預設的SecurityManager;
五、設定檔簡單解釋5.1 配置基本原則
在啟用安全管理器的時候,配置遵循以下基本原則:
- 沒有配置的許可權表示沒有。
- 只能配置有什麼許可權,不能配置禁止做什麼。
- 同一種許可權可多次配置,取並集。
- 統一資源的多種許可權可用逗號分割。
5.2 預設設定檔解釋
第一部分授權:
1 grant codeBase "file:${{java.ext.dirs}}/*" {2 permission java.security.AllPermission;3 };
授權基於路徑在"file:${{java.ext.dirs}}/*"的class和jar包,所有許可權。
第二部分授權:
1 grant { 2 permission java.lang.RuntimePermission "stopThread";3 …… 4 }
這是細粒度的授權,對某些資源的操作進行授權。具體不再解釋,可以查看javadoc。如RuntimePermission的可授權操作經查看javadoc如下:
| 許可權目標名稱 |
許可權所允許的操作 |
允許此許可權所帶來的風險 |
| createClassLoader |
建立類載入器 |
授予該許可權極其危險。能夠執行個體化自己的類載入器的惡意應用程式可能會在系統中裝載自己的惡意類。這些新載入的類可能被類載入器置於任意保護域中,從而自動將該域的許可權授予這些類。 |
| getClassLoader |
類載入器的擷取(即調用類的類載入器) |
這將授予攻擊者得到具體類的載入器的許可權。這很危險,由於攻擊者能夠訪問類的類載入器,所以攻擊者能夠載入其他可用於該類載入器的類。通常攻擊者不具備這些類的存取權限。 |
| setContextClassLoader |
線程使用的上下文類載入器的設定 |
在需要尋找可能不存在於系統類別載入器中的資源時,系統代碼和擴充部分會使用上下文類載入器。授予 setContextClassLoader 許可權將允許代碼改變特定線程(包括系統線程)使用的上下文類載入器。 |
| enableContextClassLoaderOverride |
線程上下文類載入器方法的子類實現 |
在需要尋找可能不存在於系統類別載入器中的資源時,系統代碼和擴充部分會使用上下文類載入器。授予 enableContextClassLoaderOverride 許可權將允許線程的子類重寫某些方法,這些方法用於得到或設定特定線程的上下文類載入器。 |
| setSecurityManager |
設定安全管理器(可能會替換現有的) |
安全管理器是允許應用程式實現安全性原則的類。授予 setSecurityManager 許可權將通過安裝一個不同的、可能限制更少的安全管理器,來允許代碼改變所用的安全管理器,因此可跳過原有安全管理器所強制執行的某些檢查。 |
| createSecurityManager |
建立新的安全管理器 |
授予代碼對受保護的、敏感方法的訪問權,可能會泄露有關其他類或執行堆棧的資訊。 |
| getenv.{variable name} |
讀取指定環境變數的值 |
此許可權允許代碼讀取特定環境變數的值或確定它是否存在。如果該變數含有機密資料,則這項授權是很危險的。 |
| exitVM.{exit status} |
暫停帶有指定退出狀態的 JAVA 虛擬機器 |
此許可權允許攻擊者通過自動強制暫停虛擬機器來發起一次拒絕服務的攻擊。注意:自動為那些從應用程式類路徑載入的全部代碼授予 "exitVM.*" 許可權,從而使這些應用程式能夠自行中止。此外,"exitVM" 許可權等於 "exitVM.*"。 |
| shutdownHooks |
虛擬機器關閉鉤子 (hook) 的註冊與取消 |
此許可權允許攻擊者註冊一個妨礙虛擬機器正常關閉的惡意關閉鉤子 (hook)。 |
| setFactory |
設定由 ServerSocket 或 Socket 使用的通訊端工廠,或 URL 使用的流處理常式工廠 |
此許可權允許代碼設定通訊端、伺服器通訊端、流處理常式或 RMI 通訊端工廠的實際實現。攻擊者可能設定錯誤的實現,從而破壞資料流。 |
| setIO |
System.out、System.in 和 System.err 的設定 |
此許可權允許改變標準系統流的值。攻擊者可以改變 System.in 來監視和竊取使用者輸入,或將 System.err 設定為 "null" OutputStream,從而隱藏發送到 System.err 的所有錯誤資訊。 |
| modifyThread |
修改線程,例如通過調用線程的 interrupt、stop、suspend、resume、setDaemon、setPriority、setName 和 setUncaughtExceptionHandler 方法 |
此許可權允許攻擊者修改系統中任意線程的行為。 |
| stopThread |
通過調用線程的 stop 方法停止線程 |
如果系統已授予代碼訪問該線程的許可權,則此許可權允許代碼停止系統中的任何線程。此許可權會造成一定的危險,因為該代碼可能通過中止現有的線程來破壞系統。 |
| modifyThreadGroup |
修改線程組,例如通過調用 ThreadGroup 的 destroy、getParent、resume、setDaemon、setMaxPriority、stop 和 suspend 方法 |
此許可權允許攻擊者建立線程組並設定它們的運行優先順序。 |
| getProtectionDomain |
擷取類的 ProtectionDomain |
此許可權允許代碼獲得特定代碼源的安全性原則資訊。雖然獲得安全性原則資訊並不足以危及系統安全,但這確實會給攻擊者提供了能夠更好地定位攻擊目標的其他資訊,例如本地檔案名稱等。 |
| getFileSystemAttributes |
擷取檔案系統屬性 |
此許可權允許代碼獲得檔案系統資訊(如調用者可用的磁碟使用量或磁碟空間)。這存在潛在危險,因為它泄露了關於系統硬體設定的資訊以及一些關於調用者寫入檔案特權的資訊。 |
| readFileDescriptor |
讀取檔案描述符 |
此許可權允許代碼讀取與檔案描述符讀取相關的特定檔案。如果該檔案包含機密資料,則此操作非常危險。 |
| writeFileDescriptor |
寫入檔案描述符 |
此許可權允許代碼寫入與描述符相關的特定檔案。此許可權很危險,因為它可能允許惡意代碼傳播病毒,或者至少也會填滿整個磁碟。 |
| loadLibrary.{庫名} |
動態連結指定的庫 |
允許 applet 具有載入機器碼庫的許可權是危險的,因為 Java 安全架構並未設計成可以防止惡意行為,並且也無法在機器碼的層級上防止惡意行為。 |
| accessClassInPackage.{包名} |
當類載入器調用 SecurityManager 的checkPackageAccess 方法時,通過類載入器的 loadClass 方法訪問指定的包 |
此許可權允許代碼訪問它們通常無法訪問的那些包中的類。惡意代碼可能利用這些類協助它們實現破壞系統安全的企圖。 |
| defineClassInPackage.{包名} |
當類載入器調用 SecurityManager 的 checkPackageDefinition 方法時,通過類載入器的 defineClass 方法定義指定的包中的類。 |
此許可權允許代碼在特定包中定義類。這樣做很危險,因為具有此許可權的惡意代碼可能在受信任的包中定義惡意類,比如 java.security 或 java.lang。 |
| accessDeclaredMembers |
訪問類的已聲明成員 |
此許可權允許代碼查詢類的公用、受保護、預設(包)訪問和私人的欄位和/或方法。儘管代碼可以訪問私人和受保護欄位和方法名稱,但它不能訪問私人/受保護欄位資料並且不能調用任何私人方法。此外,惡意代碼可能使用該資訊來更好地定位攻擊目標。而且,它可以調用類中的任意公用方法和/或訪問公用欄位。如果代碼不能用這些方法和欄位將對象強制轉換為類/介面,那麼它通常無法調用這些方法和/或訪問該欄位,而這可能很危險。 |
| queuePrintJob |
列印工作請求的開始 |
這可能向印表機輸出敏感資訊,或者只是浪費紙張。 |
| getStackTrace |
擷取另一個線程的堆棧追蹤資訊。 |
此許可權允許擷取另一個線程的堆棧追蹤資訊。此操作可能允許執行惡意代碼監視線程並發現應用程式中的弱點。 |
| setDefaultUncaughtExceptionHandler |
線上程由於未捕獲的異常而突然終止時,設定將要使用的預設處理常式 |
此許可權允許攻擊者註冊惡意的未捕獲例外處理常式,可能會妨礙線程的終止 |
| Preferences |
表示得到 java.util.prefs.Preferences 的訪問權所需的許可權。java.util.prefs.Preferences 實現了使用者或系統的根,這反過來又允許擷取或更新 Preferences 持久內部儲存中的操作。 |
如果運行此代碼的使用者具有足夠的讀/寫內部儲存的 OS 特權,則此許可權就允許使用者讀/寫優先順序內部儲存。實際的內部儲存可能位於傳統的檔案系統目錄中或註冊表中,這取決於平台 OS。 |
5.3 可配置項詳解
當大量設定的時候,有三種模式:
- directory/ 表示directory目錄下的所有.class檔案,不包括.jar檔案
- directory/* 表示directory目錄下的所有的.class及.jar檔案
- directory/- 表示directory目錄下的所有的.class及.jar檔案,包括子目錄
可以通過${}來引用系統屬性,如:
"file:${{java.ext.dirs}}/*"六、問題解決
當出現關於安全管理的報錯的時候,基本有兩種方式來解決。
6.1 取消安全管理器
一般情況下都是無意啟動安全管理器,所以這時候只需要把安全管理器進行關閉,去掉啟動參數即可。
6.2 增加相應許可權
若因為沒有許可權報錯,則報錯資訊中會有請求的許可權和請求什麼許可權,如下:
Exception in thread "main" java.security.AccessControlException: access denied (java.io.FilePermission E:\pack\a\a.txt write)
上面例子,請求資源E:\pack\a\a.txt,的FilePermission的寫入權限沒有,因此被拒絕。
也可以開放所有許可權:
1 grant { 2 permission java.security.AllPermission;3 };
java基礎系列--SecurityManager入門(轉)