13 Feb 2024

Hacker Likely Targeting This Incompletely Fixed Authenticated Plugin Installation Vulnerability in WordPress Plugin NextMove Lite

Today we saw a hacker probing for usage of the WordPress plugin NextMove Lite on our websites with the following request:

/wp-content/plugins/woo-thank-you-page-nextmove-lite/assets/css/xlwcty-public-rest.css

The changelog for the latest version of the plugin, which was released yesterday, mentions a security fix was made, “Security: Nonce checking added in the admin plugin installation call. (fix/108).” That sounds like a minor issue, but looking at the relevant code, it turns out the change made doesn’t fully address the vulnerability, so this was actually a serious vulnerability and still is fairly serious. The vulnerability allows those logged in to WordPress to install any plugin from the WordPress Plugin Directory on the website.

The plugin looks to contain at least one more vulnerability, so we would recommend against using the plugin unless a thorough security review is done and all issues addressed.

There is at least one other plugin from the same developer, XLPlugins, that looks like it is also contains this vulnerability.

Other Providers Are Incorrectly Claiming This Has Been Fixed

Other data providers including Patchstack, Wordfence, and WPScan are all listing the vulnerability as having been fixed, despite its still unfixed nature.

Free Warning

As this vulnerability looks to be targeted by hackers, we are adding accurate data on it to the free data that comes with our Plugin Vulnerabilities plugin.

Authenticated Plugin Installation

In the file /includes/xlwcty-xl-support.php, the plugin makes the function xl_addon_installation() accessible to anyone logged in to WordPress:

20
add_action( 'wp_ajax_xl_addon_installation', array( $this, 'xl_addon_installation' ), 10, 1 );

As of the previous version, no security checks were done before installing and activating arbitrary plugins from the WordPress plugin directory:

751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
public function xl_addon_installation() {
	$plugin_slug = isset( $_POST['xl_slug'] ) ? $_POST['xl_slug'] : '';
	$plugin_file = isset( $_POST['xl_file'] ) ? $_POST['xl_file'] : '';
	if ( empty( $plugin_slug ) || empty( $plugin_file ) ) {
		return;
	}
	$plugin_file = $plugin_slug . $plugin_file;
 
	if ( $this->is_plugin_installed( $plugin_file ) ) {
		$activation_result = activate_plugin( $plugin_file );
 
		if ( is_wp_error( $activation_result ) ) {
			wp_send_json_error( 'Failed to activate plugin.' );
		} else {
			wp_send_json_success( 'Plugin activated successfully!' );
		}
	} else {
		include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
		include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
 
		$api = plugins_api( 'plugin_information', array(
			'slug'   => $plugin_slug,
			'fields' => array(
				'sections' => false,
			),
		) );
 
		$upgrader = new Plugin_Upgrader();
 
		// Start the installation process
		$result = $upgrader->install( $api->download_link );
 
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( 'Failed to install plugin.' );
		}
 
		// Activate the plugin
		$activation_result = activate_plugin( $plugin_file );

The code at least requires the plugin to be in the WordPress Plugin Directory. Other vulnerabilities like this haven’t had that restriction and therefore allowed uploading arbitrary files.

There should have been a capabilities check to limit who has access, a nonce check to prevent cross-site request forgery (CSRF), and a limit on what plugins can be installed to the ones intended by the plugin.

The new version only adds a nonce check:

751
752
753
754
755
756
757
758
public function xl_addon_installation() {
	$plugin_slug = isset( $_POST['xl_slug'] ) ? $_POST['xl_slug'] : '';
	$plugin_file = isset( $_POST['xl_file'] ) ? $_POST['xl_file'] : '';
	$nonce       = isset( $_POST['nonce'] ) ? $_POST['nonce'] : '';
	// Verify the nonce
	if ( ! wp_verify_nonce( $nonce, 'xl_addon_installation_nonce' ) ) {
		wp_send_json_error( 'Invalid nonce.' );
	}

The value needed for that nonce check is available to anyone logged in to WordPress who can access Admin pages, so those who shouldn’t have access to the functionality still do.

As this plugin extends WooCommerce, normally not everyone logged in to WordPress has access to Admin pages. (At least if there isn’t another bug in the code that enforces that.)

We have reached out to the developer about the remaining issues with that code and have offered to help them fix this.


Plugin Security Scorecard Grade for Patchstack

Checked on March 5, 2025
D

See issues causing the plugin to get less than A+ grade


Plugin Security Scorecard Grade for WPScan

Checked on April 12, 2025
F

See issues causing the plugin to get less than A+ grade

Leave a Reply

Your email address will not be published.