「玩转漏洞」Tomcat任意文件读取与反序列化漏洞实战
文/李佳琳
前言
Tomcat 是一个开源的轻量级Web应用服务器,普遍使用于中小型系统和并发访问用户不是很多的场合,是开发和调试JSP 程序的首选。其中连接器Connector和容器Container是Tomcat的核心组件。本文主要介绍Tomcat 的两个相关漏洞:Tomcat任意文件读取/jsp文件包含漏洞(CVE-2020-1938)与Tomcat反序列化漏洞(CVE-2016-8735)。
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端口。
且8009端口绑定了ajp服务。
在攻击机上运行如下命令进行检测,可以看到靶机成功将web.xml展示了出来。
python CNVD-2020-10487-Tomcat-Ajp-lfi.py -p 8009 -f WEB-INF/web.xml targetIP
此时抓包可以看到关键请求如下:
由于存在validate验证限制,会过滤掉诸如“../”之类的操作,因此只能读取该网站根目录下的文件,无法读取上级目录的文件。
通过jsp文件包含实现远程代码执行
若网站存在文件上传功能,攻击者可以上传任意文件后缀的木马,通过jsp文件包含漏洞进行远程代码执行。为模拟上传功能,直接在/uploads目录下添加一个shell.png文件,这个文件的作用是反弹shell。
修改CNVD-2020-10487-Tomcat-Ajp-lfi.py代码,将requestURI改为一个不存在的jsp文件,tomcat会将path_info中的文件当做jsp文件执行。
在攻击机上运行命令:
Ncat -lvvp 2333,即监听本机的2333端口。
运行命令:
python CNVD-2020-10487-Tomcat-Ajp-lfi.py -p 8009 -f uploads/shell.png targetIP
发送一个ajp协议的请求,靶机收到后会将图片当做jsp文件解析,从而获取shell。
抓包查看流量,可以看到此时的关键请求如下:
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中去。
后续会根据请求URI的文件类型来使用不同的servlet处理。
根据conf/web.xml,一般文件会通过DefaultServlet处理,jsp文件会通过JspServlet处理。
任意文件读取
由于我们请求URI的是/asdf,所以接下来调用了DefaultServlet中的doGet方法。
doGet方法调用serveResource方法进行具体的资源读取操作。接着就进入了关键方法getRelativePath方法。
代码这里没有任何的过滤,直接读取请求中的include_path_info和include_servlet_path,然后将两部分进行拼接。因此就会将我们发送的“/”和“WEB-INF/web.xml”拼接成“/WEB-INF/web.xml”。
最后进行缓存判断,如果在缓存中存在就直接将文件返回,如果不存在则会在本地查找,最后将文件设置进response中返回。
jsp文件包含
由于我们请求的URI是/asdff.jsp,根据web.xml中的映射规则,可以知道jsp文件是通过jspServlet来解析的。在jspServlet中的service方法下断点。可以看到,与上述任意文件读取类似,由于servlet_path和path_info是用户可控的,且代码中没有对路径做任何判断和过滤,因此最终拼接成的jspUri可以成为上传的恶意jsp文件。
jspuri被封装成了一个JspServletWrapper,添加到了Jsp运行上下文中。最终wrapper.service()会编译恶意文件,并执行它的_jspService()方法来处理当前请求。
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" />
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功能监听的端口:
修改bin目录下的catalina.bat脚本。设置为不采用身份认证。
启动Tomcat,可以看到靶机已经开启10001和10002端口。
在攻击机上运行命令:
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit targetIP 10001 Groovy1 calc.exe
靶机成功弹出了计算器。
抓包查看流量如下:
1.3 漏洞原理
造成该漏洞的根本原因是Tomcat在配置JMX做监控时使用了JmxRemoteLifecycleListener方法。而JmxRemoteLifecycleListener底层使用了存在漏洞的groovy-2.3.9.jar包,导致了反序列化漏洞。在groovy源码的org.codehaus.groovy.runtime.MethodClosure 类中存在如下代码:
跟进此方法可发现,该方法的作用为调用指定对象的指定方法,三个参数分别代表调用方法的对象、被调用的方法和该方法的所需要的参数。因此通过合适的利用链就可以构造特定对象从而执行特定方法。
1.4 监控策略
访问10001端口(或其他RMI注册端口),且payload中含有与命令执行及MethodClosure有关的关键字。
1.5 漏洞修复
1. 升级tomcat版本;
2. 关闭JmxRemoteLifecycleListener功能,或者是对jmx JmxRemoteLifecycleListener远程端口进行网络访问控制。同时,增加严格的认证方式;
往期导读
· 信息安全技术部 ·
安全就是效益 责任重于泰山
我知道你 在看 哟