文件上传漏洞实战:从原理到防御,剖析企业应用安全风险

📅 2026/6/28 21:12:54
文件上传漏洞实战:从原理到防御,剖析企业应用安全风险
1. 项目概述一次典型的企业应用文件上传漏洞实战最近在梳理一些历史漏洞案例时我重新审视了“金华迪加现场大屏互动系统”的一个老漏洞。这个案例非常经典它暴露了在快速迭代的业务系统中开发人员对文件上传功能安全边界的忽视。漏洞的核心在于其移动端处理接口mobile.do.php存在任意文件上传缺陷攻击者能够绕过前端校验将恶意文件如Webshell上传至服务器从而获取系统控制权。这类漏洞在会展、活动、年会等需要现场互动的系统中危害极大因为这类系统通常部署在内网或临时公网环境安全防护相对薄弱一旦被入侵可能导致现场活动数据被篡改、参与者信息泄露甚至成为攻击内网其他系统的跳板。这个复现过程不仅仅是按部就班地执行攻击步骤更重要的是理解漏洞产生的根源、挖掘的方法以及在实际渗透测试或安全评估中如何系统地发现和验证此类问题。对于安全研究人员、渗透测试工程师以及企业开发人员来说通过复现此类漏洞可以深刻认识到一个看似简单的上传功能如果缺乏纵深防御会带来多么严重的后果。接下来我将从环境搭建、漏洞原理分析、利用过程到深度利用与防御完整地拆解这个案例并分享其中踩过的坑和总结的经验。2. 漏洞环境搭建与核心原理剖析2.1 目标系统与漏洞点定位“金华迪加现场大屏互动系统”通常用于活动现场的签到、抽奖、投票、弹幕上墙等场景。其架构多为B/S模式后台管理端和现场大屏展示端通过Web服务进行交互。mobile.do.php这个文件从命名上看很可能是专门用于处理移动端如微信扫码参与请求的接口文件。在分析这类系统时一个高效的思路是首先进行目录扫描和文件枚举寻找可能的上传点、管理接口或未授权访问的脚本。使用工具如dirsearch、gobuster或御剑等针对常见的PHP后台路径、API接口路径进行扫描。很快我们可能会发现诸如/admin/、/api/、/inc/等目录以及像upload.php、do_upload.php、saveimage.php这类敏感文件。而mobile.do.php很可能就位于网站根目录或某个移动端专属的目录下。漏洞的原理并不复杂但非常典型。其核心问题通常出在以下几个环节的缺失或失效文件类型校验绕过前端通过JavaScript或HTML的accept属性限制只能上传图片如.jpg, .png但后端mobile.do.php在处理$_FILES全局变量时仅通过$_FILES[‘file’][‘type’]由浏览器提供的MIME类型进行判断或者直接检查文件后缀名。攻击者可以通过Burp Suite等代理工具拦截HTTP请求将Content-Type修改为image/jpeg或将文件名改为shell.php.jpg从而绕过校验。文件内容校验缺失系统没有对上传文件的内容进行二次检查例如使用getimagesize()函数验证文件是否为真实的图片或者检查文件头魔术字节。这使得一个包含PHP代码的图片马在图片二进制内容末尾追加PHP代码或直接伪造的PHP文件得以成功上传。上传路径可控或可预测上传后的文件存储路径可能直接由用户参数控制或者使用了时间戳、随机数等可预测的规则生成导致攻击者能够准确访问上传的恶意文件。权限分离不当上传目录如/uploads/被配置了执行脚本的权限如Apache中未设置php_admin_value engine off导致即使上传了.php文件也能被Web服务器解析执行。mobile.do.php很可能就是一个接收multipart/form-data格式POST请求的上传处理器它没有严格实施上述的所有安全措施。2.2 实验环境快速搭建为了安全、合法地复现漏洞我们必须在自己的隔离环境中进行。我推荐使用 Docker 快速搭建一个包含漏洞靶场和测试工具的沙箱。方案一使用现成漏洞靶场推荐如果存在该系统的漏洞靶场镜像例如某些 Vulhub 或 VulnApp 项目这是最快的方式。# 假设存在一个名为 jinhua-diga 的漏洞环境镜像 docker pull vulnerables/jinhua-diga-lamp docker run -d -p 8080:80 --name jinhua-diga vulnerables/jinhua-diga-lamp访问http://your-host-ip:8080即可看到系统界面。方案二手动搭建模拟环境如果找不到现成靶场我们可以基于一个标准的LAMPLinuxApacheMySQLPHP环境手动模拟漏洞点。这有助于更深入地理解漏洞上下文。创建基础目录结构mkdir -p /tmp/vuln_site cd /tmp/vuln_site # 假设网站根目录为 html mkdir html uploads编写存在漏洞的 mobile.do.php 在html目录下创建mobile.do.php模拟一个有缺陷的上传逻辑?php // mobile.do.php - 存在缺陷的上传处理器 header(Content-Type: text/html; charsetutf-8); // 模拟一个简单的“认证”实际可能更复杂或没有 session_start(); // 假设这里有一个脆弱的会话验证或者根本没有 if ($_SERVER[REQUEST_METHOD] POST) { $upload_dir ../uploads/; // 上传目录通常位于Web目录外或内 $allowed_types array(image/jpeg, image/png, image/gif); $file $_FILES[file]; // 漏洞点1仅检查客户端提供的MIME类型 if (in_array($file[type], $allowed_types)) { // 漏洞点2使用原始文件名未重命名或过滤危险字符 $target_file $upload_dir . basename($file[name]); // 漏洞点3未检查文件内容直接移动 if (move_uploaded_file($file[tmp_name], $target_file)) { echo 文件上传成功路径: . htmlspecialchars($target_file); // 在实际系统中这里可能会返回一个JSON包含文件访问URL } else { echo 文件移动失败。; } } else { echo 文件类型不允许。; } } else { // 显示一个简单的上传表单 ? !DOCTYPE html html body form actionmobile.do.php methodpost enctypemultipart/form-data 选择文件上传模拟移动端接口: input typefile namefile acceptimage/* input typesubmit value上传 /form /body /html ?php } ?配置Apache与权限 确保Apache运行并且uploads目录对Web服务器用户如www-data可写且该目录错误地配置了PHP执行权限这是漏洞利用的关键。在实际漏洞中这个目录可能就在Web根目录下或者通过符号链接等方式可访问。注意此模拟代码极度简化仅用于演示核心漏洞原理。真实漏洞的代码可能嵌套在框架中参数名可能不同如filedata,imgFile等但核心逻辑缺陷是相似的。2.3 核心工具准备工欲善其事必先利其器。复现此类漏洞以下几款工具是必备的Burp Suite Professional / CommunityHTTP代理神器用于拦截、修改和重放请求。社区版对于基础漏洞复现足够用。关键功能Proxy拦截、Repeater重放、Intruder模糊测试。浏览器Chrome或Firefox配合Burp Suite的CA证书安装以便拦截HTTPS流量。中国菜刀/C刀/蚁剑/AntSwordWebshell管理工具。重要声明这些工具仅限在您拥有完全控制权的测试环境中使用用于验证漏洞危害。严禁用于任何未授权的测试。我个人在内部测试中更倾向于使用AntSword因其开源、跨平台且插件丰富。目录扫描工具如dirsearch(Python) 或gobuster(Go)用于发现潜在的mobile.do.php及其他敏感路径。python3 dirsearch.py -u http://target.com -e php,html,js -t 50文本编辑器/IDE用于编写和修改Webshell代码如VS Code、Sublime Text。Docker Docker Compose用于快速搭建和销毁测试环境避免污染宿主机。3. 漏洞利用过程深度解析3.1 信息收集与漏洞点确认在获得目标系统地址我们的测试环境http://localhost:8080后第一步不是直接攻击而是信息收集。系统指纹识别使用浏览器访问首页查看页面源码、HTTP响应头寻找框架特征如ThinkPHP、Laravel的标识、版权信息等。使用Wappalyzer浏览器插件可以快速识别技术栈。这有助于判断系统的整体安全性以及是否存在已知的通用漏洞。寻找上传接口直接尝试访问/mobile.do.php。如果返回一个上传表单或空白页可能需POST请求则初步确认该接口存在。如果返回404则需用目录扫描工具尝试更多路径如/api/mobile.do.php、/inc/mobile.do.php、/plugin/mobile/do.php等变体。分析请求参数通过浏览器开发者工具的Network面板或使用Burp拦截一次正常的上传请求例如上传一张真实图片。观察关键的参数POST路径和参数。Content-Type头部特别是multipart/form-data及其boundary。POST数据体中的name字段如file以及filename和Content-Type子头部。服务器返回的响应特别是成功上传后返回的文件存储路径或访问URL。这个路径是后续连接Webshell的关键。3.2 绕过前端校验与文件上传假设我们访问http://localhost:8080/mobile.do.php看到了一个简单的图片上传表单。正常流程测试首先选择一张正常的test.jpg图片上传用Burp Suite拦截这个请求。目的是观察正常请求的格式和服务器成功响应。请求示例Burp Raw View:POST /mobile.do.php HTTP/1.1 Host: localhost:8080 Content-Type: multipart/form-data; boundary----WebKitFormBoundaryABC123 Content-Length: 123456 ------WebKitFormBoundaryABC123 Content-Disposition: form-data; namefile; filenametest.jpg Content-Type: image/jpeg [JPEG文件二进制数据] ------WebKitFormBoundaryABC123--成功响应可能为文件上传成功路径: ../uploads/test.jpg或返回一个JSON{code:1, msg:success, url:/uploads/2025/03/27/test.jpg}。构造恶意请求在Burp的Proxy - Intercept标签页将拦截到的请求发送到Repeater标签页进行修改。这是漏洞利用的核心步骤。修改文件名将filenametest.jpg改为filenameshell.php。这是最直接的尝试如果后端只检查MIME类型可能成功。修改MIME类型将Content-Type: image/jpeg改为Content-Type: image/jpeg保持不变或Content-Type: text/plain同时文件名改为shell.php。测试后端是否信任客户端提交的MIME类型。使用双扩展名将filename改为shell.php.jpg。这是绕过某些简单后缀名检查如检查是否以.jpg结尾的常见手法。插入PHP代码将文件内容部分[JPEG文件二进制数据]替换为一个简单的PHP WebShell代码。例如一个极简的接受cmd参数执行系统命令的Shell?php eval($_POST[cmd]);?注意在实际测试中为了避免被杀毒软件或简单的内容检查拦截可能会将PHP代码嵌入到图片文件的末尾制作图片马或者使用混淆技巧。但在初步验证时直接上传纯文本的PHP代码是最快的方式。发送并观察响应在Repeater中点击“Send”发送修改后的请求。重点关注响应状态码和内容。返回成功并给出了文件路径恭喜漏洞很可能存在。记录下这个路径如../uploads/shell.php。你需要根据响应推断出Web可访问的URL。如果返回../uploads/则Web访问路径可能是http://localhost:8080/uploads/shell.php。如果返回相对路径需要结合网站目录结构判断。返回“文件类型不允许”说明后端有初步的校验。需要进一步尝试尝试shell.php.jpg同时保持Content-Type: image/jpeg。尝试在图片内容中嵌入PHP代码使用copy /b normal.jpg shell.php webshell.jpg命令制作图片马然后上传这个图片马并尝试利用文件包含漏洞或解析漏洞如Apache的AddType误配置、IIS的;解析漏洞等来执行代码。但在此案例中我们聚焦于mobile.do.php自身的上传逻辑缺陷。返回其他错误或空白可能需要检查其他参数或者系统存在Token、Referer等校验。这时需要分析正常请求是否携带了session cookie或其他认证字段。在Burp中确保从浏览器捕获的完整请求包含Cookie头被发送到了Repeater。3.3 Webshell连接与权限获取一旦确认上传成功并获得了Webshell的访问地址下一步就是验证其可用性并尝试获取更高权限。初步验证直接在浏览器中访问上传的Webshell文件例如http://localhost:8080/uploads/shell.php。如果页面空白或没有错误这通常是好迹象PHP代码被解析执行但没有输出。如果返回了PHP源代码说明该文件没有被PHP解析。这可能是因为上传目录没有执行PHP的权限这是安全配置或者文件后缀没有被识别为PHP。此时需要重新审视上传路径和服务器配置。在本次模拟漏洞中我们假设uploads目录配置错误允许执行PHP。使用Webshell管理工具连接打开AntSword添加一个新的Shell。URL地址填写Webshell的完整URL如http://localhost:8080/uploads/shell.php。连接密码填写Webshell代码中定义的密码参数。在我们上面的例子中是cmd因为代码是$_POST[cmd]。在AntSword中这通常对应“密码”字段但具体取决于Webshell的类型。对于自定义的eval($_POST[cmd])AntSword的“自定义脚本”连接类型可能更合适或者使用其内置的“PHP Eval”类型密码填cmd。编码器、解码器通常保持默认即可。如果连接失败可以尝试切换编码器如base64以绕过一些简单的WAF。点击“添加”然后双击连接。如果成功左侧会列出服务器的目录结构。权限提升与信息收集内网渗透视角 连接成功后我们模拟攻击者的下一步操作查看当前权限在AntSword的虚拟终端或文件管理器中执行命令whoamiLinux或echo %USERNAME%Windows查看Web服务运行的用户身份。通常是低权限用户如www-data、apache、nobody或IIS APPPOOL\DefaultAppPool。收集系统信息执行uname -a或systeminfo查看操作系统、内核版本、补丁情况。寻找可能的本地提权漏洞。查看网络配置执行ifconfig或ipconfig /all获取内网IP段、网关信息为可能的横向移动做准备。查找敏感文件浏览网站目录、配置文件如config.php、database.php、日志文件寻找数据库密码、API密钥等敏感信息。尝试提权根据系统类型搜索可利用的本地漏洞如Dirty Pipe、永恒之蓝MS17-010的本地利用等、检查SUID文件、计划任务、可写服务路径等。在测试环境中此步骤仅为演示攻击链切勿在非授权环境尝试。实操心得在实际渗透测试中上传Webshell只是第一步。往往需要根据目标环境进行“免杀”处理例如对Webshell代码进行加密、混淆或者使用动态函数调用等方式绕过简单的静态查杀。此外上传后应立即尝试将Shell迁移到更隐蔽的目录或写入一句话到现有合法PHP文件中以维持持久化访问。4. 漏洞根源深度分析与安全编码实践4.1 为什么 mobile.do.php 会出问题复盘这个漏洞根本原因在于开发过程中的安全意识缺失和“信任用户输入”这一黄金法则被打破。功能优先安全滞后在快速开发面向活动的系统时核心目标是功能稳定、体验流畅。文件上传作为基础功能开发人员可能直接采用了网络上未经严格安全审查的代码片段或者自己实现时只考虑了功能正常忽略了恶意输入。前端校验不可靠依赖JavaScript或HTML5的accept属性进行文件类型过滤是极度危险的因为攻击者可以完全绕过浏览器如直接用Burp发送请求。前端校验应仅作为用户体验优化绝不能作为安全边界。后端校验流于形式MIME类型检查$_FILES[‘file’][‘type’]的值完全由客户端控制可以随意伪造。正确的做法是使用PHP的finfo_file()函数Fileinfo扩展或mime_content_type()函数通过读取文件内容的头几个字节魔术字节来判断真实类型。后缀名检查简单的strpos()或substr()检查后缀名很容易被shell.php.jpg、shell.php%20、shell.php::DATANTFS流等方式绕过。应使用白名单机制只允许有限的、安全的扩展名如.jpg,.png,.gif并且将后缀名与文件的真实MIME类型进行匹配校验。内容检查缺失对于图片应使用GD库或ImageMagick的imagecreatefromjpeg()等函数尝试打开图片。如果打开失败则不是有效图片。这能有效防御图片马。对于其他文件类型也应有相应的内容格式验证。存储路径与权限问题使用原始文件名直接使用用户上传的文件名可能导致目录遍历如文件名包含../../../etc/passwd或覆盖重要文件。必须对文件名进行重命名例如使用md5(uniqid().microtime())生成随机文件名并保留安全的后缀。上传目录可执行这是最致命的配置错误。上传目录存储用户文件的目录必须设置为不可执行脚本。在Apache中可以在.htaccess或虚拟主机配置中添加php_flag engine off。在Nginx中确保对该目录的location块不传递PHP请求给FastCGI处理器。直接返回可访问路径返回完整的服务器物理路径或相对路径暴露了目录结构。应只返回基于Web根目录的相对URL或通过一个单独的、有权限控制的下载/访问脚本来读取文件。4.2 安全的文件上传功能实现指南基于以上分析一个健壮的文件上传处理流程应该如下?php // safe_upload.php function safeUpload($fileInputName) { // 1. 基础检查 if (!isset($_FILES[$fileInputName]) || $_FILES[$fileInputName][error] ! UPLOAD_ERR_OK) { return [success false, msg 上传失败或文件错误]; } $file $_FILES[$fileInputName]; $tmp_path $file[tmp_name]; // 2. 白名单允许的扩展名和对应的真实MIME类型 $allowed [ jpg [image/jpeg, image/pjpeg], png [image/png], gif [image/gif], // 可根据需要添加 pdf, docx 等并定义其魔术字节 ]; // 3. 使用 finfo 检测文件真实类型 $finfo finfo_open(FILEINFO_MIME_TYPE); $real_mime finfo_file($finfo, $tmp_path); finfo_close($finfo); // 4. 获取并验证后缀名 $client_name $file[name]; $ext strtolower(pathinfo($client_name, PATHINFO_EXTENSION)); if (!array_key_exists($ext, $allowed)) { return [success false, msg 文件类型不允许]; } // 5. 验证真实MIME类型是否在白名单内 if (!in_array($real_mime, $allowed[$ext])) { return [success false, msg 文件类型不匹配]; } // 6. 图片文件额外验证如果允许的是图片 if (in_array($real_mime, [image/jpeg, image/png, image/gif])) { $image_info getimagesize($tmp_path); if ($image_info false) { return [success false, msg 上传的不是有效图片]; } // 可选限制图片尺寸 // if ($image_info[0] 2000 || $image_info[1] 2000) {...} } // 7. 生成安全的存储文件名和路径 $safe_filename md5(uniqid() . microtime()) . . . $ext; $upload_dir /var/www/html/protected_uploads/; // 位于Web根目录之外 $full_path $upload_dir . $safe_filename; // 8. 移动文件 if (move_uploaded_file($tmp_path, $full_path)) { // 9. 返回一个访问令牌或经过安全处理的URL而不是直接路径 $access_token generateSecureToken($safe_filename); // 将 $access_token 和 $safe_filename 的映射关系存入数据库 $url /download.php?token . $access_token; // 通过一个安全脚本代理访问 return [success true, url $url]; } else { return [success false, msg 服务器存储失败]; } } // 独立的文件访问脚本 download.php // 1. 验证 token 有效性从数据库查询 // 2. 验证用户是否有权限访问该文件结合会话 // 3. 设置正确的 Content-Type 头 // 4. 使用 readfile() 安全地输出文件内容 ?4.3 企业级防御措施建议对于企业而言仅靠安全的代码是不够的还需要在架构和运维层面建立纵深防御WAFWeb应用防火墙部署WAF可以有效拦截常见的攻击payload如包含eval(、system(等危险函数的请求。但WAF可能被绕过不能作为唯一防线。定期安全扫描与渗透测试对上线前的代码进行白盒审计SAST对运行中的系统进行黑盒扫描和定期的渗透测试主动发现类似mobile.do.php这样的漏洞。最小权限原则运行Web服务的账户如www-data应具有最低必要的权限。确保上传目录、配置文件等关键资源的权限设置正确。安全开发生命周期SDL将安全要求嵌入到需求、设计、编码、测试、部署的全流程中。对开发人员进行持续的安全编码培训。日志与监控详细记录文件上传操作的日志时间、IP、文件名、结果并设置告警规则如短时间内大量上传尝试、上传非常规后缀文件等以便及时发现攻击行为。5. 漏洞复现的常见问题与排查技巧在复现过程中你可能会遇到各种问题。以下是一些常见情况及解决思路问题现象可能原因排查与解决思路访问mobile.do.php返回 404路径不正确或文件不存在。1. 使用目录扫描工具dirsearch, gobuster寻找该文件或类似上传接口。2. 检查目标系统是否使用了URL重写如ThinkPHP的PATH_INFO模式实际路径可能不同。3. 确认漏洞信息中的路径是否完整是否需特定参数触发如?actionupload。上传请求被拦截返回“无效请求”或空白页可能存在Token、Referer、Cookie等验证。1. 用Burp拦截一次浏览器正常操作产生的上传请求确保所有头部包括Cookie、CSRF Token被完整捕获并重放。2. 观察正常请求的URL是否包含时间戳、签名等参数尝试模拟。3. 如果存在会话确保在Burp的Repeater中使用了正确的Cookie头。修改文件名/MIME类型后返回“文件类型错误”后端有较强的校验逻辑。1.双写扩展名尝试shell.php.jpg,shell.php.jpeg。2.大小写绕过尝试shell.Php,shell.PHP5。3.空格/点号绕过尝试shell.php.(末尾加点),shell.php(末尾加空格需URL编码为%20)。4.配合解析漏洞如果服务器是IIS尝试shell.php;.jpg或shell.jpg/.php。如果是Nginx特定版本尝试shell.jpg%00.php(需PHP特定版本)。5.制作图片马将PHP代码追加到真实图片后上传此图片马然后结合文件包含漏洞(LFI)来执行代码。上传成功但访问Webshell返回源码或404上传目录无执行权限或文件被重命名。1.检查返回路径仔细看服务器成功响应中返回的路径。它可能是相对路径、绝对路径或URL。尝试拼接成完整的Web URL访问。2.检查目录权限尝试上传一个纯文本文件.txt然后通过浏览器访问看是否能读取。如果能读但不能执行.php说明目录配置正确禁止执行。此时漏洞可能无法直接获取Webshell需寻找其他利用点。3.文件名被修改系统可能自动重命名了文件。响应中可能返回的是新文件名。使用AntSword等工具连接失败Webshell代码不兼容、密码不对、或环境有防护。1.验证Webshell可用性先通过浏览器直接带参访问如http://target/shell.php?cmdecho test;看是否有回显。确认代码执行环境。2.检查连接配置AntSword的URL、密码、编码器必须与Webshell代码匹配。对于eval($_POST[‘c’])密码就填c。3.尝试基础编码在AntSword连接设置中将请求编码器改为base64看是否能绕过一些简单的过滤。4.更换Webshell类型尝试使用其他一句话木马如assert,system等但注意目标PHP环境可能禁用了一些危险函数在php.ini的disable_functions中。命令执行成功但权限很低Web服务以低权限用户运行。1.信息收集执行whoami; id; sudo -l查看当前权限和可能的sudo权限。2.查找提权向量上传Linux提权检查脚本如LinEnum, linux-exploit-suggester或Windows信息收集脚本寻找内核漏洞、错误配置的服务、SUID文件等。3.数据库提权如果获取到数据库密码且数据库以高权限运行可尝试通过数据库执行系统命令如MySQL的into outfile或UDF提权。此部分仅用于授权测试环境中的攻防研究。踩坑实录在一次内部测试中我遇到一个系统它不仅检查后缀和MIME还检查了文件头。我上传的.php.jpg文件因为内容不是有效的JPEG而被拒绝。最终我使用GIMP打开一张正常图片在注释区域EXIF中插入PHP代码并保存成功绕过了内容检查。这提醒我们安全校验必须多维度、全方位而攻击者的绕过手法也同样会不断进化。6. 从漏洞复现到安全研究的思考复现“金华迪加”这样的漏洞绝不仅仅是为了“能黑进去”。它的价值在于理解攻击链从一个简单的上传点到获取Webshell再到内网渗透这是一个完整的攻击链缩影。通过亲手实践你能深刻体会攻击者的思维和每一步的依赖条件。强化防御视角知道了怎么攻才能更好地防。在代码审计时你会本能地去寻找那些脆弱的move_uploaded_file调用在架构设计时你会主动考虑上传目录的权限隔离和静态资源托管。培养漏洞挖掘嗅觉看到upload、save、do.php这类接口名你会立刻警觉。在目录扫描结果中你会优先关注那些看似功能单一的处理器文件。这种“嗅觉”需要通过大量案例复现和分析来培养。合规与授权意识所有操作必须在完全可控的、自己拥有权限的环境中进行。这反复强调了安全工作的底线——法律与道德。任何在未授权环境下的测试都是非法的。这个漏洞本身技术难度不高但它像一面镜子映照出许多中小型企业在业务快速发展期对安全问题的忽视。作为安全从业者我们的任务就是通过不断地研究、复现、分析和宣讲将“安全左移”的理念植入到开发流程的每一个环节让每一个mobile.do.php都能被安全地实现。最后再分享一个习惯在测试任何上传功能时除了尝试上传脚本文件别忘了也试试上传超大文件DoS攻击、上传同名文件覆盖攻击、以及上传包含特殊目录遍历字符的文件名一个健壮的上传功能应该能妥善处理所有这些异常情况。