漏洞

两条 Joomla 公共上传路径如何抵达 PHP 执行

7 月 10 日的 KEV 更新把两项已遭利用的 Joomla 扩展上传漏洞纳入同一个处置队列,但二者的可达路径、Joomla 核心成立条件、修复方式与证据边界均不相同;iCagenda 首修为 4.0.8/3.9.15,当前复核版本为 4.0.11,Balbooa Forms 首修为 2.4.1,当前复核版本为 2.4.2。

暖纸手绘调查台上,iCagenda 事件表单与 Balbooa 附件表单沿两条不同轨道进入同一处 Web 根目录执行舱,修复后分别通过访问、类型与惰性存储关口。
文章导航

研究依据固定来源复核 CISA 利用状态、两项 CNA 记录、iCagenda 4.0.7/4.0.8 控制器与模型差异、Balbooa Forms 事件与修复说明、版本边界,以及防御性修复与事件响应验证

来源CISA KEV / Joomla CNA 与官方 API / JoomliC 公告及固定软件包 / Balbooa Forms 官方更新日志 / mySites.guru 第一手事件研究 / SOSEC 软件包差异复核

1 7 月 10 日合并的是两条事件时钟,而非两种机制

2026 年 7 月 10 日,CISA 将 CVE-2026-48939CVE-2026-56291 纳入已知遭利用漏洞目录,并要求受约束的联邦系统在 7 月 13 日前完成修复。正是这一行动决定了为什么要把 iCagenda 与 Balbooa Forms 的缺陷放在一起调查:两条已经遭利用的 Joomla 扩展上传路径由此进入同一个处置队列。它并不能证明两起事件出自同一操作者、共用基础设施、属于协同攻击活动,甚至不能证明二者犯了同一种软件错误。公开资料呈现的是不同的发现过程、不同的脆弱函数、不同的修复方式,以及文件从被接收到获得执行之间的不同成立条件。把“两项 Joomla 上传漏洞”视作一个泛化缺陷,恰恰会抹去暴露面负责人作出判断所需的差异:站点是否曾受影响、已存内容能否执行,以及更新后究竟必须验证什么。

在 KEV 收录之前,两条时钟已经启动。JoomliC 称,针对 iCagenda 的自动化利用始于 6 月 15 日 08:00 UTC;它在当天发布了适用于 Joomla 4 至 6 的 iCagenda 4.0.8,并于 6 月 16 日为旧版 Joomla 3 发布修复版本 3.9.15。CVE-2026-48939 的 Joomla CNA 记录于 6 月 20 日出现。CISA 的利用评估先从无公开证据变为 7 月 2 日的概念验证证据,再于 7 月 10 日变为活跃利用。Balbooa 调查则始于 7 月 8 日的一份托管服务商滥用通知和来自在线站点的原始访问日志,当天完成私下披露;Balbooa 于 7 月 9 日发布 Forms 2.4.1,CNA 同日公布 CVE-2026-56291;次日,CISA 将其标记为活跃利用并纳入 KEV。这些时间线足以支持紧急开展失陷审查,却都没有给出受害站点数量,也没有提供可长期跨事件沿用的指标。

1.1 先把函数、版本和临时关口钉在同一张图上

iCagenda 的两处失效分别位于操作入口和附件写入链:4.0.7 的 Site\Controller\SubmitController::submit() 检查会话令牌,却没有在进入模型前落实 submitAccess 受众和提交视图菜单;SubmitModel::submit() 又把附件交给 frontendFileUpload(),最终由 Joomla\Filesystem\File::upload() 写入默认的 images/icagenda/frontend/attachments/,而没有经过后来补上的 MediaHelper::canUpload()。JoomliC 列出的受影响子范围为 Joomla 2.5 上的 3.2.1–3.6.14、Joomla 3 上的 3.2.1–3.9.14、Joomla 4 上的 3.8.0–4.0.7、Joomla 5 上的 3.9.0–4.0.7,以及 6.1.2 之前 Joomla 6 上的 3.9.14–4.0.7;Joomla 4–6 首修为 4.0.8,Joomla 3 首修为 3.9.15,当前复核的 4.x 版本是 4.0.11。Joomla 2.5 已停止支持,不能把 3.9.15 当作该平台的修复。

Balbooa Forms 的入口是 form.uploadAttachmentFile,写入函数是 FormModel::uploadAttachmentFile():2.4.0 及更早版本无需账户或 CSRF 令牌便可抵达模型,File::makeSafe() 清理文件名材料后仍保留由客户端名称派生的扩展名,并把结果存入 images/baforms/uploads/form-<id>/。CNA 与 NVD 将 1.0–2.4.0 列为受影响范围;2.4.1 首次加入字段扩展名策略、可选 MIME 策略、服务端随机名称和 CSRF 防护,当前复核版本为 2.4.2。两条路径都需要永久升级:在升级与验证完成前,可关闭或严格限制相应公共提交入口,并在实际上传目录强制禁止脚本执行;这些措施只能暂时截断可达性或存储到执行的最后一步,不能修复旧代码,也不会清除更新前已写入的文件。

1.2 适用性判断始于产品、核心与处理器状态

一条可供行动的资产记录,不能只有 Joomla 核心版本和 CVE 标记。它还应包含扩展软件包及准确的已安装版本、受影响前端功能是否启用且可访问、已配置的提交受众或表单字段、解析后的文件系统目标位置,以及 Web 服务器针对该目标的处理器策略。被禁用的菜单和未发布的表单同样需要检查,因为界面呈现状态不一定会移除仍可路由的组件任务,而更新前写入的文件可能继续被直接提供。替代图像根目录、反向代理映射、逐目录配置、PHP-FPM 路由和托管平台模板,也可能使实际执行边界不同于 Joomla 配置表面呈现的边界。

iCagenda 矩阵包含两种相关但不相同的结果。JoomliC 公告称,访客事件提交弱点影响所列各代 Joomla:未经授权的请求可以创建一个在存储中已发布、但尚未获批且不会以已批准事件形式显示的事件。公告和第一手事件报告把任意可执行附件这一结果限定在 Joomla 6.0.0 至 6.1.1;在该区间,先前框架层的拒绝没有阻止测试中的 PHP 上传。因此,较旧 Joomla 版本上的 iCagenda 站点仍可能暴露该操作,即使其核心媒体层阻止了报告中的代码执行结果。处于受影响 Joomla 6 区间的 iCagenda 站点则可能同时满足两个条件:配置受众之外的调用者能够进入处理流程,且保留服务端可执行类型的附件能够写入由 Web 提供的媒体路径之下。

