PHP 中的错误 MIME 类型检测

False MIME type detection in PHP

我有这个代码:

<?php
    if (isset($_POST)) {
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $fileMime = finfo_file($finfo, $_FILES["file"]["tmp_name"]);
        finfo_close($finfo);
        echo $fileMime;
    }
?>
<form method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <button type="submit">Upload</button>
</form>

在某些情况下,人们设法伪造了 MIME 类型,它是一个带有 application/octet-stream 的 .php 文件,脚本将其检测为 image/jpeg.

有什么方法可以解决这个问题并检测正确的 MIME 类型吗?

谢谢!

it was a a .php file

Microsoft 已为您做好准备。文件名不是由文件的内容决定的。人们常用前者来表示后者,只是一种约定俗成。大多数网络服务器使用相同的约定将处理程序映射到文件。因此,如果您愚蠢到相信用户提供的数据并将文件存储在文档根目录中,那么用户就可以将任意脚本上传到您的服务器。

正如 Marc B 所说,finfo_file 读取文件并尝试将 variable number of bytes at the beginning of the file 与已知文件格式的数据库相匹配。

我猜这个文件可能一开始看起来像 JPEG。

一旦网络服务器决定通过 PHP 处理程序推送内容,PHP 将忽略外部的所有内容,并执行 <?php ... ?> 标签内的任何内容。

在十六进制编辑器中查看该文件,看看您找到了什么。

Is there any way to fix this and detect the correct MIME type?

为了什么目的? finfo_file() 提供最佳猜测。如果你想确保文件是预期的格式,那么你需要专门设计的代码来识别和处理该格式(例如,如果用户断言文件是 JPEG,则使用 imagecreatefromjpeg() 加载它)。如果您的系统依赖于映射到上传内容中特定 mimetype 的文件扩展名,则在不匹配时拒绝该内容。正如 Marc B 已经指出的那样,大多数文件格式都是复合结构,几乎可以包含任何内容(即使是 ascii 文本文件也可以嵌入 PHP)。 IE。文件可以是有效的 JPEG 和有效的 PHP 脚本。

PHP 被设计成一种模板语言。虽然最初的想法是在 HTML:

中嵌入动态内容
<p>Hello, <?=htmlspecialchars($name)?>!</p>

...您当然可以将 PHP 代码嵌入到您想要的任何内容中; PHP 解释器不关心这个。唯一真正使文件成为 PHP 脚本的是它被提供给 PHP 解释器的事实。

finfo_file() 只是利用数据库来查找某些签名。如果您的常规 JPEG 文件恰好以 PHP 块结尾,它将被报告为图片。

总结一下:

  • 不要向 PHP 解释器提供用户上传的任何内容
  • 验证您是否拥有有效图片的一种方法是将其作为图像处理并在成功时使用结果(例如调整大小或优化它)