路径穿越:../ 之外还有哪些花样
下载、读取、模板渲染、日志查看,只要「文件名来自用户」,就有路径穿越的可能。
过滤 ../ 是不够的:URL 编码、双写、unicode、绝对路径都能绕过去。
先说结论
先规范化成绝对路径,再校验是否在允许目录内。 只做字符串替换必然被绕。
- 用 realpath/abspath 规范化后再比较前缀
- 文件名白名单或映射表
- 下载走 ID 映射,不暴露真实路径
- 目录权限最小化,进程账号只读必要目录
漏洞是怎么产生的
路径穿越的目标是读取或覆盖允许目录之外的文件,典型目标是配置文件、密钥、日志。
防御的本质是「把用户输入限制在一组已知对象里」,而不是「过滤危险字符」。
修复与验证
修复不是改一行代码,而是四件事一起做:
- 所有文件参数改为 ID 映射到数据库记录
- 必须用路径时,规范化后校验前缀在允许目录内
- 拒绝包含空字节、绝对路径、盘符的输入
- 以最小权限账号运行,限制可读目录
- 对下载接口做鉴权,避免直接暴露静态路径
攻击面与检测点
按影响面排序,先修影响最大的:
| 绕过方式 | 示例 | 防御 |
|---|---|---|
| 编码 | %2e%2e%2f | 解码后规范化 |
| 双写 | ....// | 规范化后判断 |
| 绝对路径 | /etc/passwd | 只允许相对路径 |
| 符号链接 | ln -s /etc | 禁止跟随或校验真实路径 |

几个容易踩的坑
下面这些是最常见的错误做法:
- 只 replace('../',''):双写即可绕过
- 在应用层过滤但在 Nginx 层直接映射目录
- 下载接口无鉴权:知道文件名就能下
- 日志查看功能可读任意文件
写在最后
路径安全的原则是「不给路径,只给标识」。ID 映射是最省心的方案。
安全不是一次加固,是持续的假设:假设输入不可信、假设边界会破、假设有人会看错。
评论 (3)
修复清单比漏洞描述有用多了,很多文章只讲怎么打不讲怎么防。
白名单那条永远是最有效的,正则黑名单迟早绕过。
建议再补一条:把这类检查加到 CI 里,靠人记必然漏。
发表评论