PHP文件上传:基于mime或扩展名的验证


PHP file upload: mime or extension based verification?

当我尝试处理文件上传时,我应该基于文件MIME类型还是文件扩展名运行验证?

什么是Pros &这两种文件验证方式的缺点?

还有,还有其他需要注意的安全问题吗?

在这些日子里,我依赖于MIME类型,但在这个帖子中得到最多好评的答案

文件上传问题:

永远不要依赖浏览器提交的MIME类型!

好了,所以对于所有在这里大喊"螺丝扩展,检查MIME!FILEINFO RLZ!",我准备了一些教程:

  1. 下载我画的漂亮的php logo
  2. 视图。很漂亮,不是吗?
  3. 重命名为whatever_you_like.php
  4. 让它通过你所有的mime类型检查器
总之,永远不要永远不要依赖MIME类型。你的web服务器不关心MIME类型,它决定了EXTENSION做什么,最终被否决的@Col。Shrapnel的答案实际上是正确的。任何检查MIME的东西提供给你的信息都是绝对与你的web服务器在执行时无关。

EDIT: not-as-uncommon-code-as-you'd-want-it-to-be打开一个网站,接受这种类型的攻击:

<?php
$mimetype = mime_content_type($_FILES['file']['tmp_name']);
if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) {
   move_uploaded_file($_FILES['file']['tmp_name'], '/whatever/something/imagedir/' . $_FILES['file']['name']);
   echo 'OK';
} else {
    echo 'Upload a real image, jerk!';
}

为了准确地确定上传的内容,您不检查文件扩展名,也不检查浏览器发送的mime类型。

在*nix环境中,您已经获得用于检查给定文件的mime类型的实用程序,通常位于magic中。Mime文件(/usr/share/magic. conf)Mime或类似的东西,取决于您的设置)。

从魔术复制/粘贴。所以你可以看到它是如何工作的:

# Magic data for KMimeMagic (originally for file(1) command)
#
# Note on adding additional MIME types:
#
# [RFC2045,RFC2046] specifies that Content Types, Content Subtypes, Character
# Sets, Access Types, and conversion values for MIME mail will be assigned and
# listed by the IANA.
# http://www.iana.org/assignments/media-types/
#
# Any unregistered file type should be listed with a preceding x-, as in
# application/x-foo (RFC2045 5.1), or a x., as in application/x.foo (RFC4288
# 4.3).  Any non x-prefixed type should be registered with IANA and listed at
# the above address.  Any other behavior is a MIME standards violation!
#
# It is preferred that when a registered MIME type exists, that
# the registered Content-Type and Subtype be used to refer to a file of
# that type, so don't use application/x-zip when application/zip is
# registered.
#
# If an active RFC suggests that a MIME registration for a new type is in
# progress, make a note of it pointing to that RFC.
#
# The format is 4-5 columns:
#    Column #1: byte number to begin checking from, ">" indicates continuation
#    Column #2: type of data to match
#    Column #3: contents of data to match
#    Column #4: MIME type of result
#    Column #5: MIME encoding of result (optional)

我将为您提供一个链接,该链接将帮助您在PHP中进一步实现(一旦完成,实际上只有2行代码)。

如果你不能让它工作后,所有这些,在这里发表评论,我将提供完整的代码需要安全检测已上传的内容。

Fileinfo

None适合准确查找文件类型。原因如下:*扩展-用户可以很容易地通过重命名文件更改扩展名。* Mime类型-更改Mime类型,一些附加组件/扩展可以做到这一点,因为它来自客户端(所以可以在发送到服务器之前更改),而不是由服务器生成。

现在进行验证,问题的答案取决于为什么要验证文件类型。

大多数情况下,我们需要确保上传的文件不会被执行。出于这个原因,您需要确定服务器如何处理/执行文件。-如果你的服务器检查扩展名验证,你还需要验证你没有存储一个扩展名可以执行的文件。-如果您的服务器使用mime-types,请注意客户端发送的mime类型和服务器对同一文件使用的mime类型可能不同。因此,请使用您的服务器用于查找mime类型的相同逻辑。

Mime-type不是可靠的源,因为它从浏览器发送(任何人都可以手动创建HTTP请求)。PHP不检查扩展和mine类型是否等价(http://ru.php.net/manual/en/features.file-upload.post-method.php)。你可以用文件名"image.php"和mime类型"image/gif"来强调HTTP请求。

如果你想把上传的文件保存到硬盘上,然后让公众访问这个文件,请使用扩展名进行验证。