CVE-2017-9442漏洞复现:Bigtree CMS文件上传与路径穿越分析 📅 2026/6/30 18:11:15 1. 项目概述与背景最近在整理一些老旧的CMS漏洞案例Bigtree CMS的CVE-2017-9442这个文件上传漏洞引起了我的注意。这个漏洞虽然年代有点久远是2017年披露的但它的成因和利用方式非常经典对于理解Web应用安全中“黑名单过滤”的缺陷以及路径穿越的利用有着教科书般的意义。很多新手在学习文件上传漏洞时往往只关注如何绕过前端验证或者MIME类型检查但这个案例告诉我们后端对文件路径的处理不当同样会打开一个巨大的安全缺口。Bigtree CMS在4.2.18及之前版本中其核心文件上传处理器存在一个逻辑缺陷允许攻击者通过精心构造的HTTP请求将恶意文件上传到Web目录之外的任意位置甚至覆盖关键系统文件从而直接获取服务器权限。今天我就带大家从零开始完整地复现这个漏洞并深入剖析其背后的原理。无论你是刚入门的安全爱好者还是想巩固Web安全基础的同学跟着走一遍这个过程相信都会有新的收获。2. 漏洞原理深度剖析2.1 漏洞核心路径穿越与黑名单失效CVE-2017-9442的本质是一个未授权任意文件上传漏洞。它的核心问题出在Bigtree CMS处理用户上传文件时对文件路径参数name的过滤和校验存在严重缺陷。在正常的文件上传流程中开发者通常会做以下几件事来防御检查文件扩展名白名单或黑名单。检查文件MIME类型。将上传的文件重命名为随机名称。将文件存储在指定的、非Web可访问的目录。Bigtree CMS在这个漏洞版本中其core/admin/modules/developer/upgrade/process.php文件或其他类似的处理脚本负责处理插件或主题的升级包上传。问题在于它虽然有一个黑名单来阻止上传.php,.php5,.phtml等明显危险的脚本文件但它犯了一个关键错误它先检查了黑名单然后将用户可控的$_FILES[‘file’][‘name’]参数直接拼接到了目标路径中而没有对路径进行规范化或防止目录穿越的检查。攻击者可以提交一个这样的文件名../../../shell.php。黑名单检查发现后缀是.php于是拒绝。但是如果攻击者提交的文件名是../../../shell.php.jpg呢黑名单检查.jpg后缀通过然后这个包含路径穿越序列../的文件名被直接拼接到了目标基础路径上最终可能导致文件被写入/var/www/html甚至系统根目录等预期之外的位置。更糟糕的是如果服务器配置允许解析.jpg文件中的PHP代码在某些特定配置下可能发生或者攻击者能结合其他漏洞如本地文件包含那么这个.jpg文件同样能变成后门。注意这里的关键在于过滤逻辑和路径拼接逻辑的顺序与完整性。只过滤扩展名而不净化路径就像只锁了前门却把后门的钥匙挂在门上。2.2 影响版本与组件定位根据公开的漏洞信息受影响的版本主要是Bigtree CMS 4.2.18及之前的所有版本。漏洞存在于后台管理模块中通常与插件/主题安装、升级功能相关。具体到漏洞利用我们关注的是后台的/core/admin/modules/developer/upgrade/process.php这个脚本路径可能因版本略有差异。这个脚本通常需要一定的管理员权限才能访问但在一些默认配置或弱口令情况下攻击者可能直接进入后台。理解漏洞存在的具体位置有助于我们在代码审计时快速定位类似问题。其代码模式通常是$upload_dir /some/base/path/; $filename $_FILES[upgrade_file][name]; // 用户完全可控 // 简单的黑名单检查 if (in_array(strtolower(pathinfo($filename, PATHINFO_EXTENSION)), $blacklist)) { die(Forbidden file type.); } // 直接拼接未过滤 ../ move_uploaded_file($_FILES[upgrade_file][tmp_name], $upload_dir . $filename);这种“检查-拼接”的模式缺少了中间关键的一步路径规范化。应该使用basename()函数去除路径部分或者使用realpath()检查最终路径是否在允许的目录内。3. 复现环境搭建与配置3.1 靶机环境准备为了安全且不影响生产环境我们必须在隔离的环境中进行复现。我推荐使用Docker快速搭建一个漏洞环境这是目前最方便、最干净的方式。首先我们需要找到一个包含Bigtree CMS 4.2.18版本的Docker镜像或者源码。由于这是一个历史漏洞官方可能不再提供该版本的下载。我们可以通过一些开源漏洞靶场平台获取或者从历史镜像仓库中寻找。这里假设我们已经下载了Bigtree CMS 4.2.18的安装包。我习惯使用docker-compose来管理服务这样配置更清晰。创建一个docker-compose.yml文件version: 3 services: bigtree-cve: image: php:7.2-apache # 使用与当时接近的PHP版本 container_name: bigtree_cve_2017_9442 ports: - 8080:80 volumes: - ./bigtree-4.2.18:/var/www/html # 将源码挂载到Web根目录 - ./uploads:/var/www/html/uploads # 单独挂载上传目录方便查看 environment: - APACHE_RUN_USERwww-data - APACHE_RUN_GROUPwww-data networks: - vuln-net networks: vuln-net: driver: bridge下载源码将Bigtree CMS 4.2.18的源码解压到宿主机当前目录的bigtree-4.2.18文件夹下。配置权限确保Apache在容器内以www-data用户运行对Web目录有写权限。在宿主机上执行chmod -R 755 bigtree-4.2.18通常是一个起点但更精细的权限设置更好。启动环境在包含docker-compose.yml的目录下运行docker-compose up -d。访问安装打开浏览器访问http://localhost:8080/按照Bigtree CMS的安装向导完成安装。数据库可以选择使用Docker再启动一个MySQL容器或者为了方便使用SQLite如果Bigtree支持。安装过程中记下你设置的后台管理员账号密码。3.2 攻击机工具准备攻击机就是我们自己的物理机或虚拟机。需要准备以下工具Burp Suite Professional/Community用于拦截、修改和重放HTTP请求是Web漏洞测试的核心工具。社区版足够用于本次复现。浏览器推荐Chrome或Firefox并配置好代理指向Burp Suite通常是127.0.0.1:8080。一句话Webshell准备一个简单的PHP一句话木马文件例如内容为?php eval($_POST[‘cmd’]);?将其保存为shell.php。注意在实战中使用此类木马必须获得明确授权否则是违法行为。中国菜刀/C刀/蚁剑等Webshell管理工具可选用于验证上传的Webshell是否可用。同样仅限授权测试使用。4. 漏洞利用步骤详解4.1 信息收集与入口点寻找首先我们需要登录到Bigtree CMS的后台。默认后台地址通常是http://靶机IP:端口/core/admin/。使用安装时设置的管理员账号密码登录。登录后我们的目标是找到存在漏洞的文件上传点。根据漏洞描述它位于开发者模块的升级功能中。因此在后台侧边栏或菜单中寻找“Developer”、“扩展”、“升级”或“Marketplace”相关的选项。可能的具体路径是Core - Developer - Upgrade或类似。找到类似“Install Extension”、“Upload Package”、“Local Upgrade”的按钮或表单。这个表单就是我们上传文件的入口点。4.2 利用Burp Suite拦截与修改请求配置代理确保浏览器代理设置为Burp Suite并且Burp的代理监听是开启的Proxy - Intercept is on。触发上传在Bigtree后台的上传页面选择我们准备好的shell.php文件然后点击上传按钮。拦截请求此时Burp Suite会拦截到发出的HTTP POST请求。我们将看到类似如下的请求体部分POST /core/admin/modules/developer/upgrade/process.php HTTP/1.1 Host: localhost:8080 Content-Type: multipart/form-data; boundary----WebKitFormBoundaryABC123 ... ------WebKitFormBoundaryABC123 Content-Disposition: form-data; nameupgrade_file; filenameshell.php Content-Type: application/octet-stream ?php eval($_POST[cmd]);? ------WebKitFormBoundaryABC123--可以看到filename参数是”shell.php”。直接发送这个请求后端肯定会因为.php在黑名单中而拒绝。修改请求绕过黑名单这是关键步骤。我们将filename参数修改为包含路径穿越且以合法后缀结尾的名称。例如filename”../../../shell.php.jpg”这里../的目的是让文件跳出预定的上传目录shell.php.jpg是为了绕过黑名单检查检查.jpg通过而最终我们希望服务器能以PHP方式解析这个文件。这通常需要另一个条件如文件包含漏洞或畸形解析配置但在这个漏洞的经典利用中有时直接上传到Web根目录的上一级再通过路径穿越回来访问或者利用某些Apache配置如AddType application/x-httpd-php .jpg错误可能成功。更通用的利用是上传到Web目录内然后通过其他方法触发代码执行。但针对CVE-2017-9442更直接的利用可能是尝试覆盖一个已存在的、非.php后缀但可执行的文件或者上传到某个可通过Web直接访问的路径。我们需要结合实际情况测试。例如尝试将文件上传到Web根目录filename”../../../../var/www/html/uploads/shell.php.jpg”需要根据容器内实际路径调整../的数量。发送请求并观察响应修改完成后点击Burp Suite的“Forward”按钮发送请求。仔细观察服务器的响应。如果返回成功、重定向到某个页面或者没有明显的错误信息就可能上传成功了。4.3 Webshell上传与验证定位上传文件如果请求成功我们需要找到文件究竟被上传到了哪里。这需要一些猜测和测试。尝试访问http://localhost:8080/uploads/shell.php.jpg。尝试访问http://localhost:8080/shell.php.jpg。如果使用了路径穿越../../../文件可能被上传到了容器根目录甚至宿主机目录取决于挂载点。我们可以进入Docker容器内部查找docker exec -it bigtree_cve_2017_9442 bash然后使用find / -name “shell.php.jpg” 2/dev/null命令搜索。查看Bigtree的代码或配置文件确定默认的上传基础路径$upload_dir是什么。连接Webshell一旦找到文件并确认其可通过Web访问返回200状态码就可以尝试用Webshell管理工具连接了。在蚁剑中添加一个数据URL填写我们找到的Webshell地址如http://localhost:8080/uploads/shell.php.jpg。连接密码填写我们木马中设定的cmd。尝试连接。如果连接成功并可以执行命令如whoami、pwd则证明漏洞复现成功我们获得了服务器的命令执行权限。5. 漏洞修复方案与安全启示5.1 官方修复与自查Bigtree CMS官方在后续版本中修复了此漏洞。修复方案通常包括强化路径校验在拼接文件路径前使用basename()函数提取文件名彻底剥离任何目录路径防止目录穿越。$safe_filename basename($_FILES[‘upgrade_file’][‘name’]); $target_path $upload_dir . $safe_filename;使用白名单替代黑名单只允许一组明确安全的文件扩展名如.zip,.tar.gz用于升级包拒绝其他所有类型。文件重命名不使用用户提供的文件名而是使用随机生成的文件名如UUID存储文件并保留原始文件名在数据库中。目录权限隔离将上传的文件存储在Web根目录之外并通过脚本或CDN来访问它们避免直接执行。如果你正在维护使用旧版本Bigtree或其他CMS的系统应立即检查所有文件上传处理逻辑确保同时做到了以上几点。5.2 对开发者的安全启示这个漏洞给所有开发者上了一堂生动的安全课永远不要信任用户输入$_FILES[‘file’][‘name’]和其他任何来自客户端的参数一样可以被任意篡改。黑名单是脆弱的攻击者总能找到不在你名单上的危险扩展名或利用解析特性。白名单是唯一可靠的方式。路径操作必须谨慎任何涉及文件系统路径拼接的操作都必须进行规范化并检查最终路径是否在预期范围内。最小权限原则运行Web服务的用户如www-data只应拥有对必要目录的最小写权限绝不能拥有对系统关键目录或Web根目录的写权限。纵深防御除了代码层面的修复还应考虑服务器层面的配置如配置Web服务器禁止执行上传目录中的脚本、定期进行安全扫描等。6. 拓展文件上传漏洞的常见绕过方式CVE-2017-9442主要利用了路径穿越这只是文件上传漏洞的冰山一角。在实际渗透测试中攻击者会尝试多种组合拳来绕过防御。了解这些手法才能更好地防御。绕过类型原理描述示例/方法防御建议前端验证绕过仅通过JavaScript检查文件扩展名。禁用浏览器JS、使用Burp拦截修改请求、直接发送POST请求。后端必须做完全相同的校验前端校验仅用于提升用户体验。MIME类型绕过检查Content-Type头。将PHP文件的Content-Type改为image/jpeg或text/plain。检查文件内容的魔术头Magic Bytes并结合扩展名白名单。扩展名黑名单绕过名单不全或解析特性。尝试.php5,.phtml,.phps,.php7或在Apache中可能被解析的.php.jpg畸形解析。使用白名单只允许已知安全的类型。配置服务器不解析陌生扩展名。内容校验绕过检查文件开头/结尾的特定字节如图片头。在Webshell代码前添加合法的图片文件头如GIF89a制作图片马。使用更严格的内容解析校验如图库函数重采样图片或将上传文件存储在非Web目录。条件竞争绕过服务器先保存文件再检查/重命名中间存在时间窗口。急速并发上传和访问文件在文件被删除前访问并执行它。将文件先保存到临时随机名完成所有安全检查后再移动到最终位置并重命名。解析漏洞绕过Web服务器如IIS、Nginx、Apache的特定配置导致非脚本文件被解析。IIS的shell.php.jpg分号解析、Nginx的shell.jpg/.php路径解析错误。及时更新中间件版本审查并加固服务器配置删除不必要的处理器映射。路径穿越/目录遍历未过滤文件名中的路径序列。本次CVE-2017-9442的利用方式../../../shell.php.jpg。使用basename()或类似函数净化文件名或检查最终路径是否在允许的目录内。7. 复现过程中的常见问题与排查在复现过程中你可能会遇到一些问题。这里记录了几个我踩过的坑和解决方法上传请求被拒绝返回“Invalid File Type”原因黑名单检查生效。你使用的文件名后缀可能仍然在黑名单中或者不在允许的白名单内。排查仔细查看Bigtree的源代码找到$blacklist数组的具体内容。尝试使用一个绝对冷门的、但可能被系统需要的扩展名或者尝试.php.jpg这种双扩展名注意有些检查会取最后一个点之后的部分有些取第一个。更好的方法是直接搜索源码中对pathinfo或explode(‘.’, $filename)的使用逻辑。上传成功但找不到文件或访问返回404原因路径穿越的层级不对文件被上传到了非Web目录或者根本不存在。排查计算../数量这需要知道目标脚本的当前工作目录getcwd()和Web根目录的绝对路径。一个笨办法但有效的方法是先上传一个正常的文件如test.txt然后在服务器上找到它的位置从而反推出基础路径。再根据基础路径到Web目录的相对位置计算需要多少层../才能跳出来。查看服务器错误日志Apache或Nginx的错误日志通常在/var/log/apache2/error.log或/var/log/nginx/error.log会记录文件操作警告或错误这是黄金信息源。在Docker容器内用tail -f命令实时查看。使用绝对路径尝试如果知道Web根目录的绝对路径如/var/www/html可以尝试直接将其作为文件名的一部分但这通常会被过滤或者通过大量../跳到根目录再向下找。文件找到且可访问但PHP代码不执行原因服务器没有将.jpg文件配置为PHP解析。此时文件被当作静态图片或文本处理源代码会直接显示在浏览器中。解决这说明仅靠这个上传漏洞可能无法直接getshell。需要寻找文件包含LFI漏洞配合。例如如果网站存在一个参数可以包含本地文件如?page../../../uploads/shell.php.jpg并且该参数未过滤那么包含我们的图片马就可能执行其中的PHP代码。这就需要结合其他漏洞进行利用。Docker环境无法连接数据库或安装失败原因Bigtree安装程序可能无法连接到指定的数据库主机localhost在容器内指容器本身。解决如果使用Docker Compose可以额外定义一个MySQL服务并将Bigtree服务的数据库主机配置为MySQL的服务名如db。或者在安装时使用宿主机的IP地址对于Mac/Windows的Docker Desktop通常是host.docker.internal作为数据库主机地址。复现历史漏洞不仅是学习攻击手法更重要的是理解防御思路。通过亲手搭建环境、修改请求、观察结果、排查问题这一整套流程你对文件上传漏洞的认识会比只看文章深刻十倍。每一次“失败”的尝试都在告诉你防御机制在哪里起了作用而这正是提升你安全开发能力的关键。