文件上传绕过为什么总在“解析”层
后缀白名单、MIME 校验、内容检查,三样都做了,上传点还是被打穿。原因不在校验写得糙:三道检查全在"进门"环节,而决定成败的是"文件落地之后,谁来解析它"。
三道检查都做了,为什么还失守
一条常见的上传链路:扩展名白名单只放图片与文档、Content-Type 做比对、图片走二次渲染、落地文件名换成随机串、目录放在 Web 根下。
每一步都合理。审计报告指出的位置却不在这些代码里,而在同一条链的另一端:落地目录能不能执行脚本、有没有别的地方会把这个文件当代码读。
上传点的风险从来不是单点,是两段拼起来——落地位与执行位。校验只管落地位,执行位常常写在别的配置文件里。
三检各自的边界
| 检查 | 判定对象 | 能否阻止落地后被当代码执行 |
|---|---|---|
| 扩展名白名单 | 文件名的字符串 | 否。名字是给人看的,解析器认的是另一套规则 |
| MIME 校验 | 请求头里的声明 | 否。声明由客户端给出,服务端只能验证它像不像 |
| 内容/魔数检查 | 文件的字节特征 | 否。判定的是"这文件像什么",不是"谁会执行它" |
三行都写着"否",原因同一个:三检判定的都是"文件的属性",而执行与否取决于"解析环境"。
一段代码是不是脚本,不由它的后缀决定,由处理它的那个进程决定。这是上传问题与 SQL 注入最像的地方——判据都在上游,结论却在下游。
解析层的三种放大
一、目录可执行。 落地目录在 Web 根内,且该目录允许脚本执行。此时"能写文件"直接等于"能写可执行文件",中间不需要任何绕过。反过来,目录禁执行时,即使传上去一个标准脚本文件,访问它也只是拿到源代码。
二、解析器取值与校验侧不一致。 校验侧取最后一个后缀或白名单里的第一个,解析侧按自己的顺序取。Apache 的多后缀映射、Nginx location 正则的匹配顺序、php-fpm 的扩展名限制,都可能与校验侧得出不同结论。同一个文件名,两套判定,谁在前面谁说了算。还有一类解析器干脆不看后缀,按内容嗅探决定是否交给脚本处理器;后缀白名单在这类解析器面前直接失效。
三、包含点与重写规则。 上传文件被 include、被模板引擎当成缓存、被伪静态规则转给脚本处理——静态文件在某一刻被当成代码读入。这一步不需要目录可执行,只需要一个"读它的人"。
三种放大里,第一种是配置问题,第二种是判定不一致,第三种是把数据当代码。危害都在解析环节,都不在上传接口的代码里。
组合链
一条完整的链需要两个位置:能落地的上传点、能执行或能读入的位置。缺一个都不成链。
这也解释了很多争议:单看上传接口,白名单齐全,判不了;单看某一个目录配置,也没人往里写文件,判不了。两个位置接上,才是漏洞。
判据可以借用漏洞判定五问法的前两问——先问"能不能多做一步无权操作",再看"这一步离业务目标有多远"。上传点给出的是"多一步写文件",执行位决定"能不能再往前走"。
审计怎么看
按顺序看四件事。
一、落地目录与 Web 根的关系。 取真实路径比较,不看配置里写的相对路径。目录在 Web 根内、且可执行,后面两条才有意义。
二、目录的解析配置。 目录级是否关掉脚本解析、扩展名是否被全局映射到脚本处理器、location 的匹配顺序。这一层通常不在代码仓库里,要去看部署配置。
三、有没有"读它的人"。 全文搜 include、require、模板加载、缓存读取,看路径是否可受外部影响。有包含点,上传目录就不只是存储。
四、重写与伪静态。 规则会不会把静态后缀交给脚本进程。规则写错一次,后面所有上传点都变成入口。
这套找法在站内《危险函数检索为什么在真实项目里失效》里已经拆过一遍:搜函数名找不到缺陷,因为缺陷长在位置关系上,不长在函数调用上。站内文章:危险函数检索为什么在真实项目里失效
怎么修
四件事,按代价从低到高。
文件名由服务端决定。 随机重命名,扩展名按内容映射生成,不采信客户端给的名字。这一条消掉"名字与解析不一致"的大半问题。
落地目录禁执行。 目录级关闭脚本解析,或把目录移出 Web 根,只通过下载接口输出。这是最有效的一条,因为它从根上取消了"执行位"。
双白名单。 内容类型白名单加扩展名白名单,两者都要过;扩展名与处理器之间用固定映射表,不做字符串拼接。
物理分离。 上传目录与站点目录分开,必要时放在独立域名或对象存储下,下载走鉴权接口,不让浏览器直连原始文件。
四件事里,只做第一件是缓解,做了第二件才算修复。
上传点的价值不在"传上去",在"传上去之后有没有人执行它"。 按这句话验收:改完之后,每一个上传目录都应该能回答"谁在解析它、用什么规则解析"。
本文仅用于安全学习与授权环境下的测试。文中所有示例均为本地或授权靶场环境,不构成对任何真实系统的测试指引。
仅限授权测试,严禁非法滥用。
读到这里,说明你在认真看。加入社群,与我们一起深挖底层。
或点此直接进入「星巡底层研习」 →
扫码加入交流社群