WebSphere IIOP反序列化(CVE-2020-4450)
前言
WebSphere 是 IBM 的软件平台。它包含了编写、运行和监视全天候的工业强度的随需应变 Web 应用程序和跨平台、跨产品解决方案所需要的整个中间件基础设施,如服务器、服务和工具。WebSphere 提供了可靠、灵活和健壮的软件。
版本影响
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
漏洞原理
RMI-IIOP反序列化构造恶意对象,利用RMIBYPASS思路寻找特定工厂类,处理lookup方法请求返回的Reference对象获取危险属性值,websphere应用请求WSIF服务将XML文件中的operation…映射执行javax.el.ELProcessor.eval()
方法造成RCE
环境搭建
参考:https://www.cnblogs.com/luzhanshi/p/11432901.html(选择9.0.0.2版本)
存储库:http://www-147.ibm.com/software/repositorymanager/com.ibm.websphere.APPCLIENT.v90
下载过程中不勾选补丁
漏洞分析
ServiceContext实例构造
通过文章描述打个桩至TxServerInterceptor.receive_request
,运行脚本
Properties env =new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.ibm.websphere.naming.WsnInitialContextFactory");
env.put(Context.PROVIDER_URL,"iiop://192.168.6.130:2809");
InitialContext initialContext =new InitialContext(env);
initialContext.list("");
ZDI师傅描述,找到漏洞入口点demarshalContext
方法,需要获取的serviceContext
和serviceContext.context_data
不为空.
所以该处需要构造一个serviceContext
实例.跟踪通信脚本,调试到最终通信的执行点ClientDelegate.invoke
方法.var4变量中带有serviceContexts
实例.可以进行反射构造
回溯该值,位于Connection.getServiceContexts
方法中返回的this.connectionContexts
.该值可以通过setConnectionContexts
设置.
现在需要构造通信将serviceContext
封装进去,跟进代码在GIOPImpl.getConnection中获得连接.
至于getConnection
中的参数IOR、Profile、ClientDlegate
,可以参照第一次通信时WsnInitCtx Debug
变量参数值调试构造
输入流构造
成功构造ServiceContext
后,应用执行至TxInterceptorHelper.demarshalContext
方法体中.这里需要使用TxInterceptorHelper.marshalContext
精心构造输入流.
第80行inputStream.read_any()
开始从输入流读取IDL any值.了解过CORBA
通信可以知道需要反序列化数据会存储在Any
类中,可以通过类似以下方式,载入需要反序列化恶意对象数据流.而该Any
对象会在TxInterceptorHelper.marshalContext
构造输入流时在PropagationContext
构造方法中传入.
....
ORB orb = ORB.init();
Any any = orb.create_any();
....
any.insert_Value((Serializeable)o);
RCE利用链
ZDI师傅利用org.apache.wsif.providers.ejb.WSIFPort_EJB
作为恶意类,由于Webpshere自身CLassLoader原因,只能利用handle.getEJBObject
进一步实现RCE.而此处需要通过Handle类型对象.
跟进WSIFPort_EJB.writeObject
方法,通过this.fieldEjbOject.getHandle()
方法返回handle
对象,所以可以重写EJSWrapper.getHandle
多次反射构造EntityHandle
(Handle类型)
具体构造还是一个个Debug 缺啥就反射构造即可
RMI Bypass+WSIF
进一步到达漏洞点EntityHandle.getEJBObject方法,由于jdk版本和RMi自实现的lookup原因,借用RMIBYPASS思路,启动恶意RMI服务,指定工厂类通过lookup从RMI服务中获取Reference对象.利用getObjectInstance
方法引用可控的危险属性.最后由于homeClass可控,进一步获得EJBHome类型的实例home.
现在目的是寻找工厂类,需要实现javax.naming.spi.ObjectFactory
且具有getObjectInstance
方法.ZDI师傅此处利用org.apache.wsif.naming.WSIFServiceObjectFactory
工厂类。通过ObjectFactoryHelper.getObjectInstanceViaContextDotObjectFactories
方法进一步调用WSIF
工厂类的getObjectInstance
方法.
该类中的getObjectInstance
方法获取远程RMI服务设置的属性值.进一步请求WSIF服务,最后返回代理对象stub.
返回的代理对象由于代理机制会触发invoke方法,映射字段
现在就是需要精心构造XML文件,使之后的映射能够调用到危险函数.
由于该处需要调用operation=>findByPrimaryKey
可以编写映射到method=>eval
,并且编写classname=>javax.el.ELProcessor
.就能够执行执行方法javax.el.ELProcessor.eval()
方法.args参数值由反序列化时构造的this.key
字段.
复现
漏洞修复
https://www.ibm.com/support/pages/node/6220276
删除WSIFPort_EJB.readObject
方法中的handle.getEJBObject
参考链接
https://ws.apache.org/wsif/providers/wsdl_extensions/java_extension.html
https://www.thezdi.com/blog/2020/7/20/abusing-java-remote-protocols-in-ibm-websphere
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!