
1) 【一句话结论】:通过构造文件内容开头为合法的MIME类型声明(文件头),使服务器在检查文件扩展名后,读取文件头判断MIME类型时匹配白名单,从而绕过MIME检查,实现任意文件上传并执行。
2) 【原理/概念讲解】:老师口吻解释关键概念。
文件上传时,服务器对文件的处理逻辑通常包含“文件扩展名检查”和“MIME类型检查”。文件扩展名(如.jpg)是文件名的后缀,用于快速分类;MIME类型(如image/jpeg)是文件内容开头的声明(即文件头),用于精确识别文件类型。
漏洞核心在于服务器对两者的检查顺序或验证逻辑存在缺陷:
Content-Type: image/jpeg),即使文件内容是WebShell,也能通过MIME检查。3) 【对比与适用场景】:
| 检查顺序 | 检查位置 | 验证逻辑 | 使用场景 |
|---|---|---|---|
| 扩展名优先 | 文件名后缀 | 检查是否在白名单(如.jpg) | 传统Web服务器,快速过滤 |
| MIME优先 | 文件内容前N字节 | 读取文件头判断MIME类型 | 更严格的验证,但易被文件头欺骗 |
| 混合验证 | 先扩展名,再MIME | 两者都匹配才允许 | 中间状态,易被文件头欺骗 |
4) 【示例】:
构造文件内容(伪代码):
Content-Type: image/jpeg
<?php eval($_GET['cmd']); ?>
文件名:test.jpg
上传请求示例(POST,form-data):
[文件内容]Content-Type: image/jpeg,匹配,允许上传并执行WebShell。5) 【面试口播版答案】:
面试官您好,针对文件上传漏洞,核心思路是通过构造文件头(MIME类型头)来欺骗MIME检查。具体来说,服务器通常先检查文件扩展名是否在白名单(如.jpg),然后读取文件内容前若干字节作为MIME类型。如果文件头被设置为合法的MIME类型(比如image/jpeg),即使文件内容是WebShell,也能通过检查。比如构造一个文件,开头是Content-Type: image/jpeg,后面跟着PHP WebShell代码,文件名是test.jpg,上传后服务器会认为MIME匹配,从而执行WebShell。
6) 【追问清单】:
Content-Type: image/jpeg; charset=utf-8),确保服务器解析正确。7) 【常见坑/雷区】: