保衛 Java 應用程式的安全沙箱機制你需要了解一下
如果你經常閱讀原始碼,你會發現 Java 的原始碼中到處都有類似於下面這一段程式碼
class File {
// 判斷一個磁碟檔案是否存在
public boolean exists() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(path);
}
...
}
}
這明顯是一個安全檢查程式碼,檢查的是你是否有訪問磁碟路徑的許可權,為什麼 Java 語言需要這樣的安全檢查程式碼呢?我們再看看客戶端套接字的 connect 函式原始碼,它需要檢查使用者是否有connect 某個網路地址的許可權
class Socket {
public void connect(SocketAddress endpoint, int timeout) {
...
SecurityManager security = System.getSecurityManager();
if (security != null) {
if (epoint.isUnresolved())
security.checkConnect(epoint.getHostName(), port);
else
security.checkConnect(addr.getHostAddress(), port);
}
}
...
}
}
再看服務端套接字的原始碼,它會檢查埠的監聽許可權
class ServerSocket {
public void bind(SocketAddress endpoint, int backlog) {
...
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkListen(epoint.getPort());
...
}
}
似乎所有和 IO 操作有關的方法呼叫都需要進行安全檢查。跟 IO 操作相關的許可權檢查似乎還可以理解,不是所有的 IO 資源使用者程式都是可以隨意訪問的。但是連環境變數都不讓隨意讀,而且限制的還不是所有環境變數,而是某個具體的環境變數,這安全檢查是不是有點過了?
class System {
public static String getenv(String name) {
SecurityManager sm = getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("getenv."+name));
}
return ProcessEnvironment.getenv(name);
}
}
這是因為 Java 的安全檢查管理器和作業系統的許可權檢查不是一個概念,Java 編寫的不只是服務端應用程式,它還可以作為客戶端跑在瀏覽器上(Applet),它還可以以 app 的形式跑在手機上(J2ME),針對不同的平臺 JVM 會使用不同的安全策略。對於 Applet 而言,受限尤其嚴苛,通常都不允許 Applet 來操作本地檔案。待 Java 的安全檢查透過後執行具體的 IO 操作時,作業系統還會繼續進行許可權檢查。
我們平時在本地執行 java 程式時通常都不會預設開啟安全檢查器,需要執行 jvm 引數才會開啟
$ java -Djava.security.manager xxx
$ java -Djava.security.manager -DDjava.security.policy="${policypath}"
因為安全限制條件可以定製,所以還需要提供具體的安全策略檔案路徑,預設的策略檔案路徑是 JAVA_HOME/jre/lib/security/java.policy,下面讓我們來看看這個檔案裡都寫了些什麼
// 內建擴充套件庫授權規則
// 表示 JAVA_HOME/jre/lib/ext/ 目錄下的類庫可以全權訪問任意資源
// 包含 javax.swing.*, javax.xml.*, javax.crypto.* 等等
grant codeBase "file:${{java.ext.dirs}}/*" {
permission java.security.AllPermission;
};
// 其它類庫授權規則
grant {
// 允許執行緒呼叫自己的 stop 方法自殺
permission java.lang.RuntimePermission "stopThread";
// 允許程式監聽 localhost 的隨機可用埠,不允許隨意訂製埠
permission java.net.SocketPermission "localhost:0", "listen";
// 限制獲取系統屬性,下面一系列的配置都是隻允許讀部分內建屬性
permission java.util.PropertyPermission "java.version", "read";
permission java.util.PropertyPermission "java.vendor", "read";
permission java.util.PropertyPermission "java.vendor.url", "read";
permission java.util.PropertyPermission "java.class.version", "read";
permission java.util.PropertyPermission "os.name", "read";
permission java.util.PropertyPermission "os.version", "read";
permission java.util.PropertyPermission "os.arch", "read";
permission java.util.PropertyPermission "file.separator", "read";
permission java.util.PropertyPermission "path.separator", "read";
permission java.util.PropertyPermission "line.separator", "read";
permission java.util.PropertyPermission "java.specification.version", "read";
permission java.util.PropertyPermission "java.specification.vendor", "read";
permission java.util.PropertyPermission "java.specification.name", "read";
permission java.util.PropertyPermission "java.vm.specification.version", "read";
permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
permission java.util.PropertyPermission "java.vm.specification.name", "read";
permission java.util.PropertyPermission "java.vm.version", "read";
permission java.util.PropertyPermission "java.vm.vendor", "read";
permission java.util.PropertyPermission "java.vm.name", "read";
};
grant 如果提供了 codeBase 引數就是針對具體的類庫來配置許可權規則,如果沒有指定 codeBase 就是針對所有其它類庫配置的規則。
安全檢查沒有透過,那就會丟擲 java.security.AccessControlException 異常。即使安全檢查透過了,作業系統的許可權檢查仍然可能通不過,這時候又會丟擲其它型別的異常。
授權規則採用白名單,依據上面的配置意味著啟用預設安全策略的 JVM 將無法訪問本地檔案。如果需要訪問本地檔案,可以增加下面的規則
permission java.io.FilePermission "/etc/passwd", "read";
permission java.io.FilePermission "/etc/shadow", "read,write";
permission java.io.FilePermission "/xyz", "read,write,delete";
// 允許讀所有檔案
permission java.io.FilePermission "*", "read";
Permission 的配置引數正好對應了它的構造器引數
public FilePermission(String path, String actions) {
super(path);
init(getMask(actions));
}
Java 預設安全規則分為幾大模組,每個模組都有各自的配置引數
其中 AllPermission 表示開啟所有許可權。還有一個不速之客 HibernatePermission,它並不是內建的許可權模組,它是 Hibernate 框架為自己訂製的,這意味著安全規則是支援自定義擴充套件的。擴充套件也很簡單,可以自己編寫一個 Permission 子類,實現它的 4 個抽象方法。
abstract class Permission {
// 許可權名稱,對於檔案來說就是檔名,對於套接字來說就是套接字地址
// 它的意義是子類可定製的
private String name;
// 當前許可權物件是否隱含了 other 許可權
// 比如 AllPermission 的這個方法總是返回 true
public abstract boolean implies(Permission other);
// equals 和 hashcode 用於許可權比較
public abstract boolean equals(Object obj);
public abstract int hashCode();
// 許可權選項 read,write,xxx
public abstract String getActions();
}
class CustomPermission extends Permission {
private String actions;
CustomPermission(string name, string actions) {
super(name)
this.actions = actions;
}
...
}
JVM 啟動時會將 profile 裡面定義的許可權規則載入到許可權池中,使用者程式在特定的 API 方法裡使用許可權池來判斷是否包含呼叫這個 API 的許可權,最終會落實到呼叫許可權池中每一個許可權物件的 implies 方法來判斷是否具備指定許可權。
class CustomAPI {
public void someMethod() {
SecurityManager sec = System.getSecurityManager();
if(sec != null) {
sec.CheckPermission(new CustomPermission("xname", "xactions"));
}
...
}
}
啟用安全檢查,將會降低程式的執行效率,如果 profile 裡面定義的許可權規則特別多,那麼檢查效率就會很慢,使用時注意安全檢查要省著點使用。
沙箱的安全檢查點非常多,下面列舉一些常見的場景
檔案操作
套接字操作
執行緒和執行緒組
類載入器控制
反射控制
執行緒堆疊資訊獲取
網路代理控制
Cookie 讀寫控制
如果你的服務端程式開啟了安全檢查,就需要在 policy 配置檔案裡開啟很多安全設定,非常繁瑣,而且配置多了,檢查的效能也會產生一定損耗。這點有點類似 Android 的應用許可權設定,在每個 Android 應用的配置檔案裡都需要羅列出一系列應用子許可權。不過用 Java 來編寫服務端程式似乎開啟安全檢查沒有任何必要。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31561269/viewspace-2284736/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 冷門的 Java 應用程式安全沙箱機制瞭解一下Java
- JVM--java沙箱安全機制JVMJava
- 技術淺析:前端沙箱資料安全保護的機制前端
- 鴻蒙Next安全基石:應用沙箱與許可權機制深度剖析鴻蒙
- Java12 Collectors.teeing 你真的需要了解一下Java
- 關於等保2.0,你需要了解的
- 安全沙箱技術的原理、應用程式的安全性和穩定性
- JVM探究(一)談談雙親委派機制和沙箱安全機制JVM
- pwn 之 沙箱機制
- 淺談雲端計算與安全沙箱機制!
- 確保應用程式安全性
- 你需要理解的 Java 反射機制知識總結Java反射
- 你應該瞭解的 Java SPI 機制Java
- 開發者需要了解的nodejs中require的機制NodeJSUI
- qiankun 的 CSS 沙箱隔離機制CSS
- qiankun 的 JS 沙箱隔離機制JS
- 你的應用安全嗎? ——用Xray和Synk保駕護航
- 六款你需要了解的實用軟體
- JDK12 Collectors.teeing 你真的需要了解一下JDK
- 前端也需要了解的 JSONP 安全前端JSON
- 資料安全認證你有幾個?來了解一下
- Java鎖機制瞭解一下Java
- Java 鎖機制瞭解一下Java
- 一文了解微分段應用場景與實現機制
- 你需要了解的 HTTP Status CodeHTTP
- 你需要了解的HTTP協議HTTP協議
- 智慧合約的沙箱機制是什麼?
- 你需要了解API介面API
- 入門Java你需要了解的幾個知識要點!Java
- 程式設計師需要了解的硬核知識之作業系統和應用程式設計師作業系統
- 確保Web應用程式安全應該考慮哪些事項Web
- CodeArts如何保證客戶程式碼和應用安全?
- 關於深度學習,這些知識點你需要了解一下深度學習
- 為 Node.js 應用建立一個更安全的沙箱環境Node.js
- 程式設計師需要了解的硬核知識之二進位制程式設計師
- 精讀《Deno 1.0 你需要了解的》
- Android應用程式訊息處理機制Android
- 關於響應式佈局,你需要了解的知識點