Php finfo 检测 php 文件为 jpeg

Php finfo detecting php file as a jpeg

我试着写一个上传表单,我希望用户只发送图像或 pdf 文件。为了检测 mime 类型,我使用 finfo,但在这里举个例子很容易搞砸他

<?php

$cnt ='<form action="" method="get">\x0aCommand: <input type="text" name="cmd" /><input type="submit" value="Exec" />\x0a</form>\x0aOutput:<br />\x0a<pre><?php passthru($_REQUEST["cmd"], $result); ?></pre>\x0a';
echo $cnt."\n";
$finfo = new \finfo(FILEINFO_MIME);
echo $finfo->buffer($cnt) . "\n"; // text/plain; charset=us-ascii

$cnt ="\xff\xd8\xff\xe0\x0a".$cnt; // adding random utf8 char at the begining
echo $cnt."\n";
$finfo = new \finfo(FILEINFO_MIME);
echo $finfo->buffer($cnt) . "\n";  // image/jpeg; charset=iso-8859-1

有没有人知道如何正确地做到这一点?

更新:

好吧,让我们揭开魔术的面纱:finfo 像许多工具或工具(例如 unix 上的 cmd file)使用“魔术 table”来找出哪种文件就是它。 Look at those example

短版 finfo 在流中搜索一系列特定字节,如果找到,它 return 与这些数字关联的 mime 类型。

要欺骗它,您只需要在文件中包含这些字节...

它没有回答关于如何正确找出的问题...

这是获取图像文件扩展名的方法:

$path = $_FILES['image']['name'];
$ext = pathinfo($path, PATHINFO_EXTENSION);

这是 Html 代码:

<form action="" method="POST">
        <input type="file" name="" id="" accept="application/pdf,image/jpeg">
<input type="submit" name="submit" value="">
</form>

为什么要使用 Finfo?

有几种提高文件安全性的方法;

图像最有效的方法是将PHP中的图像转换为另一种格式,例如从JPEG到PNG,然后重新加载(在PHP内存中)并将其转换回所需格式。

如果原始图像代码格式不正确(如您所举),则无法成功转换;这将被 PHP 检测到(如 false 或类似)。

您还可以执行其他并行测试,例如使用 getimagesize 检查返回的值是否与原始文件和转换文件等中的预期值相关。

如果是一张图片,一个模糊的过程可能是:

  • 检查文件 finfo MIME 类型(就像您已经做的那样)
  • 将文件转换为另一种格式(即 JPG --> PNG )。
  • 测试文件尺寸(getimagesize)。记住这些。
  • 将 PHP 内存中的文件数据转换回原始格式(即 PNG --> JPG)。
  • 测试这些文件尺寸 (getimagesize) 是否与上面的值进行比较。

这不适用于 PDF,但可以确保图像是真实的,并且还可以通过将 JPG 图像转换为 PNG 然后再转换回 JPG 来从 JPG 图像中删除潜在危险的元数据。

This post 可能对您的 PDF

也有用

本质上,文件只是数据块,在这个程度上,MIME 类型检查(孤立地)永远不会是保证文件“真实”的可靠方式。 MIME 类型就像一本书的封面;封面看起来像一部文学杰作,但直到你翻过书页发现它全是 1980 年代的色情作品,你才能确定。

一些有用的链接: