Addonify – Compare Products For WooCommerce <= 1.1.17 - Missing Authorization to Unauthenticated Settings Update
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:NTechnical Details
<=1.1.17Source Code
WordPress.org SVNThis 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
- Entry Point: The plugin registers an AJAX handler using
add_action( 'wp_ajax_nopriv_...', '...' ). - Handler Function: The handler function (likely located in
includes/Admin/Settings.phporincludes/Admin/Ajax.php) is called when the specific action is triggered viaadmin-ajax.php. - Missing Check: The handler likely checks for a nonce but fails to call
current_user_can( 'manage_options' ). - Sink: The function extracts data from
$_POSTand callsupdate_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:
- 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-productsoraddonify-compare-js.
- Grep Command:
- 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).
- Grep Command:
- 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]' - Extract Nonce via Browser:
- Navigate to the newly created page.
- Use
browser_evalto find the nonce in the global JS object. - Inferred Variable:
window.addonify_compare_params?.nonceorwindow.afc_vars?.nonce.
5. Exploitation Strategy
Once the action name and nonce (if required) are identified:
- Identify Target Settings: Check
includes/Admin/Settings.phpto see which option name is used (e.g.,addonify_compare_settings). - Craft Payload:
- URL:
http://<target>/wp-admin/admin-ajax.php - Body (URL-encoded):
action=addonify_compare_save_settings&nonce=<NONCE>&settings[button_text]=EXPLOITED
- URL:
- Execute Request: Use
http_requestwith the following headers:Content-Type: application/x-www-form-urlencoded
- Verify Response: A successful response usually returns
{"success":true}or1.
6. Test Data Setup
- Install and activate the plugin version 1.1.17.
- Install and activate WooCommerce (the plugin depends on it).
- Create a product to ensure the comparison environment is "live":
wp post create --post_type=product --post_title="Test Product" --post_status=publish - If a nonce is needed, create the page as described in Section 4.
7. Expected Results
- The
http_requestshould return a 200 OK status. - The plugin settings in the database will be updated to reflect the attacker-supplied values.
- If
button_textis 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_settingsis 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:
Ifgrep -rn "register_rest_route" . -A 5 | grep "permission_callback"permission_callbackis__return_trueor missing, use a REST API request instead of AJAX.
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
@@ -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.