反序列化漏洞
1、概述
序列化是让Java对象脱离Java运行环境的一种手段,可以有效的实现多平台之间的通信、对象持久化存储。 Java 序列化是指把 Java 对象转换为字节序列的过程,便于保存在内存、文件、数据库中,ObjectOutputStream类的 writeObject() 方法可以实现序列化。反序列化是指把字节序列恢复为 Java 对象的过程,ObjectInputStream 类的 readObject() 方法用于反序列化。
条件: 类必须实现反序列化接口,同时设置serialVersionUID以便适用不同jvm环境。 可通过SerializationDumper这个工具来查看其存储格式,主要包括Magi头:0xaced,TC_OBJECT:0x73,TC_CLASS:0x72,serialVersionUID,newHandle
示例: 代码功能: 将String对象obj1序列化后写入object文件,后反序列化得到对象obj2。
Object文件中的内容: Ac ed 00 05是java序列化内容的特征,编码后是rO0ABQ==
使用场景: ? http参数,cookie,sesion,存储方式可能是base64(rO0),压缩后的base64(H4sl),MII等 ? Servlets HTTP,Sockets,Session管理器 包含的协议就包括JMX,RMI,JMS,JNDI等(\xac\xed) ? xml Xstream,XMLDecoder等(HTTP Body:Content-Type:application/xml) ? json(Jackson,fastjson) http请求中包含
2、漏洞成因
序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。
漏洞案例: Test.class中MyObject类有一个共有属性name,myObj实例化后将myObj.name赋值为了“hi”,然后序列话写入object: 漏洞发生在反序列化过程,MyObject类实现了Serializable接口,并重写了readObject()函数(从源输入流中读取字节序列,反序列化成对象),这里定制的行为是打开计算器: 攻击时序图:
3、Weblogic反序列化漏洞汇总
历史漏洞:
3.1 CVE-2015-4852 Commons Collections
概述: 借用Java反序列化和Apache Commons Collections这一基础类库实现远程命令执行。这个漏洞横扫WebLogic、WebSphere、JBoss、Jenkins、OpenNMS的最新版。
漏洞出现在WLS Security组件,允许远程攻击者执行任意命令。攻击者通过向TCP端口7001发送T3协议流量,其中包含精心构造的序列化Java对象利用此漏洞。
(T3 协议在 WebLogic Server 和其他 Java 程序,包括客户端及其他 WebLogic Server 实例间传输数据)
漏洞分析: Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库,实现了一个TransformedMap类,该类是对Java标准数据结构Map接口的一个扩展。该类可以在一个元素被加入到集合内时,自动对该元素进行特定的修饰变换,具体的变换逻辑由Transformer类定义,Transformer在TransformedMap实例化时作为参数传入。(可控变量) 如果某个可序列化的类重写了readObject()方法,并且在readObject()中对Map类型的变量进行了键值修改操作,并且这个Map变量是可控的,就可以实现我们的攻击目标了。 于是找到了这个类:AnnotationInvocationHandler。该类的代码如下(反序列化)
我们可以实例化一个AnnotationInvocationHandler类,将其成员变量memberValues赋值为精心构造的恶意TransformedMap对象。然后将其序列化,提交给未做安全检测的Java应用。Java应用在进行反序列化操作时,则会触发TransformedMap的变换函数,执行预设的命令。
分析:https://security.tencent.com/index.php/blog/msg/97 Poc:https://github.com/fjserna/CVE-2015-7547
修复办法: http://www.oracle.com/technetwork/topics/security/alert-cve-2015-4852-2763333.html https://blogs.oracle.com/security/entry/security_alert_cve_2015_4852
3.2 CVE-2016-0638
漏洞位置,在readExternal位置: 补丁,加了一个FilteringObjectInputStream过滤接口:
3.3 CVE-2017-3248
根据JRMPListener来构造的,从补丁也可以看出,在resolveClass和resolveProxyClass都设置了黑名单。
3.4 CVE-2017-3506&CVE-2017-10271
概述: CVE-2017-10271 是3506的绕过。 漏洞在WLS-WebServices这个组件中,基于WLS wsat模块,核心就是XMLDecoder的反序列化漏洞,Java 调用XMLDecoder解析XML文件的时候,存在命令执行漏洞。 当前市面上挖矿主力军。
案例: xmldecoder.xml: 利用Java的XMLDecoder解析这个xml文件: 漏洞分析: 漏洞出现在wls-wsat.war中,此组件使用了weblogic自带的webservices处理程序来处理SOAP请求,在weblogic.wsee.jaxws.workcontext.WorkContextServerTube 类中获取XML数据传递给XMLDecoder来解析。 实例化了WorkContextXmlInputAdapter类,并且将获取到的XML格式的序列化数据传递到此类的构造方法中,最后通过XMLDecoder来进行反序列化操作。 漏洞复现: 抓包: 工具:
java -jar WebLogic_Wls-Wsat_RCE_Exp.jar http://192.168.43.100:7001 test.jsp
修复: 1、建议不要用JDK中的XmlDeocder类,寻求其它更安全的xml解析工具类,考虑是否删除WLS-WebServices组件 2、官方修复:补丁限定了object,new,method,void,array等字段,限定了不能生成java 实例
参考: https://github.com/Tom4t0/Tom4t0.github.io/blob/29314ca531f23e9e245bad9516c5d4e4c63756f2/_posts/2017-12-22-WebLogic%20WLS-WebServices%E7%BB%84%E4%BB%B6%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90.md 3.5 CVE-2018-2628
影响版本: Oracle WebLogic Server10.3.6.0 Oracle WebLogic Server12.2.1.2 Oracle WebLogic Server12.2.1.3 Oracle WebLogic Server12.1.3.0 漏洞分析: 1.反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2.RMI RMI是Remote Method Invocation的简称,是J2SE的一部分,能够让程序员开发出基于Java的分布式应用。一个RMI对象是一个远程Java对象,可以从另一个Java虚拟机上(甚至跨过网络)调用它的方法,可以像调用本地Java对象的方法一样调用远程对象的方法,使分布在不同的JVM中的对象的外表和行为都像本地对象一样。 RMI传输过程都使用序列化和反序列化,如果RMI服务端端口对外开发,并且服务端使用了像Apache Commons Collections这类库,那么会导致远程命令执行。 RMI依赖于Java远程消息交换协议JRMP(Java Remote Messaging Protocol),该协议为java定制,要求服务端与客户端都为java编写。
3.绕过黑名单 Weblogic 中InboundMsgAbbrev 的resolveProxyClass处理rmi接口类型,因为只判断了java.rmi.registry.Registry ,找一个其他的rmi接口绕过,比如java.rmi.activation.Activator为 RMI 对象激活提供支持。 复现过程: 首先服务端监听ysoserial,上面的反射代码被集成到了ysoserial工具中的CommonsCollections 的payload中,最终依然是sun.reflect.annotation.AnnotationInvocationHandler。 攻击端生成payload,接口用java.rmi.registry.Registry
4、漏洞挖掘
基本手段: 从可控数据的反序列化或间接的反序列化接口入手,在此基础上尝试构造序列化对象。
首先拿到一个Java应用,需要找到一个接受外部输入的序列化对象的接收点,即反序列化漏洞的触发点。我们可以通过审计源码中对反序列化函数的调用(例如readObject())来寻找,也可以直接通过对应用交互流量进行抓包,查看流量中是否包含java序列化数据来判断,java序列化数据的特征为以标记(ac ed 00 05)开头。
确定了反序列化输入点后,再考察应用的Class Path中是否包含Apache Commons Collections库(ysoserial所支持的其他库亦可),如果是,就可以使用ysoserial来生成反序列化的payload,指定库名和想要执行的命令即可:
通过先前找到的传入对象方式进行对象注入,数据中载入payload,触发受影响应用中ObjectInputStream的反序列化操作,随后通过反射调用Runtime.getRunTime.exec即可完成利用。
5、防御手段
5.1 weblogic防御
? 过滤T3协议,限定可连接的IP ? 设置Nginx反向代理,实现t3协议和http协议隔离 ? JEP290(JDK8u121,7u131,6u141),这个机制主要是在每层反序列化过程中都加了一层黑名单处理
5.2 原生反序列化防御
? 不要反序列化不可信的数据 ? 给反序列数据加密签名,并确保解密在反序列之前 ? 给反序列化接口添加认证授权 ? 反序列化服务只允许监听在本地或者开启相应防火墙 ? 升级第三方库 ? 升级JDK,JEP290
|