题目

考点
本关服务端对上传做了目录限制(只能保存到指定目录),但保存路径拼接的是用户可控的filename字段。思路:用路径遍历(../)跳出限制目录,把文件写到可以解析执行的位置;后端还做了简单关键字过滤,用URL编码(%2e%2e%2f)绕过。
开始打靶
依旧是先上传一张正常的图片去获取到图片存储的路径

接着上传php文件去读取文件,可以看到成功上传

我们访问上传的文件,发现我们的php代码不能被解析了,显示了源代码

multipart/form-data 上传请求里的 filename 字段,服务器常拿这个值决定保存文件名 + 存放路径
我们尝试加上../用来跳出当前目录,将文件上传到上一级目录

这里有一个问题,那就是我们文件虽然看起来是上传成功了,但是我们仔细看会发现我们上传成功的文件保存的路径好像依然还是这个,和我们不加上../一样。所以我们考虑服务器后端有校验,可能有关键字符过滤,这里尝试将../进行url编码,重新上传后成功的上传了

去访问文件上传的路径,成功读取到了内容

最后提交内容成功通关~

修复措施
本关问题根源是用用户可控的filename拼接存储路径。修复要点:
- 不要用用户文件名拼路径:文件名只用来展示,存储路径完全由服务端决定,
../想跳也跳不出去。 - 过滤危险字符:对filename做消毒,拒绝
../、%00、\等字符,URL编码的(%2e%2e%2f)也要解出来再拦。 - 路径规范化校验:保存前用
realpath()解析最终路径,确认它还在允许的目录内,越界直接拒绝。 - 固定存储目录+不可执行:文件只进固定目录,目录禁脚本执行。