【问题标题】:PHP: What is the origin of the 'type' index in $_FILES?PHP:$_FILES 中“类型”索引的来源是什么?
【发布时间】:2011-02-17 17:22:44
【问题描述】:

为了验证文件上传中允许的 mime 类型,我通常依赖 fileinfo 扩展名,但由于该扩展名或 magic database 并不总是可用,我虽然使用与每个文件关联的类型 index $_FILES 超全球。

所以我的问题是,这个索引是从哪里来的?我怀疑它要么来自浏览器(如果是这种情况,它可以被伪造),或者很可能来自网络服务器(或 PHP)——如果是这样的话:它只是 mime 类型映射的扩展还是是真的吗?

【问题讨论】:

    标签: php security apache file-upload webserver


    【解决方案1】:

    它是浏览器通过解释文件扩展名提供的文件的MIME类型。所以你是对的,这可以由客户伪造。

    【讨论】:

    【解决方案2】:

    这不是您问题的答案,但 @BoldClock 已经提供了答案。

    首先,我不会使用它来验证您的文件,它不是 100% 可靠的,而是使用文件函数和一些二进制转换函数扫描文件以查找其 Magic Number

    这听起来可能很复杂,但实际上并没有那么难。

    每个文件都应该有一组幻数,允许您通过读取前 4 / 8 / 16 个字节的数据来确定文件类型。

    PDF 文件以“%PDF”(十六进制 25 50 44 46)开头。

    您还必须实施其他检查,例如:Microsoft Office PPT / DOC / XLS 都具有相同的字节码,因此您还需要验证扩展。

    记住安全第一。

    【讨论】:

    • 很高兴知道这一点。例如,如果.php 文件具有以下内容会发生什么:%PDF<?php destroyServer(); ?>?
    • Alix,它不是这样工作的,数据是二进制的,写入文件的头部,内容不可见。
    【解决方案3】:

    由客户端在构造 POST 请求时定义。文件只能以multipart/form-data body 出现,如下所示:

    --BoUnDaRy02984
    Content-Disposition: form-data; name="textfield1"
    Content-Type: text/plain; charset=utf-8
    Content-Transfer-Encoding: quoted-printable
    
    Joe owes =80100.
     --BoUnDaRy02984
    Content-Disposition: form-data; name="file2"; filename="C:\tmp\file.doc"
    Content-Type: application/ms-word
    Content-Transfer-Encoding: base64
    Content-Length: 32
    
    VGhpcyB3b3VsZCBiZSB0aGUgdGV4dAo=
     --BoUnDaRy02984
    

    PHP 不会解释 multipart/ 的所有可能变体,但它会通过 filename= 属性的存在来检测文件上传,并将 Content-Type: 字段逐字用于 $_FILES[*][type]。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 2021-07-20
      • 2021-03-14
      • 2017-12-12
      相关资源
      最近更新 更多