Balbooa 记录呈现的是另一张控制图。Forms 2.4.0 及更早版本暴露了一项前端附件任务,其控制器到模型的交接既不要求账户,也不要求 CSRF 令牌;模型还信任客户端文件名携带的类型信息。第一手报告把目标位置确定为 images/baforms/uploads/form-<id>/ 之下。只有当服务器实际配置把该存储类型交给解释器时,文件存储才会转化为远程代码执行;把目录配置为仅提供惰性下载,可以切断最后一步,却并未修复该任务。公开证据没有证明每个受影响安装都配置了可执行处理器,所以准确结论应写成“无需身份验证的任意文件上传,在存储可执行时可导致 RCE”,不能写成“每个 2.4.0 站点都必然执行了该文件”。

2 iCagenda 让有效令牌进入了未获授权的操作

iCagenda 的失效点出现在附件写入器之前。对官方 4.0.7 与 4.0.8 组件包的比较表明,脆弱控制器具备 CSRF 检查,却没有在操作执行时落实组件配置的提交受众。公开页面可以正当地为匿名访客建立会话并发放令牌;观测到的请求携带的正是这种会话令牌,而非伪造或击败 Joomla 的令牌算法。问题在于令牌既不特定于某个表单或操作,也不认证身份或授予权限,接受它之后,控制器仍需单独回答调用者是否获准提交。

证据锚定于供应商制品,而非重新构造的示例。官方 4.0.7 外层软件包的 SHA-256 为 F12E38D16F7C6CDF9BFD4BDE9AB2351F8123C78E09B1DB0846371EB42FB30537,其内嵌 com_icagenda.zip0143757AE58104A75634672D2C2BDFDD08753EEB9435AA058CDA49123C361D4C。4.0.8 外层软件包与组件的哈希依次为 BE3788DAAEF85B903B540685EEBEEC2BF3257ED2CC02159F11FBDDF5E707CE742CB539DD2B118042B713D438932C2473BBDC72096ED8489474778F34BF8C17E0。在内嵌组件中,4.0.7 的 Site\Controller\SubmitController::submit() 先调用 $this->checkToken(),再取得菜单项标识符、校验表单并调用模型。它既没有把已授权查看级别与 submitAccess 比较,也没有证明所选菜单项指向 iCagenda 的提交视图。因此,菜单可见性并不构成操作执行时的强制控制。

2.1 会话令牌从未回答权限问题

授权也不能交给菜单代行。Joomla 菜单描述导航并可应用查看访问控制,但验证和持久化数据的边界仍是组件操作本身。在 4.0.7 中,调用者可控的菜单项标识符进入操作时,并没有在同一操作内证明它解析到预期的 com_icagenda 提交链接。运维人员隐藏菜单项或把它分配给注册用户,只会改变可见界面;处理例程仍需拒绝策略范围之外的身份。这是一条通用的控制器原则,在此处却有具体后果:请求一旦进入模型,iCagenda 就可能创建事件记录并处理随附文件,而应用仍未确认调用者是否获准提交。

JoomliC 把事件后果与可执行上传后果明确区分开来。在受影响的各 Joomla 代际范围内,访客可以创建一个在存储中已发布但未获批准的事件,因此它不会以已批准事件形式正常展示。在 Joomla 6.0.0 至 6.1.1 上,同一条可达流程还可能让附件穿过下一章所述的媒体策略缺口。这正是不能把分类历史压平的原因。最初的事件分析和早期 Joomla CNA 历史强调缺少访问控制,即 CWE-284;CNA 记录于 7 月 5 日改为当前的危险文件上传分类 CWE-434。前者指向让错误受众进入的操作层,当前记录则命名了造成代码执行的文件处理弱点。它们描述的是不同层面和记录沿革,不能当成两个可互换、同时具有权威性的标签来断言。

对防守方而言,这一区分决定了如何解释日志。建立会话的请求或有效令牌本身并不可疑;遭拒的访客提交同样不能证明利用已经发生。报告中的 iCagenda 序列只有在公开会话或令牌上下文之后紧接提交请求,随后又从组件的前端附件树取回一个新存文件时,才具有显著意义。观测到的用户代理 icagenda-batch/1.0 可用于在留存日志中扩展查询,但它只是可变的客户端文本,并非规范指标。检测应保存行为与时间关系,而不应让调查依赖该字符串。

2.2 4.0.8 把受众与菜单策略移入操作

4.0.8 把三道关口放在任何模型副作用之前。checkToken() 继续比较当前会话令牌;随后,控制器取得当前身份的获准查看级别和组件的 submitAccess 配置,只有公开级别被明确允许时才接纳匿名身份,已认证身份的级别也必须与配置集合相交;最后,传入菜单项必须存在,且链接必须等于 index.php?option=com_icagenda&view=submit。三者分别回答请求是否来自当前会话、身份是否属于提交受众,以及呈现层标识符是否确实指向预期操作,缺少任何一道都会重新打开不同的控制缺口。

运维验证应确认这些分支,而无需尝试执行代码。在使用修复包的自有预发布副本中,配置非公开提交受众,确认匿名请求在任何事件或附件状态提交之前即被拒绝。还应确认,允许查看级别之外的已认证身份同样被拒绝,而明确获准的身份能够提交一个良性业务文件。然后分别使用缺失或无效令牌,以及无法解析到 iCagenda 提交视图的菜单项标识符,重复负向用例。验收证据应是决策顺序——授权和菜单绑定先于模型副作用——而不能只是前端渲染的一条错误消息。

暖纸手绘的 iCagenda 控制器流程:4.0.7 只有会话令牌印章便进入模型,4.0.8 则在模型前加入受众与提交视图菜单关口。
图1:iCagenda 4.0.7 的会话令牌检查会直接走向提交处理;4.0.8 保留这道 CSRF 关口,并在进入模型前加入提交受众和提交视图菜单授权。会话令牌既不特定于操作,也不能证明身份或权限。

