vlambda博客
学习文章列表

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

文/李佳琳

前言

Tomcat 是一个开源的轻量级Web应用服务器,普遍使用于中小型系统和并发访问用户不是很多的场合,是开发和调试JSP 程序的首选。其中连接器Connector和容器Container是Tomcat的核心组件。本文主要介绍Tomcat 的两个相关漏洞:Tomcat任意文件读取/jsp文件包含漏洞(CVE-2020-1938)与Tomcat反序列化漏洞(CVE-2016-8735)。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

CVE-2020-1938

Tomcat任意文件读取/jsp文件包含漏洞

1.1 漏洞概述

该漏洞是由于Tomcat AJP协议存在缺陷,攻击者可通过构造特定参数利用该漏洞,读取服务器webapp下任意文件。若目标服务器同时存在文件上传功能,攻击者可进一步实现远程代码执行。

影响版本:

Apache Tomcat 6

Apache Tomcat 7 < 7.0.100

Apache Tomcat 8 < 8.5.51

Apache Tomcat 9 < 9.0.31

1.2 AJP协议简介

Tomcat根据默认配置(conf/server.xml)启动两个连接器。一是HTTP Connector默认监听8080端口处理HTTP请求,二是AJP connector默认8009端口处理AJP请求。Tomcat处理两个协议请求区别不大,AJP协议相当于HTTP协议的二进制优化版。通常在存在负载平衡的部署中使用,一般位于Web服务器后方,使用路由机制将会话重定向到正确的应用服务器,其中每个应用服务器实例都获得一个名称。这种情况下,Web服务器充当应用程序服务器的反向代理。

1.3 漏洞复现

环境

攻击机:mac OS

靶机:windows7,tomcat8.5.32

任意文件读取

以Tomcat8.5.32为例,从官网下载Tomcat8.5.32,部署在靶机。靶机启动bin目录下的startup.bat,可看到已默认启动8009端口。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

且8009端口绑定了ajp服务。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

在攻击机上运行如下命令进行检测,可以看到靶机成功将web.xml展示了出来。

python CNVD-2020-10487-Tomcat-Ajp-lfi.py -p 8009 -f WEB-INF/web.xml targetIP

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

此时抓包可以看到关键请求如下:

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

由于存在validate验证限制,会过滤掉诸如“../”之类的操作,因此只能读取该网站根目录下的文件,无法读取上级目录的文件。

通过jsp文件包含实现远程代码执行

若网站存在文件上传功能,攻击者可以上传任意文件后缀的木马,通过jsp文件包含漏洞进行远程代码执行。为模拟上传功能,直接在/uploads目录下添加一个shell.png文件,这个文件的作用是反弹shell。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

修改CNVD-2020-10487-Tomcat-Ajp-lfi.py代码,将requestURI改为一个不存在的jsp文件,tomcat会将path_info中的文件当做jsp文件执行。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

在攻击机上运行命令:

Ncat -lvvp 2333,即监听本机的2333端口。

运行命令:

python CNVD-2020-10487-Tomcat-Ajp-lfi.py -p 8009 -f uploads/shell.png targetIP

发送一个ajp协议的请求,靶机收到后会将图片当做jsp文件解析,从而获取shell。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战
「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

抓包查看流量,可以看到此时的关键请求如下:

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

1.4 漏洞原理

通过以上复现,可以看到关键在于如下三个变量,这个漏洞正是由于用户可以操控这三个变量导致的文件读取。

javax.servlet.include.request_uri: /

javax.servlet.include.path_info: WEB-INF/web.xml

javax.servlet.include.servlet_path: /

我们搭建源码环境,通过调试源代码分析漏洞原理。

首先在org.apache.coyote.ajp.AbstractAjpProcessor prepareRequest方法处下断点,可以看到方法里对属性进行了设置。当遇到case中没有的属性时,会将属性设置到request中去。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

后续会根据请求URI的文件类型来使用不同的servlet处理。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

根据conf/web.xml,一般文件会通过DefaultServlet处理,jsp文件会通过JspServlet处理。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战
「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

任意文件读取

由于我们请求URI的是/asdf,所以接下来调用了DefaultServlet中的doGet方法。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

doGet方法调用serveResource方法进行具体的资源读取操作。接着就进入了关键方法getRelativePath方法。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

代码这里没有任何的过滤,直接读取请求中的include_path_info和include_servlet_path,然后将两部分进行拼接。因此就会将我们发送的“/”和“WEB-INF/web.xml”拼接成“/WEB-INF/web.xml”。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

