Stop People Uploading Malicious PHP Files Via Forms

How to prevent every malicious file upload on my server? (check file type)?

You're going to need to validate that the uploaded file is actually the type that the extension indicates it is. You can do that through various methods, probably the easiest is via the file command. I don't know if it has an API. You can try it out yourself in the shell. For your example of file.exe that was renamed to file.jpg before being uploaded, run file file.jpg and it will print out something telling you it's an executable. It can be fooled, however.

I'm guessing you don't know much about Linux file permissions if you think .exe means it will be executed. On linux, only the execute bit in the file permissions determine that -- you can execute any file, regardless of extension, if that bit is turned on. Don't set it on any uploaded files and you should be safe from executing them. You may still be serving them back up to your site's visitors, so it could still be a vector for XSS attacks, so watch out for that.

Security measures when uploading files via php

If all you're doing is acting as a file store, what do you care? You're not executing the files or looking at them in any way, are you?

A file extension has nothing to do with how safe a file is.

Edit: What you would really do is store your filename in a database along with a checksum of the full path. Then your script would be passed that checksum, which would then look up in your database, and then you'd return the file somehow. Don't use your webserver to serve up the file, else (as you say in comments below) you could accidentally execute an uploaded PHP file.

Completely secure php file upload?

There are 1000 answers why not, but imagine the following: I could upload a .htaccess file to make some other extensions being handled by PHP, thus I would be able to get around your "only .php files are executable". An very easy one :)

Is php fileinfo sufficient to prevent upload of malicious files?

I usually invoke ClamAV when accepting files that can be shared. With PHP, this is rather easily accomplished with php-clamav.

One of the last things you want to do is spread malware around the globe :)

If you can, do this in the background after a file is uploaded, but before making it public. A quirk with this class is that it can load the entire ClamAV virus definition database into memory, which will almost certainly stink if PHP is running under Apache conventionally (think on the order of +120 MB of memory per instance).

Using something like beanstalkd to scan uploads then update your DB to make them public is a very good way to work around this.


I mentioned this only because the other answers had not, in no way did I intend this to be a complete solution. See the other answers posted here, this is a step you should be finishing with. Always, always, always sanitize your input, make sure it's of the expected type, etc (did I mention that you should read the other answers too?)

Protecting PHP files from being called by other websites

As suggested by DaveRandom, I finally used a cookie based authentication technique to avoid calling of PHP by other websites.

The server first sets a access code for each valid client. This access code is checked at the beginning of my PHP file.

Cookie is set a max time limit of 5 hrs and cookie is destroyed on window close. This is working pretty fine for me.

Please mention if there is any glitches in this part !!

Security threats with uploads

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 example.com/uploads/malicious.php 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.

Secure PHP File Upload Script

a late response, but i think your script should be based on this:
http://blog.insicdesigns.com/2009/01/secure-file-upload-in-php-web-applications/

it covers all aspects of security and explains all valid points. I hope this helps.

EDIT: The above link is dead, here is a cached version of that article.



Related Topics



Leave a reply



Submit