Viewed   77 times

I am allowing users to upload files to my server. What possible security threats do I face and how can I eliminate them?

Let's say I am allowing users to upload images to my server either from their system or from net. Now to check even the size of these images I have to store them in my /tmp folder. Isn't it risky? How can I minimize the risk?

Also let's say I am using wget to download the images from the link that the users upload in my form. I first have to save those files in my server to check if they actually are images. Also what if a prankster gives me a URL and I end up downloading an entire website full of malware?



First of all, realize that uploading a file means that the user is giving you a lot of data in various formats, and that the user has full control over that data. That's even a concern for a normal form text field, file uploads are the same and a lot more. The first rule is: Don't trust any of it.

What you get from the user with a file upload:

  • the file data
  • a file name
  • a MIME type

These are the three main components of the file upload, and none of it is trustable.

  1. Do not trust the MIME type in $_FILES['file']['type']. It's an entirely arbitrary, user supplied value.

  2. Don't use the file name for anything important. It's an entirely arbitrary, user supplied value. You cannot trust the file extension or the name in general. Do not save the file to the server's hard disk using something like 'dir/' . $_FILES['file']['name']. If the name is '../../../passwd', you're overwriting files in other directories. Always generate a random name yourself to save the file as. If you want you can store the original file name in a database as meta data.

  3. Never let anybody or anything access the file arbitrarily. For example, if an attacker uploads a malicious.php file to your server and you're storing it in the webroot directory of your site, a user can simply go to to execute that file and run arbitrary PHP code on your server.

    • Never store arbitrary uploaded files anywhere publicly, always store them somewhere where only your application has access to them.

    • Only allow specific processes access to the files. If it's supposed to be an image file, only allow a script that reads images and resizes them to access the file directly. If this script has problems reading the file, it's probably not an image file, flag it and/or discard it. The same goes for other file types. If the file is supposed to be downloadable by other users, create a script that serves the file up for download and does nothing else with it.

    • If you don't know what file type you're dealing with, detect the MIME type of the file yourself and/or try to let a specific process open the file (e.g. let an image resize process try to resize the supposed image). Be careful here as well, if there's a vulnerability in that process, a maliciously crafted file may exploit it which may lead to security breaches (the most common example of such attacks is Adobe's PDF Reader).

To address your specific questions:

[T]o check even the size of these images I have to store them in my /tmp folder. Isn't it risky?

No. Just storing data in a file in a temp folder is not risky if you're not doing anything with that data. Data is just data, regardless of its contents. It's only risky if you're trying to execute the data or if a program is parsing the data which can be tricked into doing unexpected things by malicious data if the program contains parsing flaws.

Of course, having any sort of malicious data sitting around on the disk is more risky than having no malicious data anywhere. You never know who'll come along and do something with it. So you should validate any uploaded data and discard it as soon as possible if it doesn't pass validation.

What if a prankster gives me a url and I end up downloading an entire website full of malware?

It's up to you what exactly you download. One URL will result at most in one blob of data. If you are parsing that data and are downloading the content of more URLs based on that initial blob that's your problem. Don't do it. But even if you did, well, then you'd have a temp directory full of stuff. Again, this is not dangerous if you're not doing anything dangerous with that stuff.

Saturday, August 13, 2022

If you don’t validate and/or escape the input values properly, anyone can execute arbitrary commands on your system in behalf of the user that runs PHP.

For command arguments, there is escapeshellarg. Make sure you escape the whole argument value, e.g.:

$cmd='echo '.escapeshellarg('html + '.$html).' | htmldoc --format pdf > '.escapeshellarg($filename);
$cmd='/usr/bin/convert '.escapeshellarg($docs).' '.escapeshellarg($filename);
// […]
$cmd='sendfax -n -m -w -i '.escapeshellarg($id).' -o JohnDoe -D -S "" -s "us-leg" -f '.escapeshellarg($from).' -d '.escapeshellarg($to).' '.escapeshellarg($doc_list);
Friday, December 9, 2022

a standard form will suffice for the upload just remember to include the mime in the form. then you can use $_FILES[''] to reference the file.

then you can check for the filename provided and see if it exists in the file system using file_exists() check for the file name OR if you don't need to keep the old file, you can use perofrm the file move and overwrite the old one with the new from the temporary directory

// this assumes that the upload form calls the form file field "myupload"
$name  = $_FILES['myupload']['name'];
$type  = $_FILES['myupload']['type'];
$size  = $_FILES['myupload']['size'];
$tmp   = $_FILES['myupload']['tmp_name'];
$error = $_FILES['myupload']['error'];
$savepath = '/yourserverpath/';
$filelocation = $svaepath.$name;
// This won't upload if there was an error or if the file exists, hence the check
if (!file_exists($filelocation) && $error == 0) {
    // echo "The file $filename exists";
    // This will overwrite even if the file exists
    move_uploaded_file($tmp, $filelocation);
// OR just leave out the "file_exists()" and check for the error,
// an if statement either way

Tuesday, August 9, 2022

The file will always end up in the temporary directory first while the upload completes, even before you're able to work with the uploaded file. You get all the file's chunks before, and then it get rebuilt in the /tmp directory by default. So no, there's no "pass-through". But I guess you could re-upload directly from the temporary directory afterwards instead of moving it to another working directory.

Thursday, November 10, 2022

I think the problem is very similar to the one described here. So you might want to look at the accepted answer.

Apart from this, I have two additional ideas I would like to share:

Delete the client

It really depends on how you use client ids. But you could, of course, delete a client - this would make the refresh process fail.

Deactivate the user

From the documentation:

if you inject a UserDetailsService or if one is configured globally anyway (e.g. in a GlobalAuthenticationManagerConfigurer) then a refresh token grant will contain a check on the user details, to ensure that the account is still active

So if you are using a UserDetailsService and your token is associated with a user you could deactivate the user to make the refresh process fail.

Saturday, November 5, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :