中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么濫用IBM WebSphere平臺中的Java遠程協議漏洞

發布時間:2021-11-30 14:47:07 來源:億速云 閱讀:183 作者:iii 欄目:安全技術

本篇內容主要講解“怎么濫用IBM WebSphere平臺中的Java遠程協議漏洞”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“怎么濫用IBM WebSphere平臺中的Java遠程協議漏洞”吧!

CORBA,即公共對象請求代理體系結構,它是一個由對象管理組織(OMG)定義的標準化規范。它是一個獨立與平臺的RPC框架,并且早于SOAP和gRPC等標準出現。在分布式環境中,CORBA使用了互聯網InterORB協議(IIOP)來實現端點之間的通信。在IBM WebSphere的默認安裝配置下,CORBA服務可以運行在TCP端口2809、9100、9402和9403。在調用服務方法之前,Interceptor類將會攔截調用請求,這里我們需要注意的是TxServerInterceptor類。

CVE-2020-4450-snippet-1.java:

public void receive_request(ServerRequestInfo sri) {

  // ...snip...

    if (TxProperties.SINGLE_PROCESS) {

      propagationContext = TxInterceptorHelper.demarshalContext(serviceContext.context_data, (ORB)((LocalObject)sri)._orb()); // <------------

      contextType = TxInterceptorHelper.determineContextType(propagationContext);

    }  

  // ...snip...

}

 

public static final PropagationContext demarshalContext(byte[] bytes, ORB orb) {

  // ...snip...

  propContext.implementation_specific_data = inputStream.read_any(); // <-------

  // ...snip...

}

 

public Any read_any() {

  // ...snip...

  any.read_value(this.encoderStream, typeCodeImpl); // <------------------------

  return any;

}

 

private Object simpleReadObjectInternal(Class paramClass, String paramString) throws ClassNotFoundException, IOException {

  // ...snip...

      return readSerializable(paramClass, objectStreamClass, paramString); // <------

  // ...snip...

}

 

private Object readSerializable(Class paramClass, ObjectStreamClass paramObjectStreamClass, String paramString) throws IOException, ClassNotFoundException {

  // ...snip...

  return inputObjectClassDesc(serializable, paramObjectStreamClass); // <-------

}

 

private Object inputObjectClassDesc(Object paramObject, ObjectStreamClass paramObjectStreamClass) throws IOException, ClassNotFoundException {

  ObjectStreamClass objectStreamClass = processClassHierarchy(paramObject, paramObjectStreamClass);

  return inputObjectUsingClassDesc(paramObject, objectStreamClass); // <--------

}

 

  Object inputObjectUsingClassDesc(Object paramObject, ObjectStreamClass paramObjectStreamClass) throws IOException, ClassNotFoundException {

    // ...snip...

      ObjectStreamClass objectStreamClass = this.readObjectOSC;

      this.readObjectOSC = paramObjectStreamClass;

      paramObjectStreamClass.readObjectMethod.invoke(paramObject, this.readObjectArglist); // <--- calls readObject()

      this.readObjectOSC = objectStreamClass;

      return true;

}

當TxServerInterceptor類成功攔截調用請求時,便會調用receive_request()方法,同時還會試用demarshalContext()方法來從字節流中接收一個ServiceContext對象,而這個對象是攻擊者可控的。任何嵌入在這個字節流中的對象都可以通過調用read_any()方法來提取,最終通過調用readObject()方法來獲取嵌入的對象類。

遠程代碼執行漏洞(CVE-2020-4450)

盡管我們可以實現對任何對象進行反序列化操作,但實現遠程代碼執行并非易事。這是因為IBM Java SDK實現了針對反序列化攻擊的安全緩解措施,其中包括:

  • 擁有更嚴格的ClassLoader類,在運行時僅提供必要的類;

  • TemplatesImpl類已無法再被序列化;

  • IBM SDK不會使用Oracle JDK的Java名命方法以及目錄接口(JNDI)。因此,我們無法通過RMI/LDAP來加載遠程類并實現漏洞利用;

根據tint0的描述,tint0提供了一個Gadget鏈來繞過這種緩解方案。這個Gadget使用了WSIFPort_EJB類作為入口點。