最后进行缓存判断,如果在缓存中存在就直接将文件返回,如果不存在则会在本地查找,最后将文件设置进response中返回。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

jsp文件包含

由于我们请求的URI是/asdff.jsp,根据web.xml中的映射规则,可以知道jsp文件是通过jspServlet来解析的。在jspServlet中的service方法下断点。可以看到,与上述任意文件读取类似,由于servlet_path和path_info是用户可控的,且代码中没有对路径做任何判断和过滤,因此最终拼接成的jspUri可以成为上传的恶意jsp文件。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

jspuri被封装成了一个JspServletWrapper,添加到了Jsp运行上下文中。最终wrapper.service()会编译恶意文件,并执行它的_jspService()方法来处理当前请求。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

1.5 监控策略

AJP协议中同时设置了javax.servlet.include.request_uri、javax.servlet.include.servlet_path、javax.servlet.include.path_info三个属性。

1.6 漏洞修复

1. 将Tomcat升级;

3. 若需使用Tomcat AJP协议,可根据使用版本配置协议属性设置认证凭证。

使用Tomcat 7和Tomcat 9的用户可为AJP Connector配置secret或requiredSecret来设置AJP协议的认证凭证。例如:

<Connector port="8009"protocol="AJP/1.3" redirectPort="8443"address="YOUR_TOMCAT_IP_ADDRESS" secret="YOUR_TOMCAT_AJP_SECRET"/> 

<Connector port="8009"protocol="AJP/1.3" redirectPort="8443"address="YOUR_TOMCAT_IP_ADDRESS"requiredSecret="YOUR_TOMCAT_AJP_SECRET" />


「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

CVE-2016-8735

Tomcat反序列化漏洞

1.1 漏洞概述

该漏洞与之前Oracle发布的jmxRemoteLifecycleListener反序列化漏洞(CVE-2016-3427)相关,是由于使用了JmxRemoteLifecycleListener的监听功能所致。而在Oracle官方发布修复后,Tomcat未能及时修复更新而导致的远程代码执行。

漏洞影响版本:

ApacheTomcat 9.0.0.M1 到9.0.0.M11

ApacheTomcat 8.5.0 到8.5.6

ApacheTomcat 8.0.0.RC1 到8.0.38

ApacheTomcat 7.0.0 到7.0.72

ApacheTomcat 6.0.0 到6.0.47

漏洞利用条件:

外部需要开启JmxRemoteLifecycleListener监听的10001和10002端口来实现远程代码执行,且未开启访问控制。

1.2 漏洞复现

环境:

攻击机:mac OS

靶机:windows7,tomcat 8.5.32

所需工具包:

catalina-jmx-remote.jar

groovy-2.3.9.jar

ysoserial.jar

以tomcat8.5.32为例,从官网下载tomcat8.5.32,部署在靶机上。将catalina-jmx-remote.jar、groovy-2.3.9.jar两个jar包放入lib目录下。

修改conf/server.xml 文件,启用JmxRemoteLifecycleListener功能监听的端口:

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

修改bin目录下的catalina.bat脚本。设置为不采用身份认证。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

启动Tomcat,可以看到靶机已经开启10001和10002端口。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

在攻击机上运行命令:

java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit targetIP 10001 Groovy1 calc.exe

靶机成功弹出了计算器。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

抓包查看流量如下:

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

1.3 漏洞原理

造成该漏洞的根本原因是Tomcat在配置JMX做监控时使用了JmxRemoteLifecycleListener方法。而JmxRemoteLifecycleListener底层使用了存在漏洞的groovy-2.3.9.jar包,导致了反序列化漏洞。在groovy源码的org.codehaus.groovy.runtime.MethodClosure 类中存在如下代码:

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

跟进此方法可发现,该方法的作用为调用指定对象的指定方法,三个参数分别代表调用方法的对象、被调用的方法和该方法的所需要的参数。因此通过合适的利用链就可以构造特定对象从而执行特定方法。

「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战

1.4 监控策略

访问10001端口(或其他RMI注册端口),且payload中含有与命令执行及MethodClosure有关的关键字。

1.5 漏洞修复

1. 升级tomcat版本;

2. 关闭JmxRemoteLifecycleListener功能,或者是对jmx JmxRemoteLifecycleListener远程端口进行网络访问控制。同时,增加严格的认证方式;


往期导读


· 信息安全技术部 ·

安全就是效益 责任重于泰山


我知道你  在看  哟