「在文件名的地方混入 ../,结果连服务器深处的 .env 都能读到」——这就是路径遍历。本文讲解其原理与可靠的防范方法(不会写出攻击步骤)。
会出现在哪里
凡是「用用户输入来选择文件」的地方都是候选。
| 功能 | 危险的用法 |
|---|---|
| 下载/预览 | 把 ?file= 中的文件名原样使用 |
| 图片/附件的显示 | 用 URL 参数拼出路径的一部分 |
| 上传 | 在保存目标路径中使用用户指定的名字(写入型·最危险) |
| 模板/语言文件读取 | 用 ?lang= 等动态选择文件 |
为什么会成立(原理)
../ 表示「向上一级目录」。当应用把 公开文件夹 + 用户输入 原样拼接起来打开文件时,用叠加了 ../ 的输入就能「走」出公开文件夹之外。
读取会导致信息泄露,写入(上传)则会被在任意位置放置文件,有时还会发展为 RCE。
防御:不把输入用作路径 + 限制在基准内
不把用户输入用作生文件路径(最重要)
要公开的文件用 ID→实际文件的对应表(白名单)来查。用户传入的只是「第 3 号」「invoice」等标识符,实际路径由服务器决定。
规范化之后,务必确认「是否在基准目录的内侧」
用语言标准的路径规范化(相当于 resolve/realpath)转换为绝对路径,并校验它是否以所允许的基准目录开头。在外面就拒绝。../ 的简单字符串删除存在编码绕过,因此不可取。
以最小权限运行应用
把应用运行用户能读取的文件收窄到业务所需的范围。即便万一被逃出,只要本来就读不到,就不会产生危害。
把「不该交出的东西」放到公开根目录之外
.env·.git·密钥·备份,本来就不要放在 Web 根目录或上传文件夹里。用配置消除攻击面。
本站的视角:与配置失误一脉相连。别弄错堵漏的顺序
路径遍历与 .env 公开的事故一脉相连。两者都是「本不该经由 Web 送达的东西,却经由 Web 送达了」的问题。用应急处置(响应头或简单过滤)把「症状」掩盖起来,只要代码和配置没修好,就会从别的路径被穿出去。顺序是①不把输入用作路径的代码 ②基准目录内的检查 ③根本上把秘密挪到公开根目录之外。再配合阅读 在共享租用服务器上的安全配置,就能看清根本对策的形态。
接下来阅读
- 事故:把 .env 整个公开出去的事故
- 对策:租用服务器上的 .env 保护 / 术语:RCE 是什么
FAQ
Q路径遍历会泄露什么?
本来这个应用不应让人接触到的文件。典型例子有 .env(数据库凭据、API 密钥)、配置文件、私钥、源代码、操作系统的 /etc 目录下的文件等。不仅是读取,一旦被滥用于指定上传目标路径,还会被写入到任意位置,进而可能发展为 RCE(任意代码执行)。
Q最主要的防御是什么?
就是「不把用户的输入原样用作文件路径」。如果实在要用,就把它转换为白名单(ID 或固定的文件名集合),并用库对路径进行规范化后,务必确认「它是否落在基准目录的内侧」。仅靠扩展名校验或简单地删除 ../ 是会被绕过的。
Q用 .htaccess 或响应头堵上就行了吗?
那只是针对「本不该交出的文件被放在了公开目录」这一另一个问题的应急处置。根本在于纠正配置「把应用本体、.env、.git 放到公开根目录之外」,以及编写不把输入用作路径的代码。应急处置和根本对策是两项不同的工作。