Php 美元文件[…][';大小';]可以伪造吗?

Php 美元文件[…][';大小';]可以伪造吗?,php,security,file-upload,Php,Security,File Upload,关于不信任通过PHP中的文件上载发送的MIME类型,有一个众所周知的警告($\u FILES[…]['type']),因为它是由HTTP客户端发送的,因此可能是伪造的 文件名($\u FILES[…]['name'])也有类似的警告,它是由HTTP客户端发送的,可能包含潜在的危险字符 但是,我看不到文件大小($\u FILES[…]['size'])是如何伪造的,因为它似乎不是请求负载的一部分,至少我在Chrome的开发工具中看不到它,其中负载看起来像: ------WebKitFormBoun

关于不信任通过PHP中的文件上载发送的MIME类型,有一个众所周知的警告(
$\u FILES[…]['type']
),因为它是由HTTP客户端发送的,因此可能是伪造的

文件名(
$\u FILES[…]['name']
)也有类似的警告,它是由HTTP客户端发送的,可能包含潜在的危险字符

但是,我看不到文件大小(
$\u FILES[…]['size']
)是如何伪造的,因为它似乎不是请求负载的一部分,至少我在Chrome的开发工具中看不到它,其中负载看起来像:

------WebKitFormBoundarytYAQ3ap4cmAB46Ek
Content-Disposition: form-data; name="picture"; filename="picture.jpg"
Content-Type: image/jpeg
原始文件名和MIME类型按预期显示在这里,但没有大小参数的迹象

尽管如此,我还是偶然发现了Symfony的
UploadedFile
实现,它将文件大小视为源于客户端的,因此不可信:

返回文件大小。 它是从上传文件的请求中提取的。则不应将is视为安全值

文件大小是否可以是请求负载的一部分,因此可以伪造,或者它总是从
$\u FILES[…]['tmp\u name']
指向的实际文件推断出来,因此总是可信的?

请看,简短的回答是,不!这个尺寸不能伪造

唯一不可信的部分是浏览器提供的大小和图像类型

<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<input type="file" name="pictures" accept="image/png"/>

在这两种情况下,都可能欺骗浏览器,因此必须实现后端解决方案以进一步验证大小和图像类型

还要感谢评论部分的@Andy Gee改进了这个答案

$\u文件[i]['type']由客户端发送,因此不应信任。使用mime_内容_类型($_文件[i]['tmp_名称]])来确保

或者使用我的无耻插件:

正如所建议的,我在中检查了PHP源代码

定义
[size]
属性所涉及的行包括:

[1042] wlen = write(fd, buff, blen);
       ...
[1056] total_bytes += wlen;
       ....
[1242] ZVAL_LONG(&file_size, total_bytes);
       ...
[1270] snprintf(lbuf, llen, "%s[size]", param);
       ...
[1275] register_http_post_files_variable_ex(lbuf, &file_size, ...
我将其翻译为:

  • 临时文件以
    wlen
    size块写入
  • 在每次迭代中,
    wlen
    被添加到
    total\u字节中
  • 总字节数
    分配给
    文件大小
    zval
  • 目标变量名
    …[size]
    分配给
    lbuf
  • file\u size
    lbuf
    …[size]
因此,毫无疑问,唯一分配给
$\u文件[…]['size']
的变量是写入临时文件的实际字节数,该临时文件的路径分配给
$\u文件[…]['tmp\u name']


据我所知,没有办法伪造
大小
属性

检查PHP源代码,它是实际的缓冲区大小,因此应该是“安全的”可以通过更改发送的文件数据量来伪造。@Dagon您能给我一个相关源代码的链接吗?@Gumbo我不明白您的意思。
$\u文件[I]['type']
是由客户端发送的,因此不应被信任。请使用
mime\u内容\u类型($\u文件[i]['tmp\u名称])
确认。@AndyGee谢谢,我添加了更多详细信息