CVE-2020-1938 又名GhostCat, 之前引起了一场风雨,由长亭科技安全研究员发现的存在于 Tomcat 中的安全漏洞,由于 Tomcat AJP 协议设计上存在缺陷,攻击者通过 Tomcat AJP Connector 可以读取或包含 Tomcat 上所有 webapp 目录下的任意文件,例如可以读取 webapp 配置文件或源代码。此外在目标应用有文件上传功能的情况下,配合文件包含的利用还可以达到远程代码执行的危害。
Mac下的MxSrvs预装了Tomcat 8.5.16版本,可以直接使用
开放了 8005|8009|8080
端口
在 /Applications/MxSrvs/bin/tomcat/bin/catalina.sh
第一行export一个变量
export JPDA_ADDRESS=9001
然后将 /Applications/MxSrvs/bin/tomcat/bin/startup.sh
最后一行修改为
exec "$PRGDIR"/"$EXECUTABLE" jpda start "$@"
可以看到已经开启了9001端口
然后我们导入Tomcat源码包:
直接用maven,一步到位
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Tomcat</groupId> <artifactId>tomcat-coyote</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-coyote --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-coyote</artifactId> <version>8.5.16</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-catalina --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina</artifactId> <version>8.5.16</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper --> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jasper</artifactId> <version>8.5.16</version> </dependency> </dependencies> </project>
设置一个Remote Debug的配置
利用 https://github.com/threedr3am/learnjavabug
文件读取
文件包含
在具体分析漏洞之前,先来了解一下Tomcat-Ajp是个什么东西
在tomcat目录的 /conf/server.xml
下配置了Connector
在默认情况下,会开启8080 HTTP协议端口和8009 Ajp协议端口
简单来说,Tomcat提供Servlet容器,与其他静态资源HTTP服务器(IIS,Nginx等)集成,Tomcat和其他HTTP服务器之间需要通过专门的插件来通信,这就是Connector存在的意义
tomcat在处理AJP请求的时候,主要是通过
/tomcat-coyote-8.5.16.jar!/org/apache/coyote/ajp/AjpProcessor.class#prepareRequest()
所以我们在AjpProcessor.class的第232行处打断点,开启Debug
利用poc发送请求
前面通过一系列getXXX()方法,收集请求的协议,uri,ip,host,MIME等信息
然后通过一个switch()语句, 到 request.setAttribute()
方法,设置了request的三个属性
javax.servlet.include.request_uri javax.servlet.include.path_info javax.servlet.include.servlet_path
进入 this.getAdapter().service(this.request, this.response);
/org/apache/catalina/connector/CoyoteAdapter.class:330
反射处理了request,response
org/apache/catalina/servlets/DefaultServlet.class
:
service()
-> doGet()
-> serveResource()
调用 getRelativePath()
获取相对路径
往下走经过一个else判断,进入 this.resources.getResource(path)
跟到 /org/apache/tomcat/util/http/RequestUtil.class#normalize
函数的时候,发现对穿越字符进行了过滤
所以不能逃脱webapp目录
之后利用File类进行文件读取,并经过一系列检查
部分调用栈
调用方式和上面的大体相同,直到service()函数
调用了
org/apache/jasper/servlet/JspServlet.class#service
拼接后,直接到 serviceJspFile
方法
部分调用栈