一、Java反序列化漏洞的挖掘
1、黑盒流量分析:
在Java反序列化傳送的包中,一般有兩種傳送方式,在TCP報文中,一般二進制流方式傳輸,在HTTP報文中,則大多以base64傳輸。因而在流量中有一些特征:
(1)TCP:必有aced0005,這個16進制流基本上也意味者java反序列化的開始;
(2)HTTP:必有rO0AB,其實這就是aced0005的base64編碼的結果;
以上意味着存在Java反序列化,可嘗試構造payload進行攻擊。
2、黑盒java的RMI:
rmi是java的一種遠程對象(類)調用的服務端,默認於1099端口,基予socket通信,該通信實現遠程調用完全基於序列化以及反序列化。
3、白盒代碼審計:
(1)觀察實現了Serializable接口的類是否存在問題。
(2)觀察重寫了readObject方法的函數邏輯是否存在問題。
二、Java反序列化的攻擊:
參見我的博客:
三、Java反序列化漏洞的防御:
1、類的白名單校驗機制:
實際上原理很簡單,就是對所有傳入的反序列化對象,在反序列化過程開始前,對類型名稱做一個檢查,不符合白名單的類不進行反序列化操作。很顯然,這個白名單肯定是不存在Runtime的。
2、禁止JVM執行外部命令Runtime.exec
這個措施可以通過擴展 SecurityManager 可以實現。
1 SecurityManager originalSecurityManager = System.getSecurityManager();
2 if (originalSecurityManager == null) {
3 // 創建自己的SecurityManager
4 SecurityManager sm = new SecurityManager() {
5 private void check(Permission perm) {
6 // 禁止exec
7 if (perm instanceof java.io.FilePermission) {
8 String actions = perm.getActions();
9 if (actions != null && actions.contains("execute")) {
10 throw new SecurityException("execute denied!");
11 }
12 }
13 // 禁止設置新的SecurityManager,保護自己
14 if (perm instanceof java.lang.RuntimePermission) {
15 String name = perm.getName();
16 if (name != null && name.contains("setSecurityManager")) {
17 throw new SecurityException("System.setSecurityManager denied!");
18 }
19 }
20 }
21
22 @Override
23 public void checkPermission(Permission perm) {
24 check(perm);
25 }
26
27 @Override
28 public void checkPermission(Permission perm, Object context) {
29 check(perm);
30 }
31 };
32
33 System.setSecurityManager(sm);
34 }
四、參考文獻:
https://paper.seebug.org/312/