3 iCagenda 把调用者提供的类型带入公开附件存储

4.0.7 控制器一旦接纳请求,4.x 模型就补齐了报告中攻击链的另一半。SubmitModel::submit()jform 附件传给 frontendFileUpload() 时,没有先询问 Joomla 媒体策略是否允许上传。写入端从客户端文件名中提取扩展名、规范化基本名、在处理重名冲突时保留扩展名,并通过 Joomla Framework 的纯移动写入端 Joomla\Filesystem\File::upload() 把文件移到 icagenda/frontend/attachments/ 之下。采用默认图像根目录时,实际位置就是 images/icagenda/frontend/attachments/

API 边界至关重要。File::getExt() 只提取扩展名,并不批准它;文件名规范化也不判断类型是否安全;4.0.7 使用的 Framework File::upload() 只移动临时文件,不会应用 Joomla CMS 的安全文件策略。4.x 路径缺少的媒体策略决策正是 MediaHelper::canUpload()。旧版 3.9.14 路径则不同:它的 Joomla CMS/JFile 上传封装会应用默认安全文件关口。因此,仅靠对 4.0.7 Framework 写入端的静态审查,不能证明每一种 Joomla 3 组合都会把可执行文件写入目标。

3.1 4.0.7 在经过写入端时仍保留扩展名

无需提供利用请求体,也可以准确描述 4.0.7 的脆弱状态转移。请求传入一个文件对象,其 name 包含基本名和扩展名。写入端拆分两部分,对基本名执行清理或 slug 化,再把原始扩展名拼回存储文件名。发生重名冲突时,系统只改变基本名,仍保留该扩展名。最后,Joomla\Filesystem\File::upload($src, $dest, false) 移动临时文件,事件记录则保存其相对路径。清理基本名降低了标点和类似路径穿越的文件名风险,却不会把禁止的可执行类型转化为获准附件。

目标位置构成最后一个环境条件:文档根目录下的文件只有在 Web 服务器把其存储类型路由给解释器时才成为代码。JoomliC 和第一手报告都把已复现的“上传至 Web shell”结果限定在 Joomla 6.0.0–6.1.1,并称较早代际在测试配置中阻止了不安全上传;JoomliC 还称 Joomla 6.1.2 恢复了框架级拦截。因此,CNA/NVD 所列 CWE-434、CVSS v4 10.0 和 CISA 活跃利用状态,应与这条环境边界一起阅读:iCagenda 的媒体检查缺口让调用者可控类型进入公开附件目标,受影响的 Joomla 6 区间允许报告中的 PHP 执行转移,但不能据此断言每种服务器映射或每个受影响 Joomla 代际都能执行。禁止脚本执行可以切断最后一步,却不会阻止未经授权的事件;较旧 Joomla 的安全文件关口可以拒绝测试类型,却不会落实 iCagenda 的受众策略。

3.2 两道媒体关口修复了不同的事务边界

4.0.8 两次加入 MediaHelper::canUpload($file)。第一次调用位于 SubmitModel::submit() 中,在模型调用 frontendFileUpload() 之前。它保护的是事件事务:不可接受的附件应在事件流程把文件视为已成功处理或提交相关状态之前被拒绝。第二次调用位于 frontendFileUpload() 入口。它保护的是写入例程本身,确保现在或未来的其他调用者不能仅凭另一条模型路径抵达可复用写入端,进而绕过策略。只有把事务完整性和写入端加固误认为同一个要求时,这两项检查才显得重复;实际上二者并不相同。

该修复不会随机化 iCagenda 附件名,也不能把 Balbooa 的修复方式移植到这条代码路径。iCagenda 写入端仍会构造可读名称并保留获准的扩展名;新增的安全保证是 Joomla 媒体策略在写入前批准文件,而且事件调用端和写入端边界都会执行这一决策。后续版本又加入纵深防御:4.0.9 增加媒体目录禁止脚本执行配置文件,并强化安全检查器与上传处理;4.0.11 调整 SubmitModel 对获准非图像附件保留扩展名的行为。正因存在这些后续改动,部署目标应是当前受支持版本,而不能把 4.0.8 当作永久终点。

安全验证应让两道边界都可观察。在自有预发布环境中,获授权用户应能提交每一种必要的业务文件类型,并以预期内容和响应处置方式取回附件。一个代表禁止扩展名的惰性测试文件,以及另一个扩展名与内容不匹配的良性测试文件,都应在临时文件移动之前、也在任何事件或附件记录提交之前遭拒。测试可以对应用决策进行插桩,或比较数据库和文件系统状态,无需使用可执行标记。服务器行为应通过配置级或其他非执行式观测进行测试,以证明解析后的附件目录不能调用 PHP 或其他服务端处理器。

暖纸手绘的 iCagenda 附件写入流程:客户端扩展名经过文件名清理后仍到达公开目录,4.0.8 在事务外层和写入端内层分别加入媒体验证。
图2:iCagenda 4.0.7 的 4.x 写入端保留调用者扩展名,并通过 Framework 文件移动器进入公开存储。4.0.8 在事件事务之前和可复用写入端内各拒绝一次不合规媒体,独立的禁止脚本执行规则则让获准存储保持惰性。

4 Balbooa 在匿名交接中一直信任客户端文件名

Balbooa Forms 通过另一张控制图抵达了同一种可能终点——由服务器执行公开存储的附件。第一手事件报告把暴露的前端任务确定为 form.uploadAttachmentFile,模型例程确定为 FormModel::uploadAttachmentFile(),存储树确定为 images/baforms/uploads/form-<id>/。在受审查的 2.4.0 软件包中,该前端任务既不要求已认证账户,也不要求 Session::checkToken()。控制器把上传文件传入模型;实现从调用者提供的文件名中提取扩展名,对文件名材料应用 Joomla File::makeSafe(),再拼回扩展名,并把结果写入由 Web 提供的逐表单目录之下。

