众所周知,在php($_FILES[...]['type'])中不信任通过文件上传发送的mime类型是由http客户端发送的,因此可能是伪造的。
对于http客户端发送的文件名($_FILES[...]['name'])也有类似的警告,该文件名可能包含潜在的危险字符。
但是,我看不到文件大小($_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']指向的实际文件推断出来的,因此总是可信的?

最佳答案

根据@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
1242total_bytes被分配给
1270目标变量名file_size分配给...[size]
1275lbuffile_sizelbuf中包含的名称注册
因此,毫无疑问,唯一分配给...[size]的变量是写入路径分配给$_FILES[...]['size']的临时文件的实际字节数。
据我所见,没有办法伪造$_FILES[...]['tmp_name']属性。

10-04 23:39