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类型,它是一个带有应用程序/八位字节流的.php文件,脚本将其检测为图像/jpeg。

有没有办法解决这个问题并检测正确的MIME类型?

谢谢!

这是一个.php文件

Microsoft你身体状况良好。文件名不是由文件的内容确定的。这只是人们经常使用前者来表示后者的惯例。大多数 Web 服务器中使用相同的约定将处理程序映射到文件。因此,如果您足够愚蠢地信任用户提供的数据并将文件存储在文档根目录中,那么用户可以将任意脚本上传到您的服务器。

正如Marc B所说,finfo_file读取文件并尝试将文件开头的可变字节数与已知文件格式的数据库进行匹配。

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

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

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

有没有办法解决这个问题并检测正确的MIME类型?

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

PHP被设计成一种模板语言。虽然最初的想法是在HTML中嵌入动态内容:

<p>Hello, <?=htmlspecialchars($name)?>!</p>

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

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

总结一下:

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