Apache Tomcat从文件包含到RCE漏洞原理深入分析
字数 2072 2025-08-18 11:39:30

Apache Tomcat AJP协议文件包含与RCE漏洞深入分析教学文档

漏洞概述

CVE编号:CVE-2020-1938
漏洞名称:Apache Tomcat AJP协议文件包含漏洞
影响版本:多个Tomcat版本(测试验证包括8.0.50等版本)
漏洞类型:文件包含→远程代码执行(RCE)
危害等级:高危
默认影响:Tomcat默认配置中监听8009端口(AJP协议)

漏洞背景

AJP协议简介

AJP(Apache JServ Protocol)是一个二进制的TCP传输协议,特点:

  • 专为Tomcat与前端Web服务器(如Apache HTTP Server)通信设计
  • 相比HTTP纯文本协议,AJP具有更高效率和性能
  • 默认监听8009端口
  • 浏览器不支持直接发送AJP请求

Tomcat连接器架构

Tomcat默认配置两个连接器(Connector):

  1. HTTP Connector

    • 默认监听8080端口
    • 处理所有HTTP请求(静态和动态资源)
  2. AJP Connector

    • 默认监听8009端口
    • 专用于与前端Web服务器通信
    • 使用率约7.8%(相对较低)

漏洞原理分析

漏洞核心

攻击者可通过AJP协议控制以下三个关键参数:

  1. javax.servlet.include.request_uri
  2. javax.servlet.include.path_info
  3. javax.servlet.include.servlet_path

通过操纵这些参数实现:

  1. 任意文件读取(文件包含)
  2. 远程代码执行(RCE)

漏洞位置

在Tomcat 8.0.50版本中,漏洞存在于:
org.apache.coyote.ajp.AbstractAjpProcessor.prepareRequest()方法

文件包含漏洞分析流程

  1. 请求处理流程

    • AJP请求→SocketProcessor→AbstractAjpProcessor.prepareRequest()
    • 攻击者控制的三个参数被存入Request对象的attributes(HashMap)
  2. Servlet路由

    • 当请求URI无法匹配任何Servlet时,由DefaultServlet处理
    • DefaultServlet主要用于处理静态资源(HTML/图片/CSS/JS等)
  3. 路径拼接关键点

    • DefaultServlet.getRelativePath()进行路径拼接
    • 使用攻击者控制的path_infoservlet_path参数
    • 如果缺少request_uri参数会导致利用失败
  4. 路径规范化限制

    • RequestUtil.normalize()防止目录遍历:
      • 不允许以"/../"开头的路径
      • 不允许连续出现两个"/../"
    • 结果:只能读取webapps目录内文件,无法读取上层目录

RCE漏洞分析流程

  1. 前提条件

    • 需要先上传含有恶意代码的文件到webapps目录
    • 文件扩展名不限(甚至无扩展名)
  2. 利用JspServlet

    • 默认处理.jsp和.jspx请求
    • 功能:将JSP文件生成Servlet类→编译→执行
  3. 攻击流程

    • AJP请求URI必须以".jsp"结尾(文件可不存在)
    • path_info参数指向上传的恶意文件
    • JspServlet.service()处理流程:
      • 拼接servlet_pathpath_info
      • 生成JspServletWrapper
      • 解析并执行恶意文件中的代码

环境搭建与复现

环境准备

  1. 下载Tomcat 8.0.50

    • 源码:http://archive.apache.org/dist/tomcat/tomcat-8/v8.0.50/
    • 二进制发行版
  2. 配置pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.apache.tomcat</groupId>
  <artifactId>Tomcat8.0</artifactId>
  <version>8.0</version>
  <build>
    <finalName>Tomcat8.0</finalName>
    <sourceDirectory>java</sourceDirectory>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <!-- 添加必要依赖 -->
  </dependencies>
</project>
  1. IDEA配置
    • Main class: org.apache.catalina.startup.Bootstrap
    • VM options: -Dcatalina.home="apache-tomcat-8.5.34"

漏洞复现

  1. 任意文件读取

    • 构造AJP请求包,控制三个关键参数
    • 示例读取WEB-INF/web.xml:
      URI: /asdf
      javax.servlet.include.request_uri: /
      javax.servlet.include.path_info: WEB-INF/web.xml
      javax.servlet.include.servlet_path: /
      
  2. RCE复现

    • 先上传含恶意JSP代码的文件
    • 构造AJP请求:
      URI: /anyname.jsp
      javax.servlet.include.request_uri: /
      javax.servlet.include.path_info: /upload/malicious.file
      javax.servlet.include.servlet_path: /
      

防御措施

  1. 临时缓解

    • 注释掉conf/server.xml中的AJP Connector配置:
      <!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
      
  2. 长期方案

    • 升级到已修复版本
    • 网络层面限制8009端口的访问
  3. 架构建议

    • 避免Tomcat直接暴露在公网
    • 使用Apache/Nginx作为前端代理

技术总结

  1. 漏洞本质:AJP协议实现缺陷导致参数可控
  2. 利用条件:开启AJP服务(默认8009端口)
  3. 影响范围:所有使用默认配置的受影响Tomcat版本
  4. 利用限制
    • 文件读取限于webapps目录内
    • RCE需要先上传恶意文件

附录:关键调用链

文件包含调用链

SocketProcessor→AbstractAjpProcessor.prepareRequest()→
Request.setAttribute()→DefaultServlet.doGet()→
serveResource()→getRelativePath()→
StandardRoot.getResource()→validate()

RCE调用链

JspServlet.service()→serviceJspFile()→
JspServletWrapper.service()→Servlet.service()

注:本文基于Apache Tomcat 8.0.50版本分析,其他版本细节可能略有不同。

Apache Tomcat AJP协议文件包含与RCE漏洞深入分析教学文档 漏洞概述 CVE编号 :CVE-2020-1938 漏洞名称 :Apache Tomcat AJP协议文件包含漏洞 影响版本 :多个Tomcat版本(测试验证包括8.0.50等版本) 漏洞类型 :文件包含→远程代码执行(RCE) 危害等级 :高危 默认影响 :Tomcat默认配置中监听8009端口(AJP协议) 漏洞背景 AJP协议简介 AJP(Apache JServ Protocol)是一个二进制的TCP传输协议,特点: 专为Tomcat与前端Web服务器(如Apache HTTP Server)通信设计 相比HTTP纯文本协议,AJP具有更高效率和性能 默认监听8009端口 浏览器不支持直接发送AJP请求 Tomcat连接器架构 Tomcat默认配置两个连接器(Connector): HTTP Connector : 默认监听8080端口 处理所有HTTP请求(静态和动态资源) AJP Connector : 默认监听8009端口 专用于与前端Web服务器通信 使用率约7.8%(相对较低) 漏洞原理分析 漏洞核心 攻击者可通过AJP协议控制以下三个关键参数: javax.servlet.include.request_uri javax.servlet.include.path_info javax.servlet.include.servlet_path 通过操纵这些参数实现: 任意文件读取(文件包含) 远程代码执行(RCE) 漏洞位置 在Tomcat 8.0.50版本中,漏洞存在于: org.apache.coyote.ajp.AbstractAjpProcessor.prepareRequest() 方法 文件包含漏洞分析流程 请求处理流程 : AJP请求→SocketProcessor→AbstractAjpProcessor.prepareRequest() 攻击者控制的三个参数被存入Request对象的attributes(HashMap) Servlet路由 : 当请求URI无法匹配任何Servlet时,由DefaultServlet处理 DefaultServlet主要用于处理静态资源(HTML/图片/CSS/JS等) 路径拼接关键点 : DefaultServlet.getRelativePath() 进行路径拼接 使用攻击者控制的 path_info 和 servlet_path 参数 如果缺少 request_uri 参数会导致利用失败 路径规范化限制 : RequestUtil.normalize() 防止目录遍历: 不允许以"/../"开头的路径 不允许连续出现两个"/../" 结果:只能读取webapps目录内文件,无法读取上层目录 RCE漏洞分析流程 前提条件 : 需要先上传含有恶意代码的文件到webapps目录 文件扩展名不限(甚至无扩展名) 利用JspServlet : 默认处理.jsp和.jspx请求 功能:将JSP文件生成Servlet类→编译→执行 攻击流程 : AJP请求URI必须以".jsp"结尾(文件可不存在) path_info 参数指向上传的恶意文件 JspServlet.service() 处理流程: 拼接 servlet_path 和 path_info 生成 JspServletWrapper 解析并执行恶意文件中的代码 环境搭建与复现 环境准备 下载Tomcat 8.0.50 : 源码:http://archive.apache.org/dist/tomcat/tomcat-8/v8.0.50/ 二进制发行版 配置pom.xml : IDEA配置 : Main class: org.apache.catalina.startup.Bootstrap VM options: -Dcatalina.home="apache-tomcat-8.5.34" 漏洞复现 任意文件读取 : 构造AJP请求包,控制三个关键参数 示例读取WEB-INF/web.xml: RCE复现 : 先上传含恶意JSP代码的文件 构造AJP请求: 防御措施 临时缓解 : 注释掉 conf/server.xml 中的AJP Connector配置: 长期方案 : 升级到已修复版本 网络层面限制8009端口的访问 架构建议 : 避免Tomcat直接暴露在公网 使用Apache/Nginx作为前端代理 技术总结 漏洞本质 :AJP协议实现缺陷导致参数可控 利用条件 :开启AJP服务(默认8009端口) 影响范围 :所有使用默认配置的受影响Tomcat版本 利用限制 : 文件读取限于webapps目录内 RCE需要先上传恶意文件 附录:关键调用链 文件包含调用链 RCE调用链 注:本文基于Apache Tomcat 8.0.50版本分析,其他版本细节可能略有不同。