个人随笔
目录
文件上传漏洞攻防笔记:从 JSP 木马入侵到架构级防护方案
2026-08-26 18:20:00

引言

从一次真实的入侵场景说起:攻击者利用上传漏洞,将 JSP 木马写入服务器template/JX1786405314.jsp,仅通过一次 HTTP 访问就触发执行,进而在系统中生成 SSH 密钥、留下持久化后门。很多开发者对文件上传的防护停留在 “校验后缀”“限制目录执行权限” 的层面,却屡屡被突破。
本文完整复盘 JSP 木马的执行原理、常见防护手段的局限性,以及从入口校验到架构层的完整防护方案,系统梳理文件上传漏洞的攻防逻辑。

一、JSP 木马是如何入侵并拿到服务器权限的?

1. 木马触发执行的底层原理

攻击者上传文件后,无需复杂操作,只需直接访问文件 URL 即可触发执行,核心依赖 Java Web 容器的 JSP 解析机制。

  • 触发前提:文件落在 Web 应用的公开可访问目录(如templateupload),而非受保护的WEB-INF目录。外部可通过http://域名/template/文件名.jsp直接定位到该文件。
  • Tomcat 解析执行流程
    1. 请求匹配:Tomcat 收到.jsp后缀请求后,通过默认配置的JspServlet将请求交由 JSP 引擎处理,而非当作静态资源返回。
    2. 翻译编译:首次访问时,Tomcat 将.jsp文件翻译为标准 Java Servlet 类(.java),再编译为.class字节码,缓存至work目录。
    3. 代码执行:JVM 加载字节码并执行service()方法,文件内的所有 Java 代码(包括恶意代码)全部生效。
    4. 后续复用:再次访问时直接复用已编译的字节码,执行速度更快。

简单来说:只要文件后缀为.jsp 且位于公开目录,Tomcat 就会将其当作程序运行,而非普通文件,这是 JSP 一句话木马能够生效的根本原因。

2. 为什么木马能生成 SSH 密钥?

JSP 木马(WebShell)的核心能力是执行系统命令,生成 SSH 密钥只是命令执行的一个典型应用场景。

  • 命令执行能力来源:木马通过 Java 原生 API(如Runtime.getRuntime().exec()ProcessBuilder)fork 出系统子进程,执行任意系统命令。攻击者只需通过 URL 传入命令参数,即可控制服务器执行指令。
  • 权限来源:命令继承 Web 容器进程的系统权限。若 Tomcat 以root用户启动,木马将拥有服务器最高权限;即使用普通用户启动,也可操作用户家目录下的所有文件。
  • SSH 后门完整操作流程
    1. 执行ssh-keygen生成密钥对,存放至临时目录;
    2. 创建用户.ssh目录,将公钥追加到authorized_keys文件;
    3. 修正目录与文件权限,满足 SSH 服务的严格权限校验;
    4. 通过木马下载私钥,后续即可直接通过 SSH 免密登录服务器。

相比 WebShell,SSH 后门更隐蔽、更稳定 —— 即使删除了 JSP 木马,只要公钥仍在授权文件中,攻击者随时可以重新获取服务器控制权。

3. 完整攻击链路复盘

  1. 利用上传漏洞写入恶意 JSP 文件至公开可访问目录;
  2. 构造 URL 访问文件,触发 Tomcat 编译执行,WebShell 生效;
  3. 通过 WebShell 执行系统命令,生成 SSH 密钥并配置免密登录;
  4. 下载私钥,获得服务器长期控制权,后续可进行提权、横向渗透、数据窃取等操作。

二、为什么绝对不能只靠后缀校验防护?

很多系统的上传防护仅做了后缀黑名单 / 白名单校验,这是最基础也最容易被突破的防线。

1. 常见可执行脚本后缀清单

仅脚本后缀就种类繁多,黑名单模式极易遗漏:

  • Java/Tomcat 体系.jsp.jspx.jspf.jws
  • PHP 体系.php.php2/3/4/5/7.phtml.pht.phar
  • ASP/ASP.NET体系.asp.aspx.ashx.asmx.axd.cshtml
  • 通用 CGI 脚本.pl.py.rb.cgi
  • 特殊危险后缀.htaccess.user.ini.shtml(可间接改写解析规则或执行命令)

2. 纯后缀校验的五大致命缺陷

(1)基础命名绕过:改文件名即可突破

无需利用漏洞,仅修改文件名格式就能绕过后缀校验,同时让容器正常解析:

  • 大小写绕过:Windows/NTFS 对大小写不敏感,.Jsp.JSP.jsp等效,若后端仅匹配小写后缀则直接被绕过。
  • 多后缀绕过:Apache 等容器默认从右向左匹配后缀,遇到未知后缀则向左继续匹配。例如shell.jsp.jpg,后端校验认为是图片,Apache 最终会按.jsp解析执行。
  • 截断绕过:老旧版本系统存在%00截断漏洞,shell.php%00.jpg会被后端识别为图片,落地后变为shell.php
  • 末尾空格 / 点绕过:Windows 会自动去除文件名末尾的空格和句号,shell.asp.shell.asp可绕过校验,落地后变为正常可执行脚本。

(2)容器解析漏洞:“安全后缀” 也会被当作脚本执行

