我正在处理一个脚本,该脚本将处理用户上载到服务器的内容,并且我想知道,作为附加的安全层:
有没有一种方法可以检测文件的真实扩展名/文件类型,并确保它不是被其他扩展名掩盖的其他文件类型?
每种类型/扩展名都有字节戳或某些唯一标识符吗?
我希望能够检测到有人没有在他们上传的文件上应用其他扩展名。
不是,不是。
您将需要读取每个文件的前几个字节,并将其解释为已知文件类型的有限集合的标头。大多数文件具有不同的文件头,在MP3的前几个字节或前几个千字节中都有某种元数据。
您的程序将只需尝试为每种接受的文件类型解析文件。
对于我的程序,我在try-catch块中将上传的图像发送到imagemagick,如果它爆炸了,那么我猜它是不好的图像。应该将其视为不安全的,因为我正在将任意(用户提供的)二进制数据加载到外部程序中,该外部程序通常是攻击向量。在这里,我相信imageMagick不会对我的系统做任何事情。
我建议您为打算使用的重要文件类型编写自己的处理程序,以避免任何攻击媒介。
编辑:我在PHP中看到有一些工具可以帮助您。
此外,MIME类型是用户浏览器要求的文件类型。读取它们并在您的代码中对其进行操作既方便又有用,但这不是一种安全的方法,因为任何向您发送错误文件的人都会轻易地伪造MIME标头。这是一种前线防御,可以防止期望JPEG的代码进入PNG,但是如果有人在.exe中嵌入病毒并将其命名为JPEG,则没有理由不假装MIME类型。
检查MIME类型是否足够简单?我假设更改文件的扩展名不会更改其MIME类型?
MIME类型是否足以作为此处的指示?
感谢到目前为止的所有答复。
检查MIME类型是否足够简单?我假设更改文件的扩展名不会更改其MIME类型? MIME类型是否足以作为此处的指标?
实际上取决于使用方式。
PHP有两种读取文件内容的方法来确定其MIME类型,这取决于您使用的PHP版本:
如果正在运行PHP 5.3+,请查看Fileinfo functions
$finfo = finfo_open(FILEINFO_MIME);
$type = finfo_file($finfo, $filepath);
finfo_close($finfo);
或者,检查mime_content_type以获得较旧的版本。
$type = mime_content_type($filepath);
请注意,如果您要真正安全,仅验证文件类型是不够的。例如,有人可以上传有效的JPEG文件,该文件利用了普通渲染器中的漏洞。为了防止这种情况,您需要一个维护良好的病毒扫描程序。
PHP具有superglobal $_FILES,其中包含诸如大小和文件类型之类的信息。看起来该类型是从某种标题(而不是扩展名)中获取的,但我可能是错的。
w3schools site上有一个示例。
我将测试是否有机会欺骗它。
更新:
其他人可能都知道这一点,但是$ _FILES可能会被欺骗。我可以这样确定:
$arg = escapeshellarg( $_FILES["file"]["tmp_name"] );
system( "file $arg", $type );
echo "Real type: " . $type;
它基本上使用Unix的file命令。可能有更好的方法,但是我已经有一段时间没有使用PHP了。我通常会尽可能避免使用系统命令。
仍然可以伪造。我将确保您不能(或不能)自动运行上传到服务器的文件。
我也会有一个virus/spy ware scanner,并让它为您完成工作。
如果您更改了扩展名,也可以使用下面的代码为您提供MIME类型,然后
$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo $mime = finfo_file($finfo, $_FILES['userfile']['tmp_name']);
finfo_close($finfo);
Windows用户:只需编辑php.ini并取消注释此行:
extension=php_fileinfo.dll
记住要重新启动Apache以使新的php.ini生效。
在* nix中,文件的前两个字节告诉您(请参阅“幻数”)。在Windows中,...有时是正确的(“标题信息”)。最终是美国依赖。
可执行文件通常在前几个字节上带有“签名”;我发现很难真正确定文件的真正类型。
您希望使用哪种文件类型?也许您可以检查它是否符合您的期望,然后拒绝其他所有内容。
[其他人已经提到FileInfo,我认为这是正确的解决方案,但是我将添加此信息,以防万一您由于某种原因无法使用该文件。大多数(全部?)* nix发行版都包含一个称为file
的命令,该命令在文件上运行时将输出其类型。它可以切换为以人类可读格式(默认)或MIME类型输出。您可以让脚本在上载的文件上调用此程序并读取结果。同样,这不是首选方法。如果您使用的是Windows,则可以通过Cygwin使用此实用程序。