跳到正文
>_ITDITDWeb 安全平台

安全指南

文件上传漏洞——从设计上防止 Web Shell 和 RCE

设计不当时,文件上传会变成严重漏洞:未经认证的攻击者上传一个服务器会执行的文件(Web Shell → RCE)——这正是 2026 年 Joomla 页面构建器被大规模利用的模式。用多层来防御:认证、服务器端校验、存放在 Web 根目录之外、禁止执行。

发布于 2026-07-08 更新于 2026-10-04 3 分钟阅读

适合所有让应用(或安装的扩展)接收文件的人——表单、管理后台、CMS 插件、API。这里没有攻击方法,只依据公开事实说明如何让你自己的上传功能变得安全。相关内容:用 CVE 修复手册彻底修复依赖包缺陷,以及组织安全基线。

未认证 → RCE
最坏的组合,会被无差别扫描
CWE-434
不受限制地上传危险类型的文件
只查扩展名
会被伪造和双扩展名绕过
多层防御
一层失效,下一层仍能拦住

实际会发生什么(通俗地说)

大多数应用都有接收文件的地方——「上传图片」「更换图标」「附加文档」。如果这里防护薄弱,攻击者就会发送一个伪装成图片的脚本文件,让它被保存到可以通过网页访问的文件夹里。然后只要在浏览器里打开这个文件的 URL——如果服务器把内容当作程序运行,攻击者就能远程执行命令。这就是 Web Shell(被留下的小型远程控制程序),由此会发生篡改页面、窃取数据、偷偷创建管理员账号、扩散到其他系统。

问题在于位置和执行,而不是接收文件

上传是正当的功能。危险在于把收到的东西以可执行的形式放在可执行的位置。反过来说,即使收到了可疑的文件,只要它落在永远不会执行的地方、内容经过了检查、端点要求认证,就不会造成损害。把思路从「拦住坏文件」转变为「绝不让存储位置执行任何东西」。

2026 年的真实案例:Joomla 扩展被大规模利用(同一模式)

2026 年,多个 Joomla 扩展接连披露了完全相同的「未认证上传 → RCE」模式,并被广泛利用。据报道,它们都是「没有认证检查+没有文件类型校验+存放在 Web 根目录下」这一典型组合。影响从页面构建器扩展到了一个活动日历扩展,CISA 设定了很短的修复期限。

三个真实案例(依据公开披露)
SP Page Builder(CVE-2026-48908)
JoomShaper 出品。影响 6.6.1 及以下版本,6.6.2 已修复。据报道,自定义图标上传没有进行认证或类型校验;CVSS 10.0,已被积极利用(已列入 CISA KEV)。警报解读:CVE-2026-48908。
iCagenda(CVE-2026-48939)
joomlic 出品的活动日历扩展。影响 3.2.1–3.9.14/4.0.0–4.0.7,3.9.15/4.0.8 已修复。据报道,公开活动报名表单的附件处理程序只在视图层做了访问控制;CVSS 10.0,已被积极利用(已列入 CISA KEV)。警报解读:CVE-2026-48939。
Page Builder CK(CVE-2026-56290)
joomlack.fr 出品。影响 3.5.10 及以下版本,3.6.0 已修复(旧版本线已向后移植到 3.1.1/3.4.10)。据报道同样是导致 RCE 的未认证上传;CVSS 10.0。
共同点
无需登录即可利用=会成为无差别扫描的目标。据报道,攻击集中在保持访问上:创建隐藏的管理员账号、植入 Web Shell,使攻击者在漏洞修复后仍能保持访问。
第一项修复
把受影响的扩展更新到已修复的版本(并清点、删除不用的扩展)。再加上下面的设计和配置,层层叠加。

教训:不用的扩展往往是最常被利用的弱点

这些案例有一个共同点:被用来入侵的是被遗忘、但仍处于安装状态的扩展。你添加的每一个 CMS 插件/扩展都会增加攻击面。仅仅清点并删除不用的东西,就能减少这类大规模利用能够攻击到的范围(如何清点你的资产)。

攻击的每个阶段,以及如何拦住它

这种模式在每一步都有可以拦住它的地方。请把它读成「在哪里能拦住」,而不是攻击方法。

1. 文件被发送到未认证的端点

任何人都能访问上传处理程序并提交脚本。

修复:认证+权限检查+CSRF 令牌

↓

