题目

考点
本关服务端校验的是上传请求里的Content-Type(MIME类型),只允许image/jpeg和image/png,但没有校验文件真实内容。思路:让请求头伪装成图片类型,骗过校验。
开始打靶
我们还是先登录后发现有文件上传的功能,尝试上传一张正常的图片,成功上传,并且得到了文件上传的路径

现在我们尝试上传一个php的文件去读取信息,可以看到这里被阻止了,说是文件类型不正确,只能上传image/jpeg和image/png文件

尝试将Content-Type的类型改为image/png,再尝试去上传,发现上传成功了

Content-Type只是请求里自己声明的一个字段,表示”我声称这个文件是什么类型”。如果服务端只信这个声明、不去验证文件真实内容,那把它改成image/png就能骗过校验——而文件内容依然是php代码,服务器保存后照样按.php后缀解析执行。
访问上传的文件,成功读到了文件内容

提交获取到的内容,通关!

修复措施
本关问题的根源是只信请求头声明的Content-Type,没有验证文件真实内容。修复要点:
- 不要信任客户端声明:
Content-Type是浏览器/攻击者随便填的,不能作为安全依据。 - 服务端检测真实类型:用
mime_content_type()或finfo_file()读文件实际内容判断MIME,而不是读请求头。 - 双重校验:扩展名白名单+真实内容校验都过才放行,只过其中一个都不行。
- 重命名+不可执行目录:和入门关一样,服务端随机命名、存储目录禁止执行脚本。