Woocommerce Category Banner Management <= 2.5.1 - Authenticated (Contributor+) PHP Object Injection
Description
The Woocommerce Category Banner Management plugin for WordPress is vulnerable to PHP Object Injection in versions up to, and including, 2.5.1 via deserialization of untrusted input. This makes it possible for authenticated attackers, with contributor-level access and above, to inject a PHP Object. No known POP chain is present in the vulnerable software. If a POP chain is present via an additional plugin or theme installed on the target system, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=2.5.1This research plan focuses on identifying and exploiting a PHP Object Injection vulnerability in the **Banner Management, Product Slider, Product Carousel for WooCommerce** plugin (version <= 2.5.1). --- ### 1. Vulnerability Summary The vulnerability is a PHP Object Injection (POI) residing in the…
Show full research plan
This research plan focuses on identifying and exploiting a PHP Object Injection vulnerability in the Banner Management, Product Slider, Product Carousel for WooCommerce plugin (version <= 2.5.1).
1. Vulnerability Summary
The vulnerability is a PHP Object Injection (POI) residing in the administrative backend of the plugin. It occurs when user-supplied data from a POST parameter is passed directly into the PHP unserialize() function without prior validation or sanitization. While the plugin itself may not contain a usable POP chain, an attacker can leverage POP chains present in WordPress core (e.g., Requests_Utility_FilteredIterator in older versions) or other installed plugins to achieve Remote Code Execution (RCE) or file manipulation.
The vulnerability is accessible to users with Contributor roles or higher, which is atypical for WooCommerce management plugins and suggests a lack of proper capability checks on the vulnerable AJAX or admin action.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php(Inferred) or a specific admin page submission handler. - Action: Likely a
wp_ajax_action such aswccbm_save_settings,wccbm_update_banner, orsave_slider_data(Inferred). - Vulnerable Parameter: A POST parameter often named
data,settings,config, orwccbm_options(Inferred). - Authentication: Authenticated, Contributor-level access (
PR:L). - Preconditions: The attacker must have a valid login for a user with the
contributorrole.
3. Code Flow (Trace)
- Entry Point: The plugin registers an AJAX handler for authenticated users:
add_action('wp_ajax_wccbm_save_category_banner', array($this, 'wccbm_save_category_banner_callback'));(Inferred identifiers). - Capability Check: The callback function likely lacks a strict
current_user_can('manage_options')check, instead using a weaker check or no check at all, allowing Contributors to trigger it. - Nonce Verification: The handler likely calls
check_ajax_referer('wccbm_nonce_action', 'security'). - Data Retrieval: The code fetches a POST parameter containing serialized data:
$banner_data = $_POST['banner_data']; - Sink: The raw input is passed to the vulnerable sink:
$decoded_data = unserialize(stripslashes($banner_data));(Inferred).
4. Nonce Acquisition Strategy
To exploit the AJAX endpoint, a valid nonce is required.
- Identify Localization: The plugin likely localizes a nonce for its administrative scripts. Look for
wp_localize_scriptcalls in the plugin source (e.g., inadmin/class-banner-management-for-woocommerce-admin.php). - Trigger Page: Navigate to the plugin's settings page or a category edit page where the banner management UI appears.
- Extraction:
- Post Creation: If the settings are only visible on certain pages, create a post:
wp post create --post_type=post --post_status=publish --post_title="Exploit" --post_author=[CONTRIBUTOR_ID] - Browser Navigate: Navigate to the WordPress dashboard as the Contributor user.
- Browser Eval: Use the following JS to extract the nonce:
browser_eval("window.wccbm_admin_obj?.nonce || window.wccbm_params?.ajax_nonce")(Inferred JS keys; verify withgrep -r "wp_localize_script" .first).
- Post Creation: If the settings are only visible on certain pages, create a post:
5. Exploitation Strategy
The goal is to trigger the unserialize() call with a crafted object.
Step 1: Identify the exact AJAX action and parameter
Run the following inside the plugin directory:
grep -rn "unserialize" .
grep -rn "wp_ajax" .
Verify which wp_ajax handler leads to an unserialize call.
Step 2: Construct the Payload
Since we are demonstrating POI, we will use a "pingback" or "logger" object if available, or a standard WordPress core POP chain to trigger a noticeable effect (like an error or a file modification).
For a simple PoC, an invalid object that triggers __wakeup can be used to confirm the injection:O:8:"NonExistentClass":0:{}
Step 3: Execute the Attack
Send a POST request to admin-ajax.php.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencodedCookie: [Contributor Session Cookies]
- Body:
action=[ACTION_NAME]&security=[NONCE]&[VULNERABLE_PARAM]=O:8:"NonExistentClass":0:{}
6. Test Data Setup
- User Creation:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - Plugin Activation:
wp plugin activate banner-management-for-woocommerce - Identify Localization Key:
Usegrep -r "wp_localize_script" .to find the JavaScript object name used to store the nonce.
7. Expected Results
- Successful Injection: The server response should indicate the action was processed (even if it returns a 500 error due to the
NonExistentClassor successful execution of a chain). - Verification of Deserialization: If a POP chain is used (e.g.,
Requests_Utility_FilteredIterator), the server may attempt to execute the callback function defined in the serialized object, which can be verified via logs or side-effects.
8. Verification Steps
- Check PHP Error Logs: Look for "PHP Fatal error: unserialize(): Expected to be a closure" or "Class NonExistentClass not found" errors, which confirm the
unserialize()function was reached with our input.tail -n 20 /var/www/html/wp-content/debug.log - Function Call Verification: If utilizing a POP chain to call
phpinfo()orsystem(), check the HTTP response body for the output of those commands.
9. Alternative Approaches
- Settings Save Hook: If the POI is not in an AJAX handler, check the
admin_initoradmin_posthooks. Some plugins process settings during theadmin_inithook by checking$_POSTdirectly. - Category Meta: Check if the vulnerability exists when editing a WooCommerce category. The plugin adds banner fields to the
edit-tags.phppage. Deserialization might occur when saving these custom fields.- Action:
edited_product_cat - Payload Location: The field used for banner configuration data.
- Action:
Summary
The WooCommerce Category Banner Management plugin is vulnerable to PHP Object Injection via the unserialize() function when processing user-supplied data in administrative AJAX actions. Authenticated attackers with Contributor-level access can exploit this by submitting crafted serialized payloads, potentially leading to remote code execution or file manipulation if a suitable POP chain is present on the system.
Vulnerable Code
// Inferred from plugin functionality and research plan // File: admin/class-banner-management-for-woocommerce-admin.php add_action('wp_ajax_wccbm_save_category_banner', array($this, 'wccbm_save_category_banner_callback')); public function wccbm_save_category_banner_callback() { // Nonce verification often present but insufficient for authorization check_ajax_referer('wccbm_nonce_action', 'security'); if (isset($_POST['banner_data'])) { $banner_data = $_POST['banner_data']; // Vulnerable sink: Raw POST data is passed to unserialize $decoded_data = unserialize(stripslashes($banner_data)); // ... logic to save settings } }
Security Fix
@@ -10,7 +10,13 @@ public function wccbm_save_category_banner_callback() { - $decoded_data = unserialize(stripslashes($_POST['banner_data'])); + if ( ! current_user_can( 'manage_woocommerce' ) ) { + wp_die( -1 ); + } + + $decoded_data = json_decode(stripslashes($_POST['banner_data']), true); + if ( json_last_error() !== JSON_ERROR_NONE ) { + // Handle error + }
Exploit Outline
1. Authenticate as a user with at least Contributor-level privileges. 2. Access the WordPress dashboard to extract a valid AJAX nonce from localized scripts (e.g., the 'wccbm_params' or 'wccbm_admin_obj' global variables). 3. Identify the vulnerable AJAX action (e.g., 'wccbm_save_category_banner') and the parameter being deserialized (e.g., 'banner_data'). 4. Generate a PHP serialized object payload utilizing a known POP chain available in the environment (such as those found in WordPress core like Requests_Utility_FilteredIterator or other installed plugins). 5. Send a POST request to /wp-admin/admin-ajax.php containing the action, the security nonce, and the malicious serialized object in the vulnerable parameter. 6. Observe side effects or check logs to verify the execution of the injected object's magic methods (__wakeup, __destruct, etc.).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.