Jupiter X Core Plugin Still Contains Vulnerability Allowing Reverting Website Database to Previously Backed Up Version
As detailed in more detail in a security advisory we have released for the developer of the plugin Jupiter X Core, recently the developer left 90,000+ websites open to being hacked for two weeks, after the WordPress security company Wordfence disclosed an easily exploited vulnerability in the plugin where there wasn’t a fix available (while claiming to have done responsible disclosure). Once the new version of the plugin that addressed that was released, we could check over the current state of the plugin. What we found was that Wordfence hadn’t warned people that the plugin still contains many vulnerabilities.
Wordfence explained how to exploit the vulnerability this way:
On a site with a vulnerable version of the Jupiter Theme installed, any logged-in user can elevate their privileges to those of an administrator by sending an AJAX request with the action parameter set to abb_uninstall_template. This calls the uninstallTemplate function, which calls the resetWordpressDatabase function, where the site is effectively reinstalled with the currently logged-in user as the new site owner.
On a site where a vulnerable version of the JupiterX Core plugin is installed, the same functionality can also be accessed by sending an AJAX request with the action parameter set to jupiterx_core_cp_uninstall_template.
If you look at the code that registers jupiterx_core_cp_uninstall_template to be used as the action parameter for an AJAX request, what you see two lines above is that a function to restore a database backup is also registered:
216 217 218 219 | add_action( 'wp_ajax_abb_restore_latest_db', array( &$this, 'restoreLatestDB' ) ); add_action( 'wp_ajax_abb_is_restore_db', array( &$this, 'isRestoreDB' ) ); add_action( 'wp_ajax_jupiterx_core_cp_uninstall_template', array( &$this, 'uninstallTemplate' ) ); |
For the functionality that Wordfence identified as vulnerable, the beginning of the relevant function was this as of the previous version:
1304 1305 | public function uninstallTemplate() { try { |
It was changed to this:
1373 1374 1375 1376 1377 1378 1379 1380 | public function uninstallTemplate() { check_ajax_referer( 'jupiterx_control_panel', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'You do not have access to this section.', 'jupiterx-core' ); } try { |
That added both a nonce check to prevent cross-site request forgery (CSRF) and a capabilities check to restrict who can access the functionality.
The function for restoring a databases backup, which is located in the same file, /includes/control-panel-2/includes/class-install-template.php, still doesn’t contain those security checks:
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 | public function restoreLatestDB() { try { $db_manager = new JupiterX_Core_Control_Panel_Database_Manager(); $return = $db_manager->restore_latest_db(); if ( false == $return ) { throw new Exception( $db_manager->get_error_message() ); } JupiterX_Core_Control_Panel_Helpers::prevent_cache_plugins(); $this->message( 'Restore completed!', true ); return true; } catch ( Exception $e ) { $this->message( $e->getMessage(), false ); return false; } } |
So anyone logged in to WordPress can restore a database backup, erasing the new data from the database. Through CSRF, an attacker could cause someone logged in to do the same without intending it.
It isn’t hard to find other functionality in the plugin that is also still missing those security checks. We haven’t reviewed all of that, so we don’t know what all an attacker could accomplish. But based on everything that has happened, we are advising to avoid using plugins from the developer unless they can get the security of their plugins in much better shape.
WordPress Causes Full Disclosure
As a protest of the moderators of the WordPress Support Forum’s continued inappropriate behavior we changed from reasonably disclosing to full disclosing vulnerabilities for plugins in the WordPress Plugin Directory in protest, until WordPress gets that situation cleaned up, so we are releasing this post and then leaving a message about that for the developer through the WordPress Support Forum. (For plugins that are also in the ClassicPress Plugin Directory, we will follow our reasonable disclosure policy.)
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, but considering that they believe that having plugins, which have millions installs, remain in the Plugin Directory despite them knowing they are vulnerable is “appropriate action”, something is very amiss with them (which is even more reason the moderation needs to be cleaned up).
If the moderation is cleaned up, it would also allow the possibility of being able to use the forum to start discussing fixing the problems caused by the very problematic handling of security by the team running the Plugin Directory, discussions which they have for years shut down through their control of the Support Forum.
Update: To clear up the confusion where developers claim we hadn’t tried to notify them through the Support Forum (while at the same time moderators are complaining about us doing just that), here is the message we left for this vulnerability:
Is It Fixed?
If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.
Proof of Concept
The following proof of concept will cause the database backup restoration functionality to run, when logged in to WordPress.
Replace “[path to WordPress]” with the location of WordPress.
http://[path to WordPress]/wp-admin/admin-ajax.php?action=abb_is_restore_db