有一个众所周知的警告,即不相信通过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
实现,它认为文件大小是客户端的,因此不可信:
返回文件大小。 它是从上传文件的请求中提取的。那么就不应该被认为是安全的价值。
文件大小可以是请求有效负载的一部分,因此是伪造的,还是始终从$_FILES[...]['tmp_name']
指向的实际文件中推断出来,因此始终可信?
答案 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, ...
我翻译为:
wlen
大小块wlen
都会添加到total_bytes
total_bytes
已分配给file_size
zval ...[size]
已分配给lbuf
file_size
以lbuf
,...[size]
毫无疑问,唯一分配给$_FILES[...]['size']
的变量是写入临时文件的实际字节数,其路径分配给$_FILES[...]['tmp_name']
。
据我所见,无法伪造size
属性。
答案 1 :(得分:1)
不。我不相信$_FILES[]['size']
数组可以显示错误信息。也许那些关注它的人可能指的是压缩相关的场景。其中实际文件可能被压缩,直到它不反映文件的实际值。
就尺寸而言,唯一不值得信任的部分是MAX_FILE_SIZE
属性
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />