PHP File Upload Vulnerabilities

07th March 2016

Twice in the last week i've been asked to fix and investigate websites being hacked. On both occasions the issues arose out of really badly coded 3rd party pieces of code. I thought i'd write this post just to highlight the dangers around not properly securing file uploads.

The first site was a WordPress site which had been comprised in order to send out thousands upon thousands of spam emails. After taking the site down there were about 20 files which had had malicious PHP code injected into them. The source of vulnerability was traced down a file in the WordPress Cherry Framework used by the theme on the site. (Note that it has been patched in later versions of the framework but there are many template sites offering templates with the older unpatched version)

The code below shows that anyone can upload a file directly onto the server. There are no checks to see if you're logged in as a WordPress admin, no checks on the file type or content and no checks on the upload folder being set.

// Insecure upload.php
    $upload_dir = isset($_REQUEST['upload_dir']) ? $_REQUEST['upload_dir'] : $upload_dir ;
    $file_name =basename($_FILES['file']['name']);
    $upload_file = $upload_dir.$file_name;
    $result = move_uploaded_file($_FILES['file']['tmp_name'], $upload_file);

The second occurrence was on a very old PHP site which was using a library called Open Flash Chart in order to produce some nice looking animated pie charts. In the library there exists a filed called ofc_upload_image.php which appears to save image data passed to it. However the filename to save it to is passed as a query string and the post data is not checked or filtered in anyway. This means you can easily post PHP code to ofc_upload_image.php?name=evil.php and it'll be saved onto the site in order for you to run. One of the things the attackers did was to redirect all traffic the came via search engines to a spammy url. The code uploaded also allowed the attackers to run command line scripts, view or edit the database on the site and modify any other files they wanted.

// Insecure ofc_upload_image.php
$default_path = '../tmp-upload-images/';
if (!file_exists($default_path)) mkdir($default_path, 0777, true);
$destination = $default_path . basename( $_GET[ 'name' ] ); 
$jfh = fopen($destination, 'w') or die("can't open file");
fwrite($jfh, $HTTP_RAW_POST_DATA);

So, developers, take extra care when dealing with file uploads!