NextMove Lite <= 2.23.0 - Missing Authorization
Description
The NextMove Lite plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.23.0. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=2.23.0What Changed in the Fix
Changes introduced in v2.24.0
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-68048 ## 1. Vulnerability Summary The **NextMove Lite – Thank You Page for WooCommerce** plugin (versions <= 2.23.0) is vulnerable to **Missing Authorization**. The vulnerability exists because certain administrative functions are hooked to `admin_init` witho…
Show full research plan
Exploitation Research Plan - CVE-2025-68048
1. Vulnerability Summary
The NextMove Lite – Thank You Page for WooCommerce plugin (versions <= 2.23.0) is vulnerable to Missing Authorization. The vulnerability exists because certain administrative functions are hooked to admin_init without performing capability checks (current_user_can()) or nonce verification (check_admin_referer()).
Specifically, the functions maybe_activate_post and maybe_deactivate_post in the xlwcty_Admin class (found in admin/xlwcty-admin.php) allow unauthenticated users to toggle the status of "Thank You" pages by simply sending a crafted GET request to the WordPress admin area.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php(or any administrative URL that triggersadmin_init). - HTTP Method:
GET - Authentication: None Required (Unauthenticated)
- Vulnerable Parameters:
xlwcty_activate_post: Used to set a "Thank You" page status toactive.xlwcty_deactivate_post: Used to set a "Thank You" page status todeactive.
- Preconditions: At least one "Thank You" page (post type
xlwcty_thankyou) must exist.
3. Code Flow
- Hook Registration: In
admin/xlwcty-admin.php, the constructor orhooks()method registers the following:add_action( 'admin_init', array( $this, 'maybe_activate_post' ) ); add_action( 'admin_init', array( $this, 'maybe_deactivate_post' ) ); - Entry Point: A request is made to
/wp-admin/admin-ajax.php. Because this is an administrative entry point, WordPress fires theadmin_inithook. - Execution: The
maybe_activate_postormaybe_deactivate_postfunction is called. - Processing: The function checks for the presence of specific GET parameters:
// Logical flow of maybe_deactivate_post (inferred from plugin patterns) public function maybe_deactivate_post() { if ( isset( $_GET['xlwcty_deactivate_post'] ) ) { $post_id = intval( $_GET['xlwcty_deactivate_post'] ); update_post_meta( $post_id, 'xlwcty_post_status', 'deactive' ); // No capability check or nonce check is performed here } } - Sink: The
update_post_metafunction is called, modifying the database state.
4. Nonce Acquisition Strategy
No nonce is required.
The vulnerability is precisely that the authorization and CSRF protection (nonces) are missing for the functions hooked to admin_init. Unauthenticated attackers can trigger these functions without providing a valid _wpnonce or security token.
5. Exploitation Strategy
The goal is to unauthentically deactivate a "Thank You" page.
Step 1: Identify Target Post ID
List the existing "Thank You" pages to find an ID to target.
wp post list --post_type=xlwcty_thankyou
Step 2: Send Deactivation Request
Use the http_request tool to send an unauthenticated GET request to deactivate the post.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php?xlwcty_deactivate_post=[ID] - Headers: None required.
Step 3: Verify Deactivation
Check the post meta to confirm the status has changed.
wp post meta get [ID] xlwcty_post_status
6. Test Data Setup
Before exploitation, a "Thank You" page must be created and set to "active".
- Activate WooCommerce (dependency):
wp plugin activate woocommerce - Create a Thank You Page:
ID=$(wp post create --post_type=xlwcty_thankyou --post_title="Success Page" --post_status=publish --porcelain) wp post meta set $ID xlwcty_post_status active
7. Expected Results
- Initial State:
xlwcty_post_statusfor the post isactive. - Exploit Response: The HTTP request should return a
200 OK(standard foradmin-ajax.phpeven if the action is silent). - Final State:
xlwcty_post_statusfor the post is changed todeactive.
8. Verification Steps
- Check Meta via CLI:
wp post meta get [ID] xlwcty_post_status # Should output: deactive - Reverse the Exploit (Activation):
# Send request to reactivate # URL: http://localhost:8080/wp-admin/admin-ajax.php?xlwcty_activate_post=[ID] - Check Meta again:
wp post meta get [ID] xlwcty_post_status # Should output: active
9. Alternative Approaches
If admin-ajax.php is restricted or does not trigger the expected hook, the same parameters can be appended to any administrative URL:
/wp-admin/index.php?xlwcty_deactivate_post=[ID]/wp-admin/admin-post.php?xlwcty_deactivate_post=[ID]
While these may redirect an unauthenticated user to the login page, the admin_init hook usually fires early enough in the WordPress lifecycle to process the $_GET parameters before the redirect is enforced.
Summary
The NextMove Lite plugin for WordPress is vulnerable to unauthorized status manipulation due to missing capability checks and nonce verification on functions hooked to admin_init. This allows unauthenticated attackers to activate or deactivate 'Thank You' pages by sending crafted GET requests to administrative endpoints like admin-ajax.php.
Vulnerable Code
// admin/xlwcty-admin.php line 117-118 add_action( 'admin_init', array( $this, 'maybe_activate_post' ) ); add_action( 'admin_init', array( $this, 'maybe_deactivate_post' ) ); --- // Inferred logic of the vulnerable functions (based on research plan) public function maybe_deactivate_post() { if ( isset( $_GET['xlwcty_deactivate_post'] ) ) { $post_id = intval( $_GET['xlwcty_deactivate_post'] ); update_post_meta( $post_id, 'xlwcty_post_status', 'deactive' ); } }
Security Fix
@@ -117,8 +117,14 @@ /** * Hooks to check if activation and deactivation request for post. */ - add_action( 'admin_init', array( $this, 'maybe_activate_post' ) ); - add_action( 'admin_init', array( $this, 'maybe_deactivate_post' ) ); + if ( is_admin() && ( isset( $_GET['xlwcty_activate_post'] ) || isset( $_GET['xlwcty_deactivate_post'] ) ) ) { + if ( current_user_can( 'manage_options' ) ) { + add_action( 'admin_init', array( $this, 'maybe_activate_post' ) ); + add_action( 'admin_init', array( $this, 'maybe_deactivate_post' ) ); + } + } add_action( 'save_post_' . XLWCTY_Common::get_thank_you_page_post_type_slug(), array( $this, 'save_menu_order' ), 10, 2 ); add_action( 'wp_print_scripts', array( $this, 'xlwcty_wp_print_scripts' ), 999 );
Exploit Outline
The exploit targets the `admin_init` hook, which executes even for unauthenticated users when accessing certain administrative endpoints. 1. Target Identification: An attacker identifies a 'Thank You' page ID (e.g., through enumeration or public data). 2. Unauthenticated Request: The attacker sends a GET request to `/wp-admin/admin-ajax.php` with the parameter `xlwcty_deactivate_post` set to the target post ID. 3. Processing: Because the `maybe_deactivate_post` function is hooked to `admin_init` and lacks a `current_user_can()` check or nonce verification, the plugin processes the request. 4. Impact: The plugin updates the `xlwcty_post_status` meta of the specified post to 'deactive', effectively disabling the custom 'Thank You' page without any authentication.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.