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.

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

Thanks!


it was aa .php file

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

I would guess that this file probably starts off looking like a 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.

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?

To what end? finfo_file() provides a best guess. 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()). If your system depends on the file extensions mapping to a specific mimetype in uploaded content, reject the content if it does not match. 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). Ie a file can be a valid JPEG and a valid PHP script.


PHP was designed as if it was a template language. While the initial idea was to embed dynamic stuff inside HTML:

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

... you can of course embed PHP code inside anything you want; the PHP interpreter doesn't care about that. The only thing that really makes a file a PHP script is the fact that it's been fed to the PHP interpreter.

finfo_file() just makes use of a database to look for certain signatures. If you have a regular JPEG file that happpens to end with a PHP block it'll be reported as picture.

To sum up:

  • Don't feed the PHP interpreter with anything uploaded by your users
  • 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)
  • 链接地址: http://www.djcxy.com/p/45510.html

    上一篇: 无法使用php下载文件时浏览网站

    下一篇: PHP中的错误MIME类型检测