简体   繁体   English

PHP中的错误MIME类型检测

[英]False MIME type detection in PHP

I have this code: 我有以下代码:

<?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>

And in some cases, people have managed to fake the MIME type, it was aa .php file with application/octet-stream and the script detected it as image/jpeg. 在某些情况下,人们设法伪造了MIME类型,它是一个包含application / octet-stream的.php文件,脚本将其检测为image / jpeg。

Is there any way to fix this and detect the correct MIME type? 有什么办法可以解决此问题并检测正确的MIME类型?

Thanks! 谢谢!

it was aa .php file 这是一个.php文件

Microsoft have you well conditioned. 微软为您提供了良好的条件。 The file name is not determined by the content of the file. 文件名不是由文件的内容确定的。 Its just a convention that people often use the former to indicate the latter. 这只是人们经常使用前者来表示后者的约定。 The same convention is used within most webservers to map handlers to files. 大多数Web服务器中都使用相同的约定将处理程序映射到文件。 Hence if you are daft enough to trust the data supplied by your users and store the files within the document root then users can upload arbitrary scripts to your server. 因此,如果您足够笨拙以信任用户提供的数据并将文件存储在文档根目录下,则用户可以将任意脚本上载到服务器。

As Marc B says, finfo_file reads the file and tries to match a variable number of bytes at the beginning of the file against a database of known file formats. 正如Marc B所说,finfo_file读取文件,并尝试将文件开头的可变字节数与已知文件格式的数据库进行匹配。

I would guess that this file probably starts off looking like a JPEG. 我猜想这个文件可能看起来像是JPEG。

Once the webserver has decided to push the content through the PHP handler, PHP will ignore everything outside of, and execute anything within the <?php ... ?> tags. 一旦网络服务器决定通过PHP处理程序推送内容,PHP将忽略外部的所有内容,并执行<?php ... ?>标记内的任何内容。

Have a look at the file in a hex editor and see what you find. 在十六进制编辑器中查看该文件,然后查看发现的内容。

Is there any way to fix this and detect the correct MIME type? 有什么办法可以解决此问题并检测正确的MIME类型?

To what end? 为了什么目的 finfo_file() provides a best guess. finfo_file()提供了最佳猜测。 If you want to ensure the file is of the expected format, then you need code specifically designed to recognise and process that format (eg if user asserts file is a JPEG, load it with imagecreatefromjpeg()). 如果要确保文件具有预期的格式,则需要专门设计用于识别和处理该格式的代码(例如,如果用户断言文件是JPEG,请使用imagecreatefromjpeg()加载它)。 If your system depends on the file extensions mapping to a specific mimetype in uploaded content, reject the content if it does not match. 如果您的系统依赖于文件扩展名映射到上载内容中的特定mimetype,请拒绝该内容,如果内容不匹配。 As Marc B has already pointed out, most file formats are composite structures which can contain just about anything (even an ascii text file can have embedded PHP). 正如Marc B所指出的那样,大多数文件格式都是复合结构,几乎可以包含任何内容(即使一个ascii文本文件也可以嵌入PHP)。 Ie a file can be a valid JPEG and a valid PHP script. 即文件可以是有效的JPEG和有效的PHP脚本。

PHP was designed as if it was a template language. PHP的设计就好像它是一种模板语言一样。 While the initial idea was to embed dynamic stuff inside HTML: 最初的想法是在HTML中嵌入动态内容:

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

... you can of course embed PHP code inside anything you want; ...当然,您可以将PHP代码嵌入所需的任何内容中; the PHP interpreter doesn't care about that. PHP解释器对此并不关心。 The only thing that really makes a file a PHP script is the fact that it's been fed to the PHP interpreter. 真正使文件成为PHP脚本的唯一一件事是,该文件已被馈送到PHP解释器。

finfo_file() just makes use of a database to look for certain signatures. finfo_file()只是利用数据库来查找某些签名。 If you have a regular JPEG file that happpens to end with a PHP block it'll be reported as picture. 如果您有一个常规的JPEG文件,并且以PHP块结尾,那么它将被报告为图片。

To sum up: 总结一下:

  • Don't feed the PHP interpreter with anything uploaded by your users 不要向您的用户上传的任何内容提供PHP解释器
  • One way to validate your have a valid picture is to process it as image and use the result if successfull (eg resize or optimise it) 验证您的照片是否有效的一种方法是将其作为图像处理,并在成功后使用结果(例如调整其大小或对其进行优化)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM