4

The PHP documentation for is_uploaded_file says:

Returns TRUE if the file named by filename was uploaded via HTTP POST. This is useful to help ensure that a malicious user hasn't tried to trick the script into working on files upon which it should not be working--for instance, /etc/passwd.

It also suggests this:

For proper working, the function is_uploaded_file() needs an argument like $_FILES['userfile']['tmp_name'], - the name of the uploaded file on the client's machine $_FILES['userfile']['name'] does not work.

But as far as I know tmp_name isn't user controlled anyways, so the check shouldn't be required.

And if I use name instead of tmp_name when uploading files (for example by using copy instead of move_uploaded_file), my file upload script wouldn't actually work, as it would always move the wrong file.

My questions:

  • The comments mention that move_uploaded_file performs the is_uploaded_file check itself, it that true?
  • Is tmp_name user controlled in any way?
  • Is there a realistic scenario where is_uploaded_file is actually required when uploading a file - or when performing any other action such as reading, deleting, etc. - , as there would be a vulnerability without it? Or is the function completely useless?
tim
  • 29,018
  • 7
  • 95
  • 119

1 Answers1

3

To answer your questions:

The comments mention that move_uploaded_file performs the is_uploaded_file check itself, it that true?

It does. You can see in the source code of move_uploaded_file() that the checks it performs are (almost) the same as the ones done in the is_uploaded_file() method.

Is tmp_name user controlled in any way?

No, the user cannot control this value. It is assigned by the interpreter and is random everytime. Even if you upload the exact same file more than once, it will have a different tmp_name every time.

Is there a realistic scenario where is_uploaded_file is actually required when uploading a file - or when performing any other action such as reading, deleting, etc. - , as there would be a vulnerability without it? Or is the function completely useless?

As a PHP developer myself, I've personally never used it. Since it's already incorporated in the move_uploaded_file() method. I've never encountered a scenario where I wanted a file to be uploaded, but not moved to a location of my choosing and just remain somewhere in the temporary upload directory under a random name. I guess you could use it if you just want to display the contents of the uploaded file, but not keep it stored on your server, like the example #1 in the docs suggests. A scenario that pops into my mind is if you would run a pastebin service with upload functionality or such. You could allow the file to be uploaded, read it's contents from the temp dir, use that as input for the textarea and then immediately remove the file again from it's temporary location (or have a cleanup cronjob do that periodically).

Oldskool
  • 400
  • 1
  • 10
  • Thanks for your answer. It would be great to have an official source for tmp_name always being 100% random, but I guess that will not be possible. Regarding your last point: That would definitely be a use-case where an uploaded file is not moved, but would there be any security issue (or even a non-security issue for that matter) if `is_uploaded_file` is not called? – tim Aug 24 '16 at 09:50
  • @tim I have no official source on the tmp_name assignment. The parses seems to use an internal method to generate something, but my C knowledge is not wide enough to know if this is always unique. The point of the `is_uploaded_file` method is to check wheter the given file was uploaded via a HTTP POST request. This can help determine the user is not user other methods like $_GET or $_SESSION key to pass in a filename (if your script supports that at all). – Oldskool Aug 24 '16 at 12:04
  • Right, but `is_uploaded_file` *only* works if I pass in `tmp_name`, right? If that's the only parameter that makes sense, and if `tmp_name` is never user-controlled, I already know that that file is uploaded, so there shouldn't be a need for `is_uploaded_file`. Or am I misunderstanding something completely? – tim Aug 24 '16 at 14:18
  • @tim `is_uploaded_file` checks a local file on the server on which PHP is ran. It determines if that file ended up on the server by a HTTP POST request. It can basically be any filename, as long as it's local. So if you check a value that could potentially be altered by an attacker, it at least verified if it was POSTed to the server and not uploaded in another way (like through a backdoor), which could allow an attacker to trigger your upload handling on his custom file. So it's a very specific use case. In any reasonable script I don't see any added value. At least not in PHP5+. – Oldskool Aug 24 '16 at 15:10