上周一个朋友发来截图,说他的 WooCommerce 站后台收到了一堆异常请求日志,里面全是../、%2e%2e这样的路径穿越特征,他问我是不是被扫描了。我一看时间点,基本能对上——这轮扫描大概率就是冲着 CVE-2025-1661 这个 WooCommerce 本地文件包含漏洞来的。这个漏洞公告出来有一阵了,但很多人其实没意识到它有多值得重视,尤其是还在用旧版本、又堆了一堆插件的电商站。
本地文件包含(Local File Inclusion,LFI)在 PHP 应用里不算新鲜,但因为 WooCommerce 装得实在太广,一旦出现这类漏洞,影响面就不是“某个小插件的事情”了。攻击者不需要登录,只要构造一个特殊请求,就可能让服务器去加载并执行本不该被访问的本地文件,轻则读到数据库账号密码,重则结合其他条件直接控制整台服务器。这篇文章我把自己处理这类问题的思路、排查步骤和加固方法完整梳理一遍,适合正在维护 WordPress + WooCommerce 站点的开发者、站长,也适合想系统理解 LFI 漏洞原理的安全初学者。
1. 漏洞概览:CVE-2025-1661 到底是什么,影响有多广
1.1 先理解本地文件包含漏洞(LFI)是个什么概念
要理解 CVE-2025-1661,绕不开 LFI 这个基础概念。PHP 里有几个常用的文件操作函数:include、include_once、require、require_once,它们的作用就一个——把另一个文件的代码加载进来,然后当作当前程序的一部分执行。这本身是PHP提供的正常能力,模板引擎、语言包、配置加载都要靠它。
问题出在哪?出在“加载哪个文件”这个决定权被交给了用户。如果程序直接把 GET 参数、POST 参数、Cookie 里的值当成文件路径去 include,而没有任何过滤,攻击者就可以把这个参数改成一个特殊路径,比如../../../../etc/passwd,服务器就会真的去读取系统里的账号文件。这就好比你家小区的快递柜本来是一人一码对应一个柜子,但物管系统有漏洞,来的人随便输一串字符,打开的是楼上邻居的柜子。
电商站对这类漏洞尤其敏感。原因是 WooCommerce 站点承载的业务数据太敏感了——订单、用户手机号、地址、支付流水、后台数据库密码,全在一个系统里。LFI 漏洞一旦能被利用,最直接的后果就是“任意文件读取”,wp-config.php是几乎所有攻击者的头号目标,因为它里面躺着数据库主机、数据库名、用户名、密码。
1.2 CVE-2025-1661 的触发场景与受影响版本
CVE-2025-1661 属于 WooCommerce 插件中的本地文件包含漏洞,核心问题出现在某些文件路径参数未经严格校验就被用于文件操作。从目前公开的信息和同类漏洞的分布规律来看,这类触发点往往藏在订单导出、模板加载、报表下载、附件处理这类功能模块里——因为这些模块的业务逻辑天然需要“按名字或参数去取一个文件”。
举个例子你就明白了,一个导出订单 CSV 的功能,后端代码可能是这样的逻辑:接收一个type参数,然后根据这个参数拼接出文件路径,再通过 include 或文件读取函数输出内容。正常情况下type只允许是orders或refunds,但如果代码只做了 if-else 分支,没有对参数本身做一个“白名单校验”,攻击者传入type=../../../../tmp/shell之类的值,后端就可能跟着拼出一个危险的路径并执行。
受影响的版本方面,官方公告给出的修复版本很明确,凡是低于该修复版本的 WooCommerce 安装都应该视为潜在受影响。这个问题在开源插件里尤其容易被忽略,因为 WooCommerce 的更新节奏很快,很多站长习惯在后台看到红点就点升级,但也有大量站点用的是定制化修改过的版本、汉化包、或者第三方集成的主题包,根本收不到官方更新提示,这部分站点的风险实际上比官方源安装的站点更高。
1.3 影响范围判断:谁最该重视这个漏洞
先说结论:凡是自建独立站、用了 WooCommerce 搭建商城、且直接暴露在公网上的站点,都该重视。我再把优先级排一下:
- 使用了 WooCommerce 但长期不更新、处于“部署完就不管”状态的站点;
- 站点中安装了较多的第三方插件、主题,特别是来源不明的免费主题;
- 服务器配置了较高的 PHP 执行权限,没有做 disable_functions 限制;
- 没有 Web 应用防火墙(WAF)或访问日志分析,被扫描了都不知道。
很多人有一个误区,觉得“我的站小,流量少,不会有人盯上”。真实情况恰恰相反,攻击者从来不是人工挨个挑肥拣瘦,而是用扫描器批量扫全网,只要你的站暴露在公网,IP 一被扫到,就会自动进入攻击队列。你的站可能没有人为的“重点关注”,但漏洞扫描器对特征极其敏感,只要探测到请求响应符合特征,立刻就会跟进尝试利用,所以小站跟大站被攻击的概率在自动化扫描面前没有本质区别。
2. 深入原理:WooCommerce 为什么会出现本地文件包含问题
2.1 文件包含漏洞产生的机制拆解
从程序的角度看,LFI 漏洞的产生需要同时满足三个条件:第一,程序里确实存在用include、require、file_get_contents等函数去加载文件的地方;第二,这个加载的文件路径里包含了外部可控的变量;第三,外部可控的变量没有被有效地过滤或约束。三个条件缺一个,漏洞就不成立。
第一个条件好理解,每个 PHP 应用都离不开文件加载。第二个条件才是关键,以 WooCommerce 这样的大型插件为例,它的代码量非常大,模块之间的调用关系错综复杂,一个变量从 HTTP 请求进来,经过几层函数调用、封装、过滤,最后落到文件路径拼接处,中途任何一层的验证不够严谨,都可能把风险传递到最终的 include 调用。这也是为什么很多漏洞不是开发者故意留的,而是代码复杂度太高导致的“漏网之鱼”。
第三个条件——过滤不严——则是最常见的翻车点。很多开发者不是没有做防御,而是做错了方向。典型做法是只过滤了../,觉得把路径穿越符过滤掉就安全了。但攻击者的绕过思路非常多,URL 编码后的%2e%2e%2f、UTF-8 变体编码、Windows 下的反斜杠路径,甚至可以利用 PHP 内核函数对路径的解析差异来绕过滤。只做黑名单过滤等于在跟整个攻击生态对抗,几乎必输。
2.2 WooCommerce 里哪些功能模块容易被埋雷
我处理过几起类似的问题,也专门分析过 WooCommerce 的代码结构,直接说几个容易出现文件包含问题的典型业务场景:
第一个是“模板加载”。WooCommerce 允许主题覆盖默认模板,同时自身也有模板定位的逻辑。如果某个模板名参数可以由用户控制参与路径拼接,就存在风险。这里的难点在于模板系统太灵活,开发者为了支持自定义主题,往往用变量去动态拼模板路径,一个不小心就把用户输入带进去了。
第二个是“导出下载”。订单导出、报表导出是电商站的高频场景。导出功能的实现通常是后端生成一个文件,然后把文件路径传给前端或直接重定向到下载链接。如果这个文件路径由 GET 参数控制,攻击者完全可以修改参数指向其他文件,配合服务器配置直接拉取任意可读文件。
第三个是“附件与媒体处理”。WordPress 本身对上传文件的处理已经比较成熟,但 WooCommerce 里有很多附加的媒体逻辑,比如产品图片的缩略、备份文件的创建。这些逻辑在处理文件名时如果使用用户可控的字段,也可能把恶意路径带进文件系统函数。
你知道为什么这类漏洞在电商插件里反复出现吗?因为它本质上不是“某个字符串没过滤”的问题,而是电商业务本身太需要动态文件操作了——导出、下载、模板展示、附件管理,每一个都是合理的业务功能,每一个都需要处理路径,但每一个都容易漏掉验证。
2.3 LFI 能造成多严重的后果
LFI 最直接的能力是读取任意文件。对 WordPress 站点来说,wp-config.php是最典型的敏感目标,里面有数据库主机地址、数据库账号、数据库密码和认证密钥。拿到这些之后,攻击者可以直连数据库,篡改管理员账号、注入恶意脚本,站点基本就完全脱手了。
更进一步的场景是利用 LFI 实现远程代码执行(RCE)。常见路径有两条:一条是利用php://filter等伪协议读取源码,配合日志注入、session 文件注入或者临时文件上传,把一个写有 PHP 代码的本地文件落到服务器上,再通过 LFI 去包含它,最终拿到代码执行能力;另一条是结合文件上传漏洞,直接把恶意文件上传到服务器某个目录,再用 LFI 去 include 执行。这两条路径都有很多前置条件,比如服务器运行用户对特定目录有写权限、目标目录没有禁止 PHP 执行等,所以不是每个 LFI 都能直接升级成 RCE,但风险边界是真实存在的。
我不放完整的利用代码,这不是本文的目的,但你想理解这个漏洞的杀伤力,只要知道一件事就够了:LFI 是“权限边界突破”的跳板,它本身是信息泄露,跟其他漏洞组合就是代码执行。
提示:所有的排查和测试动作,都应该在你自己拥有授权的环境中进行,或者在你的 staging 环境中验证。对没有授权的网站进行任何形式的漏洞验证都是违法行为,技术边界和法律边界一样重要。
3. 排查与确认:怎样判断你的站点是否受影响
3.1 第一步永远是把版本信息摸清楚
排查任何漏洞的第一步,都是先确定你用的到底是哪个版本。以 WooCommerce 为例,登录 WordPress 后台,在“插件”页面找到 WooCommerce,可以看到当前版本号。如果你用的是国外主题和插件商店购买的正版授权,一般还会显示具体的版本分支。
拿到版本号之后,对照官方安全公告和主流漏洞库的信息。这几个途径都可以查:WordPress 官方安全公告页面、WooCommerce 产品的官方更新日志、第三方漏洞数据库(比如 WPScan 的漏洞库)。查的时候注意两个细节:第一,公告里写的“受影响版本区间”是什么,你的版本是否落在区间内;第二,公告里给出的“修复版本号”是多少,你的版本是否低于修复版本。
还有一种情况经常被忽略——你看到的版本号可能是被修改过的。有些第三方开发者为了隐藏修改痕迹,会把插件包里的版本号改成固定值,导致后台显示的是正常版本,但实际代码已经被改过了。这种情况下,单纯的版本对照就不够用了,需要结合其他手段来确认。
3.2 测试环境验证与风险确认方法
如果你确定自己的版本落在受影响区间,或者不确定但想进一步确认,不要直接在线上生产环境做扫描和探测,正确做法是搭建一个 staging 环境,也就是复制一份线上环境的副本,在副本上进行验证。这个环境要和线上保持一致的 PHP 版本、WordPress 版本、WooCommerce 版本和插件组合,这样测出来的结果才有参考意义。
在 staging 环境中,可以选择使用专业的漏洞扫描工具来辅助确认。扫描工具的原理是通过发送无害的检测请求,观察响应特征来判断漏洞是否存在。工具报告里如果提示存在 LFI 风险,你再根据提示的 URL 和参数位置做人工核查,确认是否真的存在用户可控的文件路径参数。
我个人不建议对生产站点直接执行这类测试,原因很简单:一是触发漏洞本身可能对业务造成影响,比如意外加载了一个大文件导致 PHP 内存耗尽;二是即使没有实际利用,漏洞扫描的行为特征也会被服务商的安全系统记录,处理起来麻烦。
3.3 日志审计:最可靠的风险证据
如果版本对照和工具扫描都难以确定,日志审计是最可靠的手段。我处理漏洞事件时,第一个去的地方永远是访问日志。不管是 Nginx 还是 Apache,访问日志都会记录每一个进来的 HTTP 请求,包括请求的 URL、参数、来源 IP、时间戳。
针对 LFI 漏洞,你应该重点检索这些特征:
- URL 参数中带有
../、..%2f、..%252f等路径穿越编码; - 参数中带有
php://filter、php://input等 PHP 伪协议前缀; - 参数中带有常见敏感文件路径,比如
/etc/passwd、wp-config.php、.env; - URL 路径片段包含
file、template、download、export、include等关键词。
日志里如果出现这类请求,说明你的站点已经被扫描器盯上了,攻击者在尝试探测是否存在文件包含点。这时候要做的是继续往下排查:这些请求是从什么 IP 发来的、是单次尝试还是反复测试、请求的目标路径是否是 WooCommerce 的已知功能入口。
除了访问日志,还要看 PHP 错误日志和 WordPress 的 debug.log。如果攻击者的请求触发了文件加载函数的报错,这些日志会留下痕迹,比如提示某个文件不存在或路径被拒绝的警告信息。这些信息能帮你还原攻击者的尝试路径,判断漏洞是否真的被触达过。
4. 修复与加固:升级只是起点,纵深防御才是终点
4.1 官方补丁与版本升级的正确姿势
CVE-2025-1661 的修复核心是升级 WooCommerce 到官方发布的修复版本。听起来很简单,但实际执行时有很多细节值得注意。
升级之前,先做备份。备份的东西有两块:数据库和 web 目录的全部文件。数据库用后台自带的导出或数据库管理工具导出一份;文件这块,至少要把wp-content目录完整打包一份,因为主题、插件上传、自定义代码都集中在里面。备份的目的是为了万一升级后出现兼容性问题,可以快速回滚。
备份完成后,建议先在 staging 环境执行升级,确认没有兼容性问题之后再动线上。升级本身的操作就是后台的“更新”按钮,但如果你用的是通过 FTP 或者命令行方式部署的环境,需要手动下载新版本插件包并替换文件,注意先停用插件再替换,然后重新启用。
升级完成后,确认版本号已经变成修复版本,然后清理缓存。WooCommerce 有自己的缓存目录,WordPress 也可能装了缓存插件,升级之后这些缓存都要清一遍,否则可能继续加载旧代码,给自己造成“明明升级了怎么还有问题”的假象。
4.2 代码层面的主动加固
升级只能解决已知漏洞,代码层的主动加固才是长期安全的保障。这里分享几个我实际用过的策略。
第一,对文件路径做规范化校验。PHP 提供了一个函数叫realpath(),它能把一个路径解析成真实的绝对路径。正确做法是:拿到用户传入的路径参数后,先通过realpath()规范化,再检查解析后的路径是否在允许的目录前缀之下。比如允许的目录是/var/www/html/wp-content/themes/,那就看解析后的路径是否以这个前缀开头,不是就直接拒绝。这个方案能有效拦截所有形式的路径穿越,因为无论你怎么编码绕过,最终到达文件系统时都会变成真实的绝对路径。
第二,对所有包含文件内容的函数参数做白名单校验。比如模板加载,不要直接 include 用户传来的字符串,而是维护一个固定的模板名数组,用户传什么就往数组里查,查不到就用默认值。这是一个很朴素但极其有效的方案,直接在业务逻辑层面把输入约束死了。
第三,检查服务器和 PHP 配置。PHP 配置里有一个allow_url_include的选项,默认是关闭的,务必确认它没有被打开,否则攻击者可以直接用远程 URL 包含任意网站文件。另外,disable_functions里可以考虑禁用一些高危函数,比如shell_exec、exec、system、passthru、popen,这些函数不是 WordPress 运行必需的,禁用它们能显著缩小攻击者拿到代码执行能力之后的破坏范围。
4.3 Web 应用层面的纵深防御
代码加固是治内,纵深防御是御外。对 WordPress 电商站,我建议至少做四层防护。
第一层是 Web 应用防火墙(WAF)。商业 WAF 或者开源方案都行,核心是开启针对路径穿越和文件包含的规则。WAF 的价值在于即使应用还没升级或者代码里存在未知的文件包含问题,攻击者的尝试请求也会在到达 PHP 之前被拦截。
第二层是 Web 服务器层的目录控制。在 Nginx 或 Apache 配置中,对关键目录做执行权限隔离,比如wp-content/uploads/目录本身只应存放图片等静态资源,文件头应该明确禁止该目录下执行 PHP 脚本。这样即使攻击者通过上传功能把恶意 PHP 文件传到了 uploads 目录,也没法通过 Web 请求直接触发执行。
第三层是文件系统权限收紧。wp-config.php的权限应该设置为 600 或 640,确保只有运行 PHP 的用户能读;web 目录里不需要写的文件一律只读。这条防线可以防止攻击者读取到敏感文件后继续横向操作。
第四层是安全监控。安装一份安全审计插件,比如 Wordfence、iThemes Security 等,开启文件完整性监控功能。这类插件会定期扫描核心文件和主题插件文件,发现被修改时立刻报警。对电商站来说,人为介入的时间越早,损失就越小。
5. 常见问题与实操心得:踩过一次坑之后的经验总结
5.1 升级后站点白屏、插件异常,怎么处理
升级 WooCommerce 后最常见的两个问题:白屏和插件冲突。白屏通常有两种原因,一是 PHP 代码报错但错误显示被关闭了,二是新版本与原主题或插件不兼容导致致命错误。
遇到白屏先别慌,打开 WordPress 的调试模式,在wp-config.php中加上define('WP_DEBUG', true);和define('WP_DEBUG_DISPLAY', true);,刷新页面,具体报错信息就会显示出来。看到报错后,判断是哪个文件导致的,一般是主题目录里的某个函数调用签名不匹配,或者某个插件使用了废弃函数。短期处理方式是停用冲突插件或更换主题,长期是联系主题/插件作者提供兼容性修复。
如果实在无法快速解决,回滚是最安全的选择。用之前备份的插件文件和数据库恢复原样,站点恢复正常后再分步排查。
5.2 装了安全插件就能高枕无忧吗
说实话,安全插件的作用远没有大多数人想的那么大。安全插件能做的主要是三件事:修改登录地址、限制登录尝试次数、周期性扫描文件是否被篡改。对 LFI 这类应用层漏洞,安全插件本身不具备直接修复能力——它既不能帮你打补丁,也不能替代代码审查。
安全插件真正的价值在于“感知”,它能让你第一时间知道站点出现了异常,比如敏感文件被修改、有恶意请求触发告警。我遇到的情况是:装了安全插件的站点,往往在攻击者刚开始探测时就会收到报警,给站长留出反应时间;没装的站点,往往等到搜索引擎提示“站点可能已被入侵”时才知道出了问题,两三天时间足够攻击者把数据拖走了。
所以我的建议是:安全插件要装,但把它当成监控工具来用,不要当成万能盾牌。真正修复漏洞的永远是对代码的修缮和对版本的及时升级。
5.3 扫描日志里发现了攻击尝试,但没实际得手,还需要处理吗
需要处理,而且要认真处理。攻击尝试本身就是一种信号,说明你的站点已经被自动化扫描器探测到了。攻击者可能今天尝试了 LFI 没成功,但如果你的站点存在其他漏洞,或者之后新增了有漏洞的插件,同一批攻击者很可能会回来继续尝试。
处理流程分三步:先根据日志特征判断攻击尝试是否触达过目标文件,触达过就深入排查文件完整性和敏感信息泄露情况;然后把攻击者的 IP 加入防火墙黑名单,并在 WAF 上临时添加拦截规则;最后复盘一下你的站点当前的整体安全状态,做过版本升级、代码加固和权限收紧之后再恢复正常运营。
尽量不要因为“没得手”就忽略这些日志。我见过不少被入侵的案例,回看日志发现攻击者在两周前就开始尝试了,但站长没当回事。漏洞被修复则已,一旦后来暴露了一个可利用的入口,之前积累的踩点信息就会立刻转化为攻击路径。
5.4 关于漏洞处置,我这些年最想说的几点心得
处理了这么多 WordPress 漏洞事件,我自己最深的体会是——安全问题本质上不是技术问题,而是流程问题。一个站点只要做到“版本持续更新、备份持续有效、日志持续监控”,绝大多数已知漏洞都能在窗口期内被修复,根本轮不到攻击者利用。
具体到这次 CVE-2025-1661 的处置,我想提醒所有维护 WooCommerce 站点的朋友:漏洞公告出来后的一周到两周是攻击最密集的窗口期,因为扫描器会第一时间更新检测规则并批量扫描全网。在这个窗口期内,优先做升级,升级不了的先用代码加固和 WAF 规则补上,至少让攻击请求打不进来。窗口期一过,针对这个漏洞的攻击流量会有所回落,但也不能放松,因为扫描器是周期性轮询的,随时可能再回来。
另外一个很值得做的事是订阅漏洞情报源。WordPress 官方安全公告、WooCommerce 的更新日志、几个主流漏洞库的邮件订阅,都可以设置提醒。与其等新闻爆出来再慌慌张张处理,不如让安全信息每天定时到你手上,把应急响应的节奏从“事后救火”变成“事前预防”。
最后说一句可能不太中听但很实在的话:如果你的站点托管在虚拟主机上、连备份都不知道在哪里设置、也不清楚自己用的 PHP 版本是多少,那比起研究单个漏洞怎么修复,你更迫切的任务是先补齐最基础的安全习惯——备份和更新这两件事做好了,你已经跑赢相当一部分同类站点了。