PHP | Security for allowing user uploads

When it comes to allowing user file uploads, you must be very careful. This is just a list of things to start with, off the top of my head:

Ensure that files cannot be executed by users

  • Set up your PHP in such a way that it will not consider using the PHP file extension in the folders where PHP files exist.
  • Make sure the permissions for the files are set correctly. If there's no need for uploaded files to have execute permissions, then why should they?

Preventing users from grabbing arbitrary files

Unless you really want them too, a user should not be able to enumerate all the files uploaded to your service. In fact, based on your description of the service there is no reason they should ever be able to download the file again.

  • Provide hard to guess unique ids in the file name. Many sites uses long, complex filenames for things as trivial as pictures in order to provide metadata, and prevent enumeration.
  • Make sure your that your system is configured to detect enumeration. A user should not be able to make thousands of incorrect guesses at the name of resource. You can do this through i.p tables, fail2ban, IDS, application, database. Depends on a lot of things and lots of ways to go.
  • If the users don't ever need to retrieve said file from your server, make sure that it is brought to a place where it cannot be accessed directly (like outside webroot.)
  • Consider hosting your files on a different server than other application parts (like the business logic and such.)

Ensuring that files do not cause issues directly for your system

You describe your service as a virus scanning service. What you are trying to do may be dangerous. It is not inconceivable that a virus might leverage the AV itself to escalate privilege.

  • Do some basic scanning to determine the validity of the file before sending to AV. Users should not be able to send severely mangled files which may crash the AV.
  • Check the headers.
  • Use programs like fileinfo.
  • Check against known file type information.
  • scan the file for obvious mangling/fuzzing attempts. For instance, a file filled with 10 thousand A characters might be testing your system.

Ensuring that the AV will not cause an issue

  • make absolutely sure you are using a trusted AV software which is fully patched and up to date.
  • Ensure that the AV software has the proper rights, and does not expose unnecessary ports.

Isolating the system in case of breach

  • Again, insure that the system holding the files has minimal rights.
  • Try using a container/jail/sandbox of some sort to limit the effectiveness of an exploit attempt.

When the file is uploaded, I would suggest to use finfo to determine what type of file it is, regardless of the file extension and perform specific actions depending on the result.

If you decide that the upload folder should be somewhere in the document root, I recommend that you should disabled execution of PHP files for that specific folder.

I would rather use a stronger hashing algorithm to rename your files combined with a random string per file. The way you describe the way you want to rename your files seems quite predictable and I as an attacker would try things like this in order to guess the file name.