一、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/