- 1 序列化与反序列化基础
- 2 漏洞基本原理
- 3 Java 反射
- 4 DNSURL gadget 分析
- 1 背景介绍
- 2 CommonsCollections 1 Gadget 分析
- 3 CommonsCollections 6 Gadget 分析
- 4 CommonsCollections 2&&4 Gadget 分析
- JDK 7U21 Gadget
- 1 原理
- 2 构造
- 3 调用链
- 4 总结
- 1 Java 动态加载字节码
- 2 CommonsCollections 3 Gadget 分析
- 3 CommonsCollections 5 Gadget 分析
- 4 CommonsCollections 7 Gadget 分析
- 反序列化攻击涉及到的相关协议
- 1 RMI
- 2 JNDI
3 调用链
在比较 Java 对象时,常用到两种方法:
- equals
- compareTo
任意 Java 对象都拥有 equals
方法,它通常用于比较两个对象是否是同一个引用。另一个常见的会调用 equals
的场景就是集合 set
。 set
中储存的对象不允许重复,所以在添加对象的时候,势必会涉及到比较操作。
HashSet 的 readObject 方法:
这里使用了一个 HashMap,将对象保存在 HashMap 的 key 处来做去重。
跟进 HashMap 的 put 方法:
变量 i
就是哈希值。两个不同的对象的 i
相等时,才会执行到 key.equals(k)
,触发前面说过的代码执行。
接下来的思路就是为了让 proxy 对象的哈希,等于 TemplateImpl 对象的哈希。
计算哈希的主要是下面这两行代码:
int hash = hash(key);
int i = indexFor(hash, table.length);
将其中的关键逻辑提取出来,可以得到下面这个函数:
public static int hash(Object key) {
int h = 0;
h ^= key.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
h = h ^ (h >>> 7) ^ (h >>> 4);
return h & 15;
}
除了 key.hashCode()
外再没有其他变量,所以 proxy
对象与 TemplateImpl
对象的哈希是否相等,仅取决于这两个对象的 hashCode()
返回值是否相等。 TemplateImpl
的 hashCode()
是一个 Native 方法,每次运行都会发生变化,理论上是无法预测的,所以想让 proxy
的 hashCode()
与之相等,只能通过 proxy.hashCode()
。
proxy.hashCode()
仍然会调用到 AnnotationInvocationHandler#invoke
,进而调用到 AnnotationInvocationHandler#hashCodeImpl
,跟进这个方法:
遍历这个 Map 中的每个 key 和 value,计算每个 (127 * key.hashCode()) ^ value.hashCode()
并求和。
JDK7u21 中使用了一个非常巧妙的方法:
- 当
memberValues
中只有一个 key 和一个 value 时,该哈希简化成(127 * key.hashCode()) ^ value.hashCode()
- 当
key.hashCode()==0
时,任何数异或 0 的结果仍是它本身,所以该哈希简化成value.hashCode()
- 当
value
就是TemplateImpl
时,这两个哈希就变成完全相等
因此,通过寻找一个 hashCode 是 0 的对象作为的 key,将恶意 TemplateImpl 对象作为 value,这个 proxy 计算的 hashCode 就与 TemplateImpl 对象本身的 hashCode 相等了。
找一个 hashCode 是 0 的对象,通过一个简单的爆破程序来实现:
public static void bruteHashCode()
{
for (long i = 0; i < 9999999999L; i++) {
if (Long.toHexString(i).hashCode() == 0) {
System.out.println(Long.toHexString(i));
}
}
}
第一个结果是 f5a5a608
,这个也是 ysoserial 中用到的字符串。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论