Balbooa 的公开更新日志能够确认版本和修复控制,却没有提供一份可像 iCagenda 那样直接比较的公开源码历史。因而,form.uploadAttachmentFile、控制器到模型的交接及 2.4.0/2.4.1 软件包差异,来自参考资料所列的第一手软件包分析;厂商日志则独立印证了修复版本和四项控制。现有证据能够确认脆弱路径与修复形态,不能把缺少的公开源码历史补写成独立仓库复核。

4.1 清理文件名并不会建立类型策略

File::makeSafe() 处理的是文件名问题。它会移除 Joomla 不希望出现在存储名称中的字符,从而降低歧义和不安全路径材料风险。它不会检查表单字段是否允许该扩展名、声明的 MIME 是否与内容一致、文件是否应改用服务端生成的名称存储,也不会检查目标位置能否执行结果。在报告所述的 2.4.0 路径中,模型从客户端可控的名称数据提取扩展名,并在清理后继续保留它。即使基本名中的每个字符都是“安全”的,可执行后缀仍然可以保持可执行。把清理与授权混为一谈,正是 Balbooa 机制的核心错误。

匿名交接放大了这一错误。由于前端上传任务既无身份验证要求,也不检查 CSRF 令牌,任何能够访问该路由的互联网客户端都可以向模型提交文件。缺少服务端逐字段扩展名策略,意味着 Upload File 字段预期的业务限制没有约束实际写入。公开目标位置随后使结果可以被取回;如果 Web 服务器处理器会在该目录中执行保留的类型,取回动作就会从任意上传跨越到远程代码执行。CNA 记录把受影响范围定为 1.0 至 2.4.0,将问题评为严重级别;CISA 7 月 10 日的活跃利用评估则要求开展追溯审查,而非更新后即告结案。

幸存的事件轨迹始于应用之外:7 月 8 日的托管服务商滥用通知和在线站点原始访问日志,随后推动了私下披露与次日的 2.4.1 发布。服务商通知应按原样保留,并记录每个数据源的时区;当本地日志已轮转时,服务商和出口侧证据可能与源站请求同等重要。调查应把上传任务 POST、随后对逐表单上传树的访问、文件创建时间、进程与 PHP 遥测、出站连接、Web 服务器错误和托管控制面板活动接成时间线。路由字符串、用户代理、地址或单次状态码都不足以归因,尤其在共享托管和反向代理会改写上下文的环境中;现有材料也没有确认操作者、活动规模或与 iCagenda 自动化的联系,两项 CVE 同日进入 KEV 只连接响应优先级。

4.2 2.4.1 把修复拆分为四项独立控制

Balbooa 官方 2.4.1 更新日志列出四项彼此独立的控制。服务端扩展名白名单校验判断配置的 Upload File 字段是否允许该类型;可选的 MIME Types 设置增加一层内容策略,但升级后已有字段的设置可能仍为空,需要逐项检查;随机服务端名称消除了客户端对存储文件名的控制;CSRF 防护要求当前会话令牌,却不构成身份验证,修复后的公共表单仍可按设计向匿名访客开放。有效令牌不会让禁止类型变得安全,随机命名也不能代替类型策略。

7 月 16 日发布的 2.4.2 是当前复核的 Balbooa 目标版本。其更新日志增加了签名和 PDF 输出的随机命名,并修正缓存行为。这些改动不能模糊更早的修复边界:前端附件上传在 2.4.1 得到修复,2.4.2 的签名和 PDF 命名改动涉及其他输出。运维人员应部署当前受支持的软件包,然后验证具体的前端控制,而不能只从更高版本号推断控制存在。应记录可信的软件包来源、已安装扩展元数据、实际加载的代码、已配置字段白名单和 MIME 策略,以及实际存储位置;如果部分更新或人工紧急修改使软件包身份变得不确定,应从可信软件包重新安装。

即使升级到 2.4.1 或 2.4.2,上传树仍需要独立的禁止脚本执行约束。应在实际生效的 Apache、Nginx、IIS、PHP-FPM 或托管平台层配置 images/baforms/uploads/ 及其每个逐表单子目录,使其只能作为惰性内容提供或直接拒绝,绝不能路由到服务端解释器。通过预发布环境中的非执行式观测验证该规则,并把配置与响应保存为证据。这种遏制不能代替扩展修复,但可以限制未来校验回归的后果。如果主机在 2.4.0 或更早版本可达期间曾暴露,应在改变软件包前保全证据,搜索整个 Joomla 目录树和同级虚拟主机,从可信软件包或已知良好基础设施重建已失陷系统,并轮换 Joomla、数据库、托管平台、SSH、SMTP 和 API 凭据,而不能因为上传目录看起来为空就宣布结案。

暖纸手绘的 Balbooa Forms 上传链:2.4.0 的匿名文件名与扩展名进入公开逐表单目录,2.4.1 在前方加入会话令牌、字段扩展名、可选 MIME 和随机存储名控制。
图3:Balbooa Forms 2.4.0 的匿名公共任务让调用者扩展名穿过文件名清理并进入公开存储;2.4.1 保留有意的匿名表单用途,同时加入字段扩展名策略、可选且需配置的 MIME 策略、随机存储名和会话令牌 CSRF 检查。惰性存储仍是独立边界。

5 相同的 RCE 终点对应两张不同的前提图

两项调查最终都抵达同一个危险状态:来自互联网的未认证请求可以把攻击者选择的内容留在可通过 Web 访问的目录中,而兼容的服务器处理程序可以把它解释为代码。这一共同终点解释了 CISA 在 7 月 10 日将两项漏洞都加入已知被利用漏洞目录后,为何它们应进入同一个紧急处置队列;但这不意味着两条路径可以互换。CVE-2026-48939 穿过 iCagenda 的公共事件提交动作和附件写入器;CVE-2026-56291 穿过 Balbooa Forms 的前端上传任务和附件模型。产品、版本、Joomla 代际、配置、存储位置和处理程序状态仍共同决定暴露面。

5.1 判定暴露面时必须保留 Joomla 代际、扩展版本和处理程序状态

