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