可以伪造$ _FILES [...] ['尺寸']吗?

时间:2014-07-03 23:25:56

标签: php security file-upload

有一个众所周知的警告,即不相信通过PHP($_FILES[...]['type'])中的文件上传发送的MIME类型,因为这是由HTTP客户端发送的,因此可以伪造。

对于文件名($_FILES[...]['name'])有一个类似的警告,它由HTTP客户端发送,可能包含潜在的危险字符。

但是,我无法看到文件大小($_FILES[...]['size'])是如何伪造的,因为它似乎不是请求有效负载的一部分,至少我看不到它在Chrome中的开发工具中,有效负载如下所示:

------WebKitFormBoundarytYAQ3ap4cmAB46Ek
Content-Disposition: form-data; name="picture"; filename="picture.jpg"
Content-Type: image/jpeg

原始文件名和MIME类型符合预期,但没有尺寸参数的标志。

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

UploadedFile::getClientSize()

  

返回文件大小。   它是从上传文件的请求中提取的。那么就不应该被认为是安全的价值。

文件大小可以是请求有效负载的一部分,因此是伪造的,还是始终从$_FILES[...]['tmp_name']指向的实际文件中推断出来,因此始终可信?

2 个答案:

答案 0 :(得分:4)

根据@Dagon in the comments的建议,我在rfc1867.c中检查了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, ...

我翻译为:

  • 1042临时文件以wlen大小块
  • 编写
  • 1056在每次迭代中,wlen都会添加到total_bytes
  • 1242 total_bytes已分配给file_size zval
  • 1270目标变量名称...[size]已分配给lbuf
  • 1275 file_sizelbuf...[size]
  • 中包含的名称注册

毫无疑问,唯一分配给$_FILES[...]['size']的变量是写入临时文件的实际字节数,其路径分配给$_FILES[...]['tmp_name']

据我所见,无法伪造size属性

答案 1 :(得分:1)

不。我不相信$_FILES[]['size']数组可以显示错误信息。也许那些关注它的人可能指的是压缩相关的场景。其中实际文件可能被压缩,直到它不反映文件的实际值。

就尺寸而言,唯一不值得信任的部分是MAX_FILE_SIZE属性

<input type="hidden" name="MAX_FILE_SIZE" value="30000" />