判定层面 iCagenda / CVE-2026-48939 Balbooa Forms / CVE-2026-56291
受影响扩展版本边界 NVD 范围为 ≥3.2.1 且 <3.9.15,以及 ≥4.0.0 且 <4.0.8;JoomliC 按 Joomla 代际映射子范围。Joomla 4–6 首次在 4.0.8 中修复,Joomla 3 首次在 3.9.15 中修复。Joomla 2.5 没有目前仍受支持的修复版本,必须迁移或移除 iCagenda。 CNA/NVD 范围为 1.0 至 2.4.0;首次在 2.4.1 中修复。
额外执行条件 JoomliC 把可执行上传条件限定为 Joomla 6.0.0–6.1.1;能否执行仍取决于服务器如何提供所存类型。 记录没有公布相当的 Joomla 代际限制;代码执行仍要求 Web 服务器执行所存类型。
不可信状态转换 公共提交动作可以到达保留调用方扩展名的附件汇点,而没有经过后来在 4.0.8 中加入的媒体策略检查。 公共前端上传任务可以到达一个模型写入器:它清理名称,却未在写入可通过 Web 访问的目录树之前强制执行已配置的允许类型。
修复形态 控制器执行受众和提交视图菜单授权;调用方边界和汇点边界都执行媒体验证。 字段派生的扩展名策略、配置后启用的可选 MIME 策略、随机化存储名称,以及既不是认证也不是授权的会话令牌检查。
本次审阅的当前版本 4.0.11,7 月 18 日发布;它晚于首批修复,还包含后续上传加固和兼容性修正。 2.4.2,7 月 16 日发布;它对签名/PDF 输出所做的额外随机化并非最初的前端上传修复。

5.2 两类证据回答不同的问题

iCagenda 的官方 4.0.7/4.0.8 软件包能够证明控制器和模型的状态变化,JoomliC 公告补充 Joomla 代际矩阵与利用开始时间,站点请求序列则证明路径曾在被观察环境中实际走过;代码可达性与单站事件证据相互支撑,却不是同一种证明。Balbooa 的证据形态不同:厂商日志独立确认 2.4.1 的发布日期和四项控制,具体任务、函数、文件名处理、目标位置及前后软件包差异来自参考资料中的第一手软件包分析,托管商通知和原始日志只证明被调查站点的活动。它们都不能推出活动规模、共同操作者或持久基础设施集群。

iCagenda 的标签历史也对应两层真实缺陷:早期 CWE-284 指向接纳错误受众的操作,7 月 5 日更新后的现行 CWE-434 指向写入前未拒绝危险类型的附件管道;Balbooa 的 CWE-434 则与缺少服务端类型策略一致。无论标签和严重性如何,文件都只有在服务器把其存储类型映射到可执行处理程序时才转化为代码;惰性提供会阻断该转移,却不会抹去未经授权的上传,升级也不会自动清除既有改动。因而,版本、Joomla 代际、上传策略、目标位置和处理程序必须分别记录,只有执行或上传后活动证据才能把资产判为已失陷。

暖纸手绘的双路径暴露矩阵:iCagenda 轨道依次经过扩展版本、Joomla 6 核心区间和处理器状态,Balbooa 轨道经过版本、字段类型策略和处理器状态,最终才可能汇入执行舱。
图4:iCagenda 的可执行路径要求受影响扩展、Joomla 6.0.0–6.1.1、Web 可达存储和兼容处理器;Balbooa 则沿自身的受影响版本与字段/类型策略链前进,执行同样取决于处理器。两条路径只在最终 RCE 条件处汇合。

6 现场证据把更新任务转化为事件响应

发现受影响版本和公共上传面后,工作就不再只是更新软件包。两项记录进入 KEV,正是因为存在已知利用。JoomliC 称,针对 iCagenda 的自动化利用始于 6 月 15 日 08:00 UTC;Balbooa 调查则始于 7 月 8 日收到的托管商滥用通知和原始访问日志。这两条时钟线都要求在替换软件包和恢复之前先行遏制并保全证据。

6.1 请求序列必须结合文件系统、进程和托管商上下文

iCagenda 报告描述了一组序列:获取会话和令牌的上下文、公共事件提交请求,以及后来对新存附件的请求。报告还记录了用户代理 icagenda-batch/1.0。该字符串是有用的关联线索,因为它可以帮助从留存日志中找回相邻请求,但它完全由请求方控制,不能当作规范化指标。命中可能来自伪造,换用另一个字符串也不会让相同行为变得良性。可辩护的分析单元应是整个序列:获取表单状态、携带上传的提交、在 iCagenda 前端附件目录树下创建文件、取回所得对象,以及随后出现的任何进程或网络活动。

Balbooa 报告从另一种幸存工件出发:托管商发现滥用行为,并返回通知和原始访问证据。对本地调查而言,有意义的链条是把前端上传请求与随后访问 images/baforms/uploads/form-<id>/ 下对象的请求连接起来,再追问 Web 工作进程是否派生子进程、建立出站连接、修改应用或服务器配置,或写入其他位置。对该目录树下异常文件的一次请求只是线索,不能自行证明已执行。文件可能是惰性的,请求可能失败,处理程序可能不存在,时间戳也可能来自后续管理操作。反过来,如果日志已轮转、上游代理才保留请求,或攻击者通过另一条路径调用已经放置的文件,那么缺少一条访问日志也不能排除主机失陷。

时间归一化是案件工作的一部分。对于托管商通知、代理和源站日志、PHP 或应用日志、操作系统事件、数据库变更和文件元数据,应保留原始时区和精度,记录转换过程,同时保留原值。还要考虑缓冲、时钟偏差、部署重置和归档时间戳。移动可疑文件之前先计算哈希,采集所有者和权限模式,同时记录逻辑 Joomla 路径与解析后的文件系统路径。随后,关联分析才能把提交、文件创建和工作进程出站行为连成一条链,而不假装其中任意一行就足以证明全链。

应沿三个轴扩展调查范围:在相邻时间窗内搜索行为,避免把范围收窄到一个用户代理或文件名;检查其他可写 Web 目录树、扩展或模板代码、计划执行项、管理状态、数据库内容和服务器配置;还要审查共享工作进程、凭据、文档根目录父路径或部署身份的同级站点与托管账户。两份报告都没有确立共同攻击者、受害者数量或共享基础设施,因此关联关系必须来自环境自身的证据。

6.2 隔离和保全必须先于软件包变更

