上传时把文件名改成 ../../static/x.jsp,服务端原样拼路径保存,返回的地址指向了应用目录之外,权限够的话能覆盖配置文件。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,客户端传来的文件名被直接拼进保存路径,没做规范化也没校验目录归属,点段把路径带出了目标目录,写入就落到任意位置。
碰到「上传路径穿越」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
name = os.path.basename(raw).replace('..', '')
dst = os.path.realpath(os.path.join(UPLOAD, name))
assert dst.startswith(os.path.realpath(UPLOAD))
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。
具体做法是,保存的时候丢掉原文件名,用随机串加白名单后缀;拼完路径做一次规范化,确认仍然在目标目录内;上传目录设成只写不可执行,去掉脚本解析权限。
最后用这个标准收尾,带 ../ 的文件名上传后只落在上传目录内,越界请求直接被拒绝。