Web 容器自身的解析逻辑漏洞,会让后缀完全合规的文件被当作脚本执行,纯后缀校验完全无法防御:

  • Tomcat 分号解析shell.jsp;123.jpg格式的文件,Tomcat 会将分号后内容视为路径参数,仍按.jsp规则解析。
  • Tomcat PUT 漏洞(CVE-2017-12615):上传时文件名写为shell.jsp/,可绕过后缀校验,最终落地为正常 JSP 文件。
  • Nginx 文件名逻辑漏洞:访问test.jpg/.php时,Nginx 会误判为 PHP 文件并转发给 PHP-FPM 执行。
  • IIS 目录解析漏洞:目录名包含.asp时,目录内所有文件都会被当作 ASP 脚本执行。

(3)配置文件注入:动态改写解析规则

攻击者可上传特殊配置文件,直接修改容器的解析规则,让 “安全后缀” 变为可执行脚本:

  • Apache 环境下上传.htaccess,添加AddType规则即可让.jpg等后缀被当作 PHP 解析;
  • PHP 环境下上传.user.ini,可动态修改 PHP 配置,实现任意文件包含执行。

(4)文件包含漏洞:后缀完全失去意义

若业务存在文件包含逻辑,只要文件内容含有恶意代码,无论后缀是什么,被包含后都会被当作脚本执行。比如 PHP 的include()、Java 的模板动态引入,都可以让后缀为.txt.jpg的文件执行恶意代码。

(5)黑名单无法穷举,永远存在遗漏

可执行后缀随容器版本、开启模块不断变化,黑名单永远存在漏判风险。只拉黑.jsp,攻击者可用.jspx绕过;只拉黑.php,攻击者可用.phtml绕过;开启 CGI 后,.py.pl等后缀也会成为攻击入口。

三、常见防护误区:后缀校验 + 目录不可执行就够了?

“后缀白名单 + 上传目录不可执行” 是性价比很高的基础防线,但远达不到 “足够安全” 的标准,且存在一个极易踩中的配置误区。

1. 最容易踩的坑:系统执行权限对脚本无效

很多人理解的 “目录不可执行”,是用chmod去掉文件的执行权限位。但这对 JSP/PHP 这类解释型脚本几乎无效:

  • 系统的x执行权限位,仅针对二进制可执行文件(ELF、exe)生效;
  • JSP/PHP 脚本由容器读取文件内容、编译 / 解释后执行,只要容器进程拥有文件的读权限,就能完成执行,完全不依赖文件自身的执行位。

真正有效的 “目录不可执行”,必须在Web 容器配置层面禁用该目录的脚本解析能力,而非仅修改系统文件权限。

2. 两层防护的核心短板

即便正确配置了容器层的目录禁执行,依然存在多处防护盲区:

  1. 挡不住容器自身解析漏洞:分号绕过、路径截断等解析漏洞可以绕过目录级的执行限制,让文件被当作脚本解析。
  2. 挡不住路径遍历:若上传功能存在路径遍历漏洞,攻击者可将恶意文件直接写入网站根目录或其他天然可执行目录,上传目录的执行限制完全失效。
  3. 挡不住业务层间接执行:模板渲染、文件包含、压缩包解压等业务逻辑,若读取并处理了上传文件,依然可能触发代码执行,与目录是否可执行无关。
  4. 挡不住配置文件改写规则:上传.htaccess等特殊配置文件,可直接突破目录的执行限制。
  5. 无法覆盖非执行类风险:SVG/XML 的 XXE 漏洞、HTML 文件的 XSS 攻击、压缩包炸弹导致的拒绝服务,都不需要文件执行权限,后缀校验也难以拦截。

四、架构级根治:对象存储(OSS/Ceph)为什么是最优解?

将用户上传文件全部迁移至独立对象存储(公有云 OSS、自建 Ceph RGW/MinIO),是从架构层面斩断 “上传→执行→入侵” 链路的最优方案,可抵御 99% 以上的脚本上传攻击。

1. 对象存储斩断攻击链路的核心原理

  1. 纯静态存储,天生无脚本解析能力
    对象存储仅负责二进制数据的存取,没有任何脚本编译、解析、执行逻辑。哪怕上传了 JSP/PHP 木马,也只会被当作普通二进制对象返回,绝不会在服务端执行代码,从本质上消除了脚本执行的可能。
  2. 与业务服务器完全隔离
    文件不落地业务服务器本地磁盘,不存在 “写入 Web 可执行目录” 的可能;对象存储采用扁平 Key-Value 结构,没有传统目录层级,路径遍历攻击彻底失效。
  3. 天然免疫所有 Web 容器解析漏洞
    所有基于容器解析规则的绕过手法(分号、多后缀、截断等),前提都是依赖 Web 容器的解析逻辑。对象存储不存在这套机制,这类攻击手法全部失效。
  4. 权限与访问链路可控
    对象存储默认私有读写,访问需通过签名授权的临时链接,攻击者无法直接猜测并触发文件;可精细控制访问时效、来源与次数,进一步降低风险。

2. 不是 100% 绝对安全:剩余风险点

对象存储解决了 “存储层直接执行脚本” 的核心风险,但无法覆盖业务层主动处理文件带来的风险:

  1. 业务后端主动处理文件的风险:若业务从对象存储下载文件进行图片裁剪、压缩包解压、模板渲染等操作,处理组件的漏洞(如 ImageMagick 漏洞、解压路径遍历)仍可能被利用,导致服务器被入侵。
  2. 前端安全风险:上传的 HTML、SVG、XML 文件被浏览器直接打开时,可触发 XSS 攻击,窃取用户 Cookie 或进行钓鱼;若存储使用主站同域名,危害会直接扩散至主站业务。
  3. 合规与配置风险:公开读写的 Bucket 可被攻击者用于恶意内容分发;配置不当的签名
 2

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2