如果证据表明发生过上传、取回、执行或无法解释的利用后活动,应把受影响工作负载与公共入站流量和不必要的出站流量隔离,同时保留受控的响应通道。对于负载均衡器后方的一次性实例,可以将其移出轮转,并为相关磁盘和运行时元数据创建快照;在共享托管环境中,则可能需要与服务商协作,以免产生附带影响并取得租户无法访问的日志。遏制记录必须准确写明改动内容——路由、防火墙策略、服务状态、凭据或账户停用——以及改动时间,因为响应动作本身会改变后续观测。

在使用 Joomla 更新器、删除可疑附件、重装扩展、清理缓存或重启 PHP 之前,先保全这些动作可能覆盖的证据。最低限度应收集可获得的反向代理和源站日志、应用与 PHP 日志、平台能够暴露的当前进程与网络状态、相关文档根目录和配置元数据、扩展清单、已安装版本记录、计划执行点、管理员账户状态,以及可疑或已变更文件的密码学哈希。按收到时的原样保留托管商原始通知和原始日志。对缺口应如实记录:共享主机可能不暴露进程内存,CDN 可能只保留抽样请求,备份也可能在疑似事件发生后才运行。

只有越过这条保全边界后,才能开始变更软件包。相比手工删除可见上传,可信重装或重建更可取,因为公开路径允许执行代码,也就允许改动最初存储目录之外的位置。通过厂商经过认证的分发路径取得软件包,保留其来源 URL、发布标识、下载时间和摘要,并将已安装状态与已知良好版本比较,或从已知良好基础设施重建。Joomla 扩展更新器可能交付有效的厂商版本,但成功提示只证明更新事务报告成功;它不能证明所有旧文件已被移除、被覆盖的更新源可信、PHP 运行时已加载新代码,或此前从未发生失陷。

恢复阶段要轮换受影响运行时能够触达的权限载体:管理员凭据、会话、数据库与托管凭据、部署密钥以及可复用 API 令牌。先建立可信管理通道并重建或清理环境,再引入替代凭据。如果站点与同级资产共享凭据或托管身份,即使后者没有匹配的上传路径,也应将其纳入凭据轮换范围。

暖纸手绘的事件证据板:托管商通知、请求序列、文件哈希、进程轨迹与出站连接先汇入保全区,封存后才进入软件包替换步骤。
图5:服务商通知、请求时间、文件哈希、进程行为、网络记录、身份变更与软件包状态必须针对两起事件分别关联。单一文件名、地址或用户代理既不能证明执行,也不能证明共同归因。

7 软件包与存储控制都给出证据,修复才算完成

磁盘上出现一个已修复文件,只代表一个事实层面。操作者还必须确认选中了预期的厂商版本,Joomla 报告并执行该版本,新决策点确实运行,存储位置保持不可执行,而且良性测试证明获准用途可以成功、禁止类型会在持久提交之前被拒绝。任何单一层面都不能代表整个修复。

7.1 验证可信软件包、安装状态、运行时状态和当前版本

先明确发布版本意图。对于 Joomla 4–6 上仍受支持的 iCagenda 安装,4.0.8 是首个安全修复版本,当前 4.x 版本线已到 7 月 18 日发布的 4.0.11;遗留 Joomla 3 产品线由 3.9.15 承载修复。Balbooa Forms 的首修是 2.4.1,当前版本线已到 7 月 16 日发布的 2.4.2。记录分支选择及 Joomla、PHP、扩展依赖和厂商支持状态;若生产环境暂时无法接受当前版本,应把具体首修回退版本和补偿控制登记为有明确时限的例外,不能悄然把旧版本当作当前版本。

随后验证分发来源。保留权威厂商页面或更新源 URL、软件包版本、获取时间和摘要,并验证厂商提供的任何签名或认证通道。内部镜像中的工件应能关联到经过审阅的厂商对象,不能只信任 4.0.11.zip 这样的文件名。来自同一软件包供应系统的摘要可以发现损坏,却不能独立确立厂商来源。恢复时不要使用第三方重新打包的软件包。

将安装事实与软件包事实比较:检查 Joomla 清单记录、已部署扩展文件,以及已不再由软件包拥有的残留文件。确认 iCagenda 的受众/菜单强制执行和两道媒体验证边界,或 Balbooa 的字段派生扩展名策略、配置时启用的可选 MIME 处理、随机化命名和会话令牌检查。这是在不重建利用过程的情况下检查控制是否存在。对于操作码缓存、不可变镜像、多个 PHP 池或集群,应以受控方式替换实例,并证明每个提供服务的节点都加载了已修复工件。

7.2 良性测试检查拒绝、提交顺序和惰性提供

验证应在自有预发布环境中进行,或走经过明确授权的生产维护路径,并使用不可执行的测试文件。先做正向对照:提交一个字段策略允许、符合业务用途的小文件,验证预期访问方式和工作流,并记录返回的应用状态、服务端存储名称、目标位置和提供内容时的响应头。这样可以确认安全更新没有只是禁用功能。测试必须遵循站点真实的受众配置:只有在有意配置公共受众时,iCagenda 公共提交测试才应公开;认证测试则应使用具备预期授权视图级别的身份和实际的提交视图菜单。

负向对照使用惰性文件:其扩展名或声明的媒体类型应位于配置策略之外,内容本身不能执行。验证应用拒绝该文件,上传目录树或临时发布位置中没有出现持久对象,数据库没有提交误导性的附件引用,而且拒绝事件以可操作的级别记入日志,同时不向请求者暴露敏感路径。把良性文本测试文件改名,可以安全地测试策略不一致;可执行标记、命令载荷或真实 Web shell 既无必要,也会制造新的事件。不得探测第三方站点,也不要给出会把验证变成可复用利用配方的 HTTP 请求体。

提交顺序本身就是测试结果的一部分。在 iCagenda 4.0.8 中,外层 MediaHelper::canUpload() 检查在事件提交事务调用写入器之前提供保护,内层检查则保护可复用的 frontendFileUpload() 边界。因此,负向测试既要确认文件不存在,也要确认事件记录保持一致,不能接受“响应称已拒绝、对象却已部分提交”的结果。在 Balbooa 2.4.1 中,应分别观察字段派生的扩展名规则、仅在配置后启用的可选 MIME 限制、不受客户端控制的存储名称,以及会话令牌检查。令牌结果不能证明身份或权限;通过某一层——例如随机命名——也不能证明禁止类型已被拒绝。