CVE-2020-4450-snippet-2.java:

public class WSIFPort_EJB

  extends WSIFDefaultPort

  implements Serializable

 

{

  // ...snip...

 

  private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {

    ois.defaultReadObject();

    if (this.separatedEJBRefs) {

      Object objHome = ois.readObject();

      if (objHome != null && objHome instanceof HomeHandle) {

        HomeHandle homeHandle = (HomeHandle)objHome;

        this.fieldEjbHome = homeHandle.getEJBHome();

      }  

 

      Object obj = ois.readObject();

      if (obj != null && obj instanceof Handle) {

        Handle handle = (Handle)obj;

        this.fieldEjbObject = handle.getEJBObject();  // <----------------------

      }  

    }

  }

}

 

public EJBObject getEJBObject() throws RemoteException {

  // ...snip...

  home = (EJBHome)PortableRemoteObject.narrow(ctx.lookup(this.homeJNDIName), homeClass); // <----

  // ...snip...

  Method fbpk = findFindByPrimaryKey(homeClass); // <---- returns findFindByPrimaryKey() method

  this.object = (EJBObject)fbpk.invoke(home, new Object[] { this.key });   <--  $proxy.findFindByPrimaryKey(Serializable $arg)

}

這個類最有趣的地方在于getEJBObject()方法,我們一起來看一看這里面的JNDI查詢調用。

CVE-2020-4450-snippet-3.java:

com.sun.jndi.rmi.registry.RegistryContext#lookup

com.sun.jndi.rmi.registry.RegistryContext#decodeObject

javax.naming.spi.NamingManager#getObjectInstance

org.apache.aries.jndi.OSGiObjectFactoryBuilder#getObjectInstance

org.apache.aries.jndi.ObjectFactoryHelper#getObjectInstance

org.apache.aries.jndi.ObjectFactoryHelper#getObjectInstanceViaContextDotObjectFactories

 

protected Object getObjectInstanceViaContextDotObjectFactories(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment, Attributes attrs) throws Exception {

  Object result = null;

  String factories = (String)environment.get("java.naming.factory.object");

 

  if (factories != null && factories.length() > 0) {

    String[] candidates = factories.split(":");

    ClassLoader cl = (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {

          public ClassLoader run() {

            return Thread.currentThread().getContextClassLoader();

          }

    });

 

    for (String cand : candidates) {

      ObjectFactory factory = null;

      try {

        Class<ObjectFactory> clz = cl.loadClass(cand);

        factory = (ObjectFactory)clz.newInstance();

      } catch (Exception e) {

        if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "Exception instantiating factory: " + e);

      }

 

      if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "cand=" + cand + " factory=" + factory);

 

      if (factory != null) {

        if (factory instanceof DirObjectFactory) {

          if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "its a DirObjectFactory");  

          DirObjectFactory dirFactory = (DirObjectFactory)factory;

          result = dirFactory.getObjectInstance(obj, name, nameCtx, environment, attrs);

        }

        else {

          if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "its an ObjectFactory");  

          result = factory.getObjectInstance(obj, name, nameCtx, environment);

        }  

      }

 

      if (result != null && result != obj)

        break;

    }

  }  if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, "result = " + result);

  return (result == null) ? obj : result;

}

我們可以看到,getObjectInstanceViaContextDotObjectFactories()將會調用getObjectInstance的任意ObjectFactory類,其中一個跟我們Gadget鏈相關的類就是WSIFServiceObjectFactory。

CVE-2020-4450-snippet-4.java:

public Object getObjectInstance(Object obj, Name name, Context context, Hashtable env) throws Exception {

  Trc.entry(this, obj, name, context, env);

  if (obj instanceof Reference && obj != null) {

    Reference ref = (Reference)obj;

    if (ref.getClassName().equals(WSIFServiceRef.class.getName())) {

      String wsdlLoc = resolveString(ref.get("wsdlLoc"));

      String serviceNS = resolveString(ref.get("serviceNS"));

      String serviceName = resolveString(ref.get("serviceName"));

      String portTypeNS = resolveString(ref.get("portTypeNS"));

      String portTypeName = resolveString(ref.get("portTypeName"));

      if (wsdlLoc != null) {

        WSIFServiceFactory factory = WSIFServiceFactory.newInstance();

        WSIFService service = factory.getService(wsdlLoc, serviceNS, serviceName, portTypeNS, portTypeName);

        Trc.exit(service);

        return service;

      }  

    } else if (ref.getClassName().equals(WSIFServiceStubRef.class.getName())) {

      String wsdlLoc = resolveString(ref.get("wsdlLoc"));

      String serviceNS = resolveString(ref.get("serviceNS"));

      String serviceName = resolveString(ref.get("serviceName"));

      String portTypeNS = resolveString(ref.get("portTypeNS"));

      String portTypeName = resolveString(ref.get("portTypeName"));

      String preferredPort = resolveString(ref.get("preferredPort"));

      String className = resolveString(ref.get("className"));

      if (wsdlLoc != null) {

        WSIFServiceFactory factory = WSIFServiceFactory.newInstance();

        WSIFService service = factory.getService(wsdlLoc, serviceNS, serviceName, portTypeNS, portTypeName); // <----

        Class iface = Class.forName(className, true, Thread.currentThread().getContextClassLoader());

        Object stub = service.getStub(preferredPort, iface);

        Trc.exit(stub);

        return stub;

      }  

    }  

  }

}

針對getObjectInstance()的調用將會根據一個指向遠程XML定義的URL來初始化一個Web服務調用框架(WSIF)服務,而這個XML也是攻擊者可控的。在這種場景下,服務的className會被設置為javax.el.ELProcessor,并且會定義一個java:operation元素,然后將findByPrimaryKey()映射為eval()方法。

getObjectInstance()調用將會返回一個WSIFClientProxy Java代理對象,當findByPrimaryKey()方法被調用時,這個代理對象將會調用ELProcessor實例的eval()方法。別忘了我們已經可以通過反序列化來控制this.key參數了,那么這樣一來,我們就可以通過表達式語言注入技術來實現遠程代碼執行了。

信息披露漏洞(CVE-2020-4449)

這個漏洞利用Gadget利用的是一個XXE漏洞,漏洞代碼如下所示。

CVE-2020-4450-snippet-5.java:

public static Definition readWSDL(String contextURL, String wsdlLoc) throws WSDLException {

  Trc.entry(null, contextURL, wsdlLoc);

   

  initializeProviders();

   

  WSDLFactory factory = WSDLFactory.newInstance("org.apache.wsif.wsdl.WSIFWSDLFactoryImpl");

   

  WSDLReader wsdlReader = factory.newWSDLReader(); // <---------------------

  wsdlReader.setFeature("javax.wsdl.verbose", false);

  try {

    Definition def = wsdlReader.readWSDL(contextURL, wsdlLoc); // <---------

    Trc.exitExpandWsdl(def);

    return def;

  } catch (WSDLException e) {

    Trc.exception(e);

    MessageLogger.log("WSIF.0002E", wsdlLoc);

    throw e;

  }  

}

這個Gadget還演示了如何在現代JRE中如何繞過類似的緩解方案,尤其是通過FTP來實現越界提取等等。在這種場景下,數據是通過錯誤信息來提取的,因此當代碼在解析XML文檔時,如果沒有封裝在一個try/catch語句中的話,那么該漏洞將產生嚴重影響。

漏洞修復

為了修復這些漏洞,IBM采取了很多措施來確保TxServerInterceptor類不再會被反序列化為任意對象:

 怎么濫用IBM WebSphere平臺中的Java遠程協議漏洞

到此,相信大家對“怎么濫用IBM WebSphere平臺中的Java遠程協議漏洞”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

桃园县| 凌海市| 乌拉特前旗| 玉龙| 辉南县| 奇台县| 玛纳斯县| 梁河县| 旬邑县| 江城| 松滋市| 永顺县| 延寿县| 安多县| 吉水县| 闸北区| 丹巴县| 进贤县| 东丽区| 新乡县| 达尔| 宁明县| 彩票| 克山县| 湖南省| 万盛区| 泊头市| 红安县| 堆龙德庆县| 铁岭市| 清水河县| 顺昌县| 昭平县| 德格县| 瑞丽市| 墨竹工卡县| 开原市| 延安市| 荆门市| 固镇县| 大同市|