2. 绕过类型校验并被保存

扩展名/Content-Type 被伪造,伪装成「图片」。

修复:服务器端白名单+内容(魔数)检查

↓

3. 落在 Web 根目录下,可通过 URL 访问

保存在可被猜到的路径,能直接在浏览器中打开。

修复:存放在 Web 根目录之外/随机化文件名

↓

4. 服务器把它当作脚本执行

存储目录允许执行=Web Shell → RCE。

修复:在上传区域禁止脚本执行

每一步都有可以拦住攻击的地方。纵深防御的意思是拥有多个这样的地方,而不是依赖一项控制。

不安全的配置与安全的配置

会出事的配置

  • 端点没有认证/权限检查(任何人都能访问)
  • 只凭扩展名或 Content-Type 做判断(可被伪造、双扩展名)
  • 收到的文件直接保存在 Web 根目录下
  • 存储位置仍然允许运行脚本
  • 文件名由用户提供/可被猜到

守得住的配置

  • 端点要求认证+权限+CSRF
  • 对类型使用白名单,并检查实际字节(魔数)
  • 存放在 Web 根目录之外(通过专用处理程序提供)
  • 上传区域禁止脚本执行
  • 重命名为随机文件名;绝不信任用户提供的路径

如何实现(按优先顺序)

1

在端点上要求认证、权限和 CSRF

处理上传的端点必须只允许拥有相应权限的已登录用户访问,并且必须验证 CSRF 令牌。据报道,2026 年的 Joomla 案例缺少的正是这项认证/权限检查。首先消除「任何人都能调用」的状态。

2

在服务器端使用白名单并检查内容

绝不信任客户端检查或浏览器发送的 Content-Type。在服务器端通过白名单只允许已知安全的类型,并检查文件的实际字节(魔数),确认它确实是那种类型。在判断之前,先把双扩展名、大小写和末尾的点规范化。

3

存放在 Web 根目录之外(或禁止执行)

把收到的文件保存在无法通过 URL 直接打开的位置,并通过专用控制器提供(设置适当的 Content-Disposition)。如果做不到,至少要在上传区域禁止脚本执行(Web 服务器配置)。只要这一点成立,即使是恶意文件也不会运行。它会在其他控制失效时保护你。

4

随机化文件名;加上大小和频率限制

重命名为由服务器选择的随机名称,绝不信任用户提供的路径或文件名(避免路径遍历)。加上大小限制和频率限制,如有可能再加上恶意软件扫描。

5

清点并更新你的扩展/CMS

清点你运行的扩展/插件,删除不用的,其余的保持更新。在 2026 年的大规模利用中,攻击者是通过未更新的扩展进来的。按照 CVE 修复手册,加上变更检测,以便发现再次引入的问题。

与本站构建方式的共通之处

这种模式的核心问题是**把不可信的输入以可执行的形式放在可执行的位置。**本站自己的原则正好相反:不信任收到的东西,隔离重要的东西,多层防御。除了上传之外,「在服务器端校验输入」和「隔离密钥和可执行区域」也是同样的防御。另请参阅不要把密钥放在公开目录里中的放置错误。

接下来阅读

FAQ

Q为什么文件上传的缺陷能让攻击者接管服务器?
A

如果攻击者能放置一个服务器会执行的文件(脚本),那么只要在浏览器里打开它,就能在服务器上运行代码(Web Shell → 远程代码执行,RCE)。之后就是:篡改页面、窃取数据、偷偷创建管理员账号、扩散到其他系统。关键不在于文件被接收了,而在于文件在落地的位置可以被执行。

Q检查文件扩展名就够了吗?
A

不够。扩展名和浏览器发送的 Content-Type 都很容易伪造。双扩展名(picture.php.jpg)、大小写技巧、末尾的点/空字节,以及不太为人知的可执行扩展名,都能绕过简单的检查。要组合使用白名单(只允许已知安全的类型)、检查文件实际字节(魔数),以及最重要的——不让存储位置执行任何东西。不要依赖黑名单。

Q小网站也会成为目标吗?
A

会。这类漏洞无需认证就能利用,所以攻击者会扫描整个互联网,不加区分地攻击存在漏洞的版本。在 2026 年 Joomla 页面构建器扩展被大规模利用的事件中,所有受影响的安装都是目标,与规模无关。「我们太小,不会被攻击」这种想法不成立。