测试 Web 服务器契约时不必放置代码。检查解析后上传目录所适用的 Apache、nginx、IIS、PHP-FPM、容器或托管配置。使用配置级测试或不会执行的无害预发布观测,确认内容以惰性方式提供或被拒绝。还要考虑别名、目录级覆盖、嵌套配置、大小写行为、替代扩展名和虚拟主机。结论只能是:被测试的配置在测试时刻让该目标位置保持惰性。

验证层面 所需证据 能够支持的结论
来源 厂商来源、发布标识、获取时间、摘要或签名、镜像关联关系。 选定工件是预期的厂商版本。
安装与运行时状态 清单/数据库版本、软件包文件比较、节点清单、缓存或实例替换证据。 每个提供服务的节点都运行预期的已修复代码。
应用策略 经授权的正向对照和针对禁止类型的惰性负向对照,包括文件系统与数据库观测。 允许的业务可以成功,禁止输入在持久提交之前被拒绝。
存储策略 解析后的路径、有效处理程序配置、不执行的预发布观测。 被测试上传目标无法把所存内容转换为代码执行。
事件状态 已保全日志/文件、搜索范围、重建或清理记录、凭据轮换和监测结果。 组织处置了此前可能发生的利用,而不只是未来请求。

业务文件正向对照失败不代表安全成功;拒绝响应伴随对象写入也同样失败。应把响应、应用与日志决策、数据库和文件系统影响、存储名称行为以及内容提供情况一并采集。这样得到的是可复现的验收记录,同时不需要危险内容。

8 舰队闭环是一份证据记录,不是一条更新消息

7 月 13 日的 KEV 截止日期压缩了补救时间,但紧迫性不会改变闭环标准。排队等待的更新或一次代表性扫描都不能关闭整个舰队。闭环必须把清单、暴露面判定、证据保全与恢复、工件来源、逐节点运行时验证、安全的应用与存储测试、凭据工作,以及每项例外的责任人连接起来。

8.1 建清单、做恢复、轮换凭据,并把搜索扩展到上传根目录之外

先建立包含以下字段的清单:站点、公共主机名、Joomla 版本、PHP/运行时与 Web 服务器处理程序、已安装的 iCagenda 或 Balbooa 版本、扩展来源、公共表单暴露情况、已配置上传字段和允许类型、解析后的存储路径、执行策略、服务节点、托管账户和责任人。发现工作必须检查已部署扩展记录和文件,不能只依赖可能遗漏手工安装的配置管理目录。应把“未安装”“已安装但路由禁用”“受影响且可达”“受影响但处理程序惰性”“已修复并验证”和“疑似失陷”记录为不同状态。处理程序惰性会降低 RCE 后果,却不会抹去未经授权的上传缺陷,也不会免除更新义务。

任何存在可疑上传、取回或执行证据的站点,都应进入事件处置分支,不能按例行更新处理。先保全并隔离,再从可信软件包或已知良好基础设施重建,比较内容与配置,只在记录持久化机制之后将其移除,并把搜索扩展到具名扩展目录之外。在环境恢复可信后,轮换 Web 运行时可触达的秘密和会话。审查同级站点和共享控制面账户。从已知良好状态恢复服务,再监测重建出的行为序列——获取表单状态、提交、访问存储、进程行为和出站流量——不依赖一个可任意改变的字符串或文件名。

每项“不受影响”判定都需要理由和证据日期。例如,权威清单证明扩展不存在;已安装版本高于受影响范围,同时具备软件包来源和运行时确认;或永久移除路由并升级到不再包含易受攻击代码的版本。“没有告警”“已启用 WAF”“使用 Joomla 5”或“上传文件夹看起来是空的”都不足以同时排除两项 CVE。前两者忽略可见性和机制差异,后两者则忽略仍然存在的访问控制缺陷、日志丢失、替代存储位置和利用后清理。

8.2 持续维持禁止脚本执行契约和回滚证明

耐久的架构规则说来简单,却很容易丢失:用户可控存储不得执行。应在 Web 服务器或托管层对每个解析后的上传目标强制执行这条规则,包括扩展媒体目录、临时处理位置、生成文档和租户特定子目录。在应用边界维持允许类型策略以及配置后启用的可选 MIME 策略;产品支持时生成服务端名称;并要求恰当的动作授权和会话令牌检查。这些控制互为补充。禁止脚本执行规则遏制终端 RCE 转换,却不会授权一次上传;会话令牌只表明请求提供了与当前会话上下文绑定的值,不表明请求者已认证或获授权;文件名随机化不会让危险类型变得安全;而允许列表也无法保护处理程序策略后来发生改变的目录。

把这项存储策略当作可部署契约。对 Apache、nginx、IIS、容器或平台配置进行版本控制;当新扩展创建目录、托管迁移改变处理程序继承关系,或平台镜像被替换时测试它。监测新增的可执行处理程序映射,以及用户内容目录树中出现业务策略之外类型的文件。iCagenda 后续版本为媒体文件夹加入禁止脚本执行文件属于纵深防御,但集中强制执行的服务器策略不应依赖每个扩展都附带正确的目录级文件,也不应依赖服务器一定接受那种文件类型。

回滚保护关闭最后一个运维缺口。配置管理和部署工具应拒绝低于已记录安全底线的工件,在内部镜像提供旧软件包时告警,并在回滚或灾难恢复后验证安装与运行时版本。6 月或 7 月之前制作的备份和黄金镜像可能完整恢复易受攻击的扩展;因此,即使恢复成功,也必须在接收流量之前重新应用安全版本和存储策略。对于停留在 iCagenda 3.9.15 的遗留 Joomla 3 站点,或无法采用当前受支持版本的任何环境,例外登记册都应写明责任人、补偿控制、到期时间和迁移计划。

