利用Content-Type限制绕过机制上传Webshell程序

题目

image-20261013151715721

考点

本关服务端校验的是上传请求里的Content-Type(MIME类型),只允许image/jpeg和image/png,但没有校验文件真实内容。思路:让请求头伪装成图片类型,骗过校验。

开始打靶

我们还是先登录后发现有文件上传的功能,尝试上传一张正常的图片,成功上传,并且得到了文件上传的路径

image-20261013151929739

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

image-20261013152056117

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

image-20261013152339460

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

访问上传的文件,成功读到了文件内容

image-20261013152434541

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

image-20261013152448128

修复措施

本关问题的根源是只信请求头声明的Content-Type,没有验证文件真实内容。修复要点:

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