There's a well-known caveat about not trusting the MIME type sent via file upload in PHP ($_FILES[...]['type']
) as this is sent by the HTTP client and could therefore be forged.
There's a similar caveat for the file name ($_FILES[...]['name']
), which is sent by the HTTP client and could contain potentially dangerous characters.
However, I can't see how the file size ($_FILES[...]['size']
) could be forged, as it does not seem to be part of the request payload, at least I can't see it in the dev tools in Chrome, where the payload looks like:
------WebKitFormBoundarytYAQ3ap4cmAB46Ek
Content-Disposition: form-data; name="picture"; filename="picture.jpg"
Content-Type: image/jpeg
Original file name and MIME type are here as expected, but no sign of a size parameter.
Still, I've just stumbled upon Symfony's UploadedFile
implementation, that considers the file size as client-originated and therefore not trustable:
Returns the file size. It is extracted from the request from which the file has been uploaded. Then is should not be considered as a safe value.
Can the file size be part of the request payload, and therefore be forged, or is it always inferred from the actual file pointed to by $_FILES[...]['tmp_name']
, and therefore always trustable?
Nope. I don't believe the
$_FILES[]['size']
array can display false information. Maybe those who are concerned by it, may be referring to compression-related scenarios. Wherein the actual file may be compressed, to the point it does not reflect the file's real value.As far as the size is concerned, the only part not to be trusted is the
MAX_FILE_SIZE
attribute<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
As suggested by @Dagon in the comments, I checked the PHP source in rfc1867.c.
The lines involved in defining the
[size]
attribute are:Which I translate as:
wlen
size chunkswlen
is added tototal_bytes
total_bytes
is assigned to thefile_size
zval...[size]
is assigned tolbuf
file_size
is registered under the name contained inlbuf
,...[size]
So without doubt, the only variable ever assigned to
$_FILES[...]['size']
is the actual number of bytes written to the temporary file whose path is assigned to$_FILES[...]['tmp_name']
.As far as I can see, there is no way to forge the
size
attribute.