Check out Scrivo

Do you want to try out Scrivo? Then here's a demo for you that does not just get your feet wet but lets you plunge right in.

Contact us

For more information, please contact us. We're happy to help you out!

Next Sep 25 Previous

Item 547236

What's the name of the PHP function to test if a file was uploaded by a user. And BTW, why do you need to do this check?

Answer

The function name is is_uploaded_file() and takes the file name of the file to test as its first argument.

Why should you use it? Well, imho there is not much use for it anymore (if you didn't turn on register_globals of course).

It's all about whether you can trust the data in the $_FILES supergobal or not. Obviously one should never trust client side data. So data from all superglobals except $_SESSION can contain client data and should be validated. But unlike $_POST, $_GET, $_REQUEST and $_COOKIE and much like $_SERVER and $_ENV, $_FILES does not contain client data only.

When a file is uploaded PHP will detect this because of the Content-type: multipart/form-data header (and a proper multipart/form-data encoded request body of course). PHP gets the file data out of the request and stores it as a file in your system's temp directory under a temporary file name. At this point a hash based on the temporary file name was created and stored internally by PHP.

Then much like PHP populates the $_POST and $_GET superglobals it starts filling in the fields of the $_FILES superglobal. But of these fields only name and type contain client data and the other fields tmp_name, error and size contain data that was generated by PHP and can be trusted.

So when working with uploaded files there are three things to distrust, and these are $_FILES["name"], $_FILES["type"] and the file itself. Three things that is_uploaded_file() will NOT check.

What does is_uploaded_files() actually do? Not much really: it's using the tmp_name field to check if the hash that was stored by PHP internally exists. And surprise, surprise, this hash always exists.

Is there really no reason to use it? The value of the tmp_name field is writable, so if an attacker succeeds in doing so you're compromised and all your password files fly out over the Internet. But how can he/she do that? If you turn on register_globals you'll definitely give him/her some ammo, but otherwise? He/she has to resort to real exploits in order to overwrite the tmp_name field in the $_FILES superglobal, exploits at a level that you can't trust PHP internal hash any more as well.

But it cannot harm if you use it and better save than sorry you'll say. And that's my problem with is_uploaded_file(): it does nothing but giving the suggestion that your save, drawing attention from those areas that you need to attend.