这两天Apache Tomcat爆出来的新漏洞,CVE-2020-1938,可远程读取web服务器下的文件,危害较大。
影响版本
- Tomcat 6.*
- Tomcat 7.* < 7.0.100
- Tomcat 8.* < 8.5.51
- Tomcat 9.* < 9.0.31
漏洞成因
Apache Tomcat默认启用了AJP协议,server.xml
中配置如下:
1 | <!-- A "Connector" represents an endpoint by which requests are received |
第一个连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。
第二个连接器监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器。AJP连接器可以通过AJP协议和一个web容器进行交互。
攻击者通过AJP协议端口利用该漏洞进行文件读取或包含 Tomcat 上所有 webapp 目录下的任意文件,如:webapp 配置文件、源代码等。
漏洞验证
Apache Tomcat/9.0.20
因之前电脑上下载过tomcat,版本也在漏洞影响范围之内,直接拿来验证,在bin/start.bat
启动服务。
POC
1 | https://github.com/hypn0s/AJPy |
读取文件
1 | python tomcat.py read_file --webapp=manager /secret.txt 127.0.0.1 |
漏洞分析
源码下载
Apache Tomcat v9.0.20源码下载地址:
1 | http://archive.apache.org/dist/tomcat/tomcat-9/v9.0.20/src/ |
代码分析
追踪到java\org\apache\coyote\ajp\AjpProcessor.java
类,tomcat官网解释如下:
1 | public class AjpAprProcessor |
在AjpProcessor.java
类中定位到prepareRequest()
函数,此函数作用为一个请求删选器。接着来到代码704行左右:
可以看到,当属性值不等于Constants.SC_A_ARE_DONE
时会进入判断,为Constants.SC_A_REQ_ATTRIBUTE
时,接着进行if-else
的判断,当没有匹配结果时,最终传入request.setAttribute()
函数,各种属性值如下图:
因此我们可以进行对Ajp设置特定的属性,封装为request对象的Attribute属性,比如以下三个属性可以被设置
1 | javax.servlet.include.request_uri |
读取文件
在java\org\apache\catalina\servlets\DefaultServlet.java
类中,service
函数调用doGet
方法处理request和response。
doGet
调用serverResource
,在serverResource
函数中读取request中的path,接着直接调用了resources.getResource()
函数读取。
)
跟进getRelativePath
函数,看下是如何获取路径以及是否存在过滤,只要获取到request_uri
不为null
,然后从request
对象中获取并设置pathInfo
属性值和servletPath
属性值。
参考
1 | https://www.anquanke.com/post/id/199448 |