7

My Situation:

I am creating a web application with PHP which allows users to scan their files for viruses. It allows the user to upload their files via the html "file" input type or via a URL. I have successfully built the html and PHP side of things and users are able to successfully upload files onto my server. I am using windows server 2012 R2 with IIS as my server.

My Question:

As far as I am aware, There is little to no security in place (both script and server side) to avoid security/attack vulnerabilities on my website or yet worse, on the server its self. I am aware that attackers could potentially upload and executed files that can hack my server. So, What steps can I take to try and eliminate these issues.

Things I Am Aware Of:

Due to the research I conducted, it is to my understanding that I could potentially do the following to strengthen my self, however these are all theories, and I have no idea how to actually put them in place (hence why I am asking):

  • Restriction on file types (Yes I could potentially block .php files, but as an example - I cannot block common .exe's as the user would most likely scan a executable) What is the correct balance for this sort of service, as limiting too many file types just removes usability

  • Storing uploaded files in a different drive - My site directory is in the C drive and I have an empty D drive I could use. How do I disable the server from executing anything in the specific drive? How do I stop Hackers from navigating to that drive and executing the uploaded files?

Things I have Tried:

  • I have Created a function to rename the file uploaded to a md5 hash of it, with a unique ID at the beginning, so therefore the user cannot identify the file easily.
  • Limited file type to remove .php uploads? Perhaps there are others which would be valid for my purpose?

Conclusion:

So essentially, as well as answers to the minor questions above. I am looking for a list of actions I can take to strenghten the application and server, to eliminate any possible threats. Thanks

Code:

As a side note, below you can see my code. Just in case you spot anything serious in there. Or there are extra security which can be added to the code:

PHP:

$upload_directory = "uploads/";
    $uploaded_file = $upload_directory . basename($_FILES["file"]["name"]);
    $upload_ok = 1;

    $image_file_type = pathinfo($uploaded_file, PATHINFO_EXTENSION);

    // check for files bigger then 8mb
    if($_FILES["file"]["size"] > 8388608){
        print "your file exceeds 8mb";
        $upload_ok = 0;
        exit();
    }

    // only allow certain file types
    if($image_file_type != "jpg" && $image_file_type != "png" && $image_file_type != "jpeg" && $image_file_type != "gif"){
        print "invalid file type";
        $upload_ok = 0;
        exit();
    }

    // upload it
    if($upload_ok != 0){
        move_uploaded_file($_FILES["file"]["tmp_name"], $uploaded_file);
    }

HTML:

<form method="post" action="index.php" enctype="multipart/form-data">

    <label>Select Desired File</label><br>
    <input type="file" name="file" id="file">

    <input type="submit" name="submit" value="Scan File"> 
</form> 
  • Don't use a folder called uploads underneath the webroot, that's for sure! You should use a folder not accessible via URL to the webserver. If you're uploading to an "uploads/" folder inside your webroot then I could just upload a payloaded php file and browse to yoursite.com/uploads/mynaughtyfile.php. – AlexH Feb 20 '15 at 17:07
  • Same question on Stack Overflow – Gumbo Feb 20 '15 at 17:08
4

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.
3

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.

  • Thanks for that. Will try disabling execution and using my own series of hashing algorithms :D – Jimmy Mar 2 '15 at 14:27
-3

One minor technique I used is as follows. I had a chunk of C code that I wrote that looks at the first 4-8 bytes of any file and identifies the type. Because C was close to PHP, I ported that routine to PHP. In some other PHP code I compared that type to the extension. If there's a mismatch e.g. a JPG extension is actually a Microsoft EXE file, I rejected it. This is important to do because one class of simplistic Windows exploits involving making an EXE file look like an image file or something else the user is likely to double-click.

  • 1
    How do you deal with ambiguous situations? For example, a Javascript .jar, a Microsoft Word .docx, and a PKZip archive all begin with 50 4b 03 04, but do very different things when double-clicked. – Mark Feb 21 '15 at 5:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.