最终案件记录应把每个公共主机名与以下证据关联起来:适用性判定、变更前保全的证据、可信软件包及其摘要、每个节点的安装和运行时确认、良性正向与负向测试结果、有效的禁止脚本执行观测、事件搜索与恢复结果、凭据轮换范围和监测责任人。CISA 7 月 10 日的行动为两个已被积极利用的上传漏洞设定了同一个响应截止日期,可靠闭环却必须分别证明两张控制图:共同终点决定紧迫性,差异决定修复什么、搜索什么,以及哪些证据足以说明工作已经完成。

暖纸手绘的舰队闭环台账:iCagenda 与 Balbooa 两条已修复轨道依次通过可信软件包、运行时、惰性存储、恢复和回滚关口,最终进入封存记录。
图6:闭环不是更新成功消息,而是每个公共主机名都具备适用性、证据保全、可信工件、逐节点运行时、良性测试、不可执行存储、恢复和回滚证明。

研究记录

9证据、对象与来源

下面保留本文实际使用的标识、时间和原始材料,便于继续调查。

9.1研究对象

报告涉及的产品、行为者、技术、受影响对象和控制点。

CVECVE-2026-48939

iCagenda 公共事件附件上传漏洞;CISA 记录活跃利用

CVECVE-2026-56291

Balbooa Forms 前端附件上传漏洞;CISA 记录活跃利用

产品iCagenda 3.2.1-3.9.14; 4.0.0-4.0.7

受影响范围;3.9.15 和 4.0.8 首次修复,当前复核版本为 4.0.11

产品Balbooa Forms 1.0-2.4.0

受影响范围;2.4.1 首次修复,当前复核版本为 2.4.2

Joomla 版本Joomla 6.0.0-6.1.1

JoomliC 和第一手报告限定的 iCagenda 可执行附件结果区间

用户代理icagenda-batch/1.0

iCagenda 观测利用序列中的可变关联线索,不是规范指标

目录images/icagenda/frontend/attachments/

iCagenda 默认前端附件目录

目录images/baforms/uploads/

Balbooa Forms 默认上传根目录,包含逐表单子目录

9.2事件时间

  1. iCagenda 利用与首修

    JoomliC 称自动化利用于 6 月 15 日 08:00 UTC 开始;4.0.8 当日发布,遗留 Joomla 3 修复版本 3.9.15 于次日发布。

  2. CVE-2026-48939 发布

    Joomla CNA 公布 iCagenda 漏洞记录。

  3. CISA 记录概念验证证据

    CISA 对 CVE-2026-48939 的利用评估从无公开证据转为概念验证证据。

  4. Balbooa 事件披露并首修

    托管商滥用通知触发调查和 7 月 8 日的私下披露;2.4.1 与 CVE-2026-56291 于次日发布。

  5. 两个 CVE 进入 CISA KEV

    CISA 将两项漏洞标记为活跃利用,纳入 KEV,并为受约束联邦系统设定 7 月 13 日修复期限。

  6. 当前复核版本发布

    Balbooa Forms 2.4.2 于 7 月 16 日发布;iCagenda 4.0.11 于 7 月 18 日发布。

9.3来源与材料

  1. CISA 已知遭利用漏洞目录https://www.cisa.gov/known-exploited-vulnerabilities-catalog
  2. CISA KEV 中 CVE-2026-48939 的筛选记录https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-48939
  3. CISA KEV 中 CVE-2026-56291 的筛选记录https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-56291
  4. CVE.org 的 CVE-2026-48939 记录https://www.cve.org/CVERecord?id=CVE-2026-48939
  5. NVD 的 CVE-2026-48939 记录与变更历史https://nvd.nist.gov/vuln/detail/CVE-2026-48939
  6. CVE.org 的 CVE-2026-56291 记录https://www.cve.org/CVERecord?id=CVE-2026-56291
  7. NVD 的 CVE-2026-56291 记录与变更历史https://nvd.nist.gov/vuln/detail/CVE-2026-56291
  8. Joomla CNA 安全中心https://developer.joomla.org/security-centre.html
  9. JoomliC 的 iCagenda 安全更新公告https://www.joomlic.com/news/icagenda-security-update
  10. iCagenda 官方发布历史https://www.joomlic.com/download/icagenda
  11. 用于差异复核的 iCagenda 4.0.7 官方软件包https://www.joomlic.com/download/icagenda/icagenda-core-4-0-7
  12. iCagenda 4.0.8 官方安全版本与软件包https://www.joomlic.com/download/icagenda/icagenda-core-4-0-8
  13. iCagenda 4.0.9 官方加固说明https://www.joomlic.com/download/icagenda/icagenda-core-4-0-9
  14. iCagenda 4.0.10 官方发布说明https://www.joomlic.com/download/icagenda/icagenda-core-4-0-10
  15. iCagenda 4.0.11 官方发布说明https://www.joomlic.com/download/icagenda/icagenda-core-4-0-11
  16. iCagenda 3.9.15 遗留 Joomla 3 修复版本https://www.joomlic.com/download/icagenda/icagenda-core-3-9-15
  17. Phil Taylor 的 iCagenda 第一手事件与软件包报告https://mysites.guru/blog/icagenda-zero-day-file-upload-rce.pdf
  18. Balbooa Forms 官方更新日志https://www.balbooa.com/help/joomla-forms-documentation/basics/changelog
  19. Balbooa Forms 官方产品与发布渠道https://www.balbooa.com/joomla-forms
  20. Phil Taylor 的 Balbooa Forms 第一手事件与 2.4.1 软件包报告https://mysites.guru/blog/balbooa-forms-unauthenticated-file-upload-flaw/
  21. Joomla CMS MediaHelper APIhttps://api.joomla.org/cms-5/classes/Joomla-CMS-Helper-MediaHelper.html
  22. Joomla CMS File APIhttps://api.joomla.org/cms-5/classes/Joomla-CMS-Filesystem-File.html
  23. Joomla CSRF 防护手册https://manual.joomla.org/docs/security/csrf-protection/
  24. Joomla 访问控制手册https://manual.joomla.org/docs/general-concepts/acl/
  25. Joomla 6.1.2 官方下载页https://downloads.joomla.org/cms/joomla6/6-1-2
  26. OWASP 文件上传安全清单(仅用于辅助控制指导)https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html