CVE-2026-86239:FeehiCMS UEditor 未认证文件上传漏洞

摘要

FeehiCMS 是基于 Yii2 框架的 PHP 内容管理系统。其后台访问控制白名单包含 assets/* 通配符条目,前缀匹配使 assets/ueditor 路由跳过身份验证,暴露 UEditor 文件上传组件。在后台入口网络可达且应用初始化完成的前提下,攻击者无需任何账户、Cookie、CSRF(跨站请求伪造)令牌或用户交互,即可上传文件至 Web 可访问目录并枚举已上传文件。运行时验证仅在 2.1.1 版本上以 .txt 文件完成,CVE 通告的影响范围标注为 2.1.1 及以下。已验证的影响为未经授权的文件上传与 UEditor 配置信息泄露;远程代码执行等更高危害未被运行时验证。

漏洞原理

授权白名单与前缀匹配

FeehiCMS 后台在 backend/config/main.php 中通过 AccessControl 过滤器配置行为鉴权。allowActions 数组列出免认证路由,其中包含 assets/* 通配符条目。AccessControl::isActive() 对通配符条目采用前缀匹配:只要请求路由以 assets/ 开头即视为匹配,从而跳过游客登录检查。该匹配方式将通配符的预期用途(开放静态资源)与实际效果(开放该前缀下所有动作)混为一谈,是认证绕过的根源。

控制器映射与 CSRF 禁用

AssetsController::actions() 将 ueditor 动作映射到 UeditorAction 类。由于 assets/ueditor 匹配白名单,该上传组件在未经认证的状态下可达。UeditorAction::init() 将 enableCsrfValidation 设为 false,使上传 POST 请求不经过 CSRF 校验。信任边界本应在认证与 CSRF 两处拦截未授权上传,但前缀匹配绕过了认证,CSRF 校验又被显式关闭。

上传校验与文件写入

Uploader 仅对文件名最后一个扩展名与 fileAllowFiles(40 个条目)做白名单比对,不校验 MIME 类型或文件内容。通过校验的文件被写入 frontend/web/uploads/ueditor/upload/file/ 目录,该目录位于 Web 根下,可通过 HTTP 检索。listfile 动作可枚举已上传文件的 URL 与时间戳。缺失的关键检查是:访问控制层未限制通配白名单前缀下不应暴露上传类特权动作,且上传层缺少独立于文件名的类型与内容验证。

触发条件与攻击逻辑

该漏洞的部署侧前提是后台入口网络可达且应用初始化已完成,这两项由部署方负责,非攻击者行为。攻击侧无需任何账户、Cookie、CSRF 令牌或用户交互,仅需向后台入口发送请求。攻击者利用 assets/* 白名单的前缀匹配特性,使 assets/ueditor 路由在未认证状态下到达 UEditor 上传组件;CSRF 校验已被禁用,上传请求仅经扩展名白名单即写入 Web 可访问目录,随后可通过返回的 URL 检索文件或经 listfile 枚举已上传内容。上述链路在 2.1.1 版本上经运行时验证;其他受影响版本为源码比对推断,未经动态确认。等价但未测试的条件包括相同配置下的其他部署环境。

核心伪代码

allowActions = ["site/*", "assets/*"]
route = resolveRoute(request)
if AccessControl.isActive(route, allowActions):
skip guestLoginCheck // prefix match: assets/* matches assets/ueditor
handler = resolveAction(route) // maps to UeditorAction
handler.init() // enableCsrfValidation = false
if action == "uploadfile" and method == POST:
ext = lastExtension(file.name)
if ext in fileAllowFiles: // extension-only, no MIME check
path = webRoot + uploadDir + filename
write(file, path)
respond(state=SUCCESS, url=publicUrl(path))

伪代码展示服务端从路由鉴权到文件写入的连续决策流。缺失的关键检查是:通配白名单 assets/* 的前缀匹配使 assets/ueditor 跳过认证,暴露了上传组件;上传层仅校验扩展名而无 MIME 或内容检查,使文件直达 Web 可访问目录。

影响范围

证据来源 版本/范围 结论
CVE 通告 2.1.1 及以下 通告影响范围,非逐版动态确认
源码比对 2.0.0、2.0.5、2.0.8、2.1.0、2.1.0.2、2.1.1、master 含 assets/* 白名单条目
源码比对 1.0.0rc2 不含该条目,判定为不受影响
运行时验证 2.1.1 唯一动态测试版本

运行时验证的影响(2.1.1):未经授权的文件上传(.txt)、Web 可访问的文件检索、已上传文件枚举、UEditor 配置信息泄露,均无 Cookie 或 CSRF 令牌。推断但未运行时验证的影响:钓鱼或恶意载荷托管、站点内容污染、磁盘耗尽。未验证的影响:RCE(远程代码执行)、存储型 XSS(跨站脚本)、SSRF(服务端请求伪造)、双扩展名绕过、其余 39 个白名单扩展名的上传行为。.php 扩展名被白名单阻止(源码层面)。无公开修复版本;2.1.1 为最新上游发布,master 分支仍受影响。CVSS 3.1 = 5.3、4.0 = 5.5(均为中危),由 CNA 分配,非独立重算。

修复与检测

修复应在两处信任边界着手。访问控制层应移除或收紧 assets/* 通配白名单,确保上传类控制器不在免认证路由下暴露;若必须开放静态资源,应以更精确的路由匹配替代前缀通配。上传层应引入独立于文件名的 MIME 类型与文件内容校验,不应仅依赖扩展名白名单。在无上游确认修复版本的情况下,建议在边界或 WAF(Web 应用防火墙)层限制对 assets/ueditor 等上传动作的未认证访问。以上为基于机制的修复建议,非厂商验证的指导。

检测方面,运行时观察(2.1.1)显示配置查询、上传与枚举动作均在无 Cookie 和 CSRF 令牌时返回成功,上传响应返回 state=SUCCESS。源码层面应检查 allowActions 是否包含覆盖上传控制器的通配条目,以及可达动作是否存在 enableCsrfValidation=false。这些为调查线索而非确证,需与正常使用场景关联分析,合法的静态资源访问也可能匹配相同前缀。

参考资料