CVE-2026-4326

Vertex Addons for Elementor <= 1.6.4 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Plugin Installation and Activation via 'afeb_activate_required_plugins'

highMissing Authorization
8.8
CVSS Score
8.8
CVSS Score
high
Severity
1.7.0
Patched in
1d
Time to patch

Description

The Vertex Addons for Elementor plugin for WordPress is vulnerable to Missing Authorization in all versions up to and including 1.6.4. This is due to improper authorization enforcement in the activate_required_plugins() function. Specifically, the current_user_can('install_plugins') capability check does not terminate execution when it fails — it only sets an error message variable while allowing the plugin installation and activation code to execute. The error response is only sent after the installation and activation have already completed. This makes it possible for authenticated attackers, with Subscriber-level access and above, to install and activate arbitrary plugins from the WordPress.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.6.4
PublishedApril 8, 2026
Last updatedApril 9, 2026

What Changed in the Fix

Changes introduced in v1.7.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-4326 - Vertex Addons for Elementor ## 1. Vulnerability Summary The **Vertex Addons for Elementor** plugin (versions <= 1.6.4) contains a missing authorization vulnerability in its AJAX handler for plugin activation. The function `AFEB\Ajax::activate_required_p…

Show full research plan

Exploitation Research Plan: CVE-2026-4326 - Vertex Addons for Elementor

1. Vulnerability Summary

The Vertex Addons for Elementor plugin (versions <= 1.6.4) contains a missing authorization vulnerability in its AJAX handler for plugin activation. The function AFEB\Ajax::activate_required_plugins() performs a capability check using current_user_can('install_plugins'), but fails to exit or return when the check evaluates to false. Instead, it merely assigns an error message to a variable and continues to the plugin installation and activation logic. This allows any authenticated user (including those with Subscriber privileges) to install and activate arbitrary plugins from the WordPress.org repository.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: afeb_activate_required_plugins
  • Required Authentication: Any logged-in user (Subscriber and above).
  • Vulnerable Parameter: Likely slug or plugin (the slug of the WordPress.org plugin to install).
  • Preconditions:
    • The plugin Vertex Addons for Elementor must be active.
    • Elementor must be active (the Ajax class is initialized only after elementor/loaded in afeb.php).

3. Code Flow

  1. Initialization: In afeb.php, Vertex_Addons_For_Elementor::init() is called on the elementor/loaded hook.
  2. Ajax Registration: init() calls (new Ajax())->init();. Inside app/Ajax.php, the init() method calls actions().
  3. Hook Registration: Ajax::actions() registers the vulnerable hook:
    add_action('wp_ajax_afeb_activate_required_plugins', [$this, 'activate_required_plugins']);
  4. Vulnerability Sink: The activate_required_plugins function is called.
    • It verifies the nonce: check_ajax_referer('afeb_ajax_nonce', 'nonce');.
    • It checks current_user_can('install_plugins').
    • The Bug: If the check fails, it populates an error variable but does not call wp_die() or return.
    • It proceeds to use Plugin_Upgrader or a similar WordPress core utility to install and activate the plugin provided in the $_POST data.
    • The error response is only sent at the very end of the function.

4. Nonce Acquisition Strategy

The endpoint requires a nonce tied to the action afeb_ajax_nonce. This nonce is localized for administrative screens.

  1. Identify Localization: In app/Assets.php, the backend_script() function enqueues afeb-backend-script and calls $this->localize_script($handle).
  2. Access Backend: Since Subscribers can access the WordPress dashboard (/wp-admin/index.php), the admin_enqueue_scripts hook will fire for them.
  3. Extraction:
    • Login as a Subscriber.
    • Navigate to /wp-admin/.
    • The localized data is likely attached to a global JavaScript object named afeb_admin or afeb_backend (inferred from the plugin prefix afeb).
    • Use browser_eval to extract it: window.afeb_admin?.nonce or window.afeb_backend?.nonce.

5. Exploitation Strategy

We will attempt to install and activate the hello-dolly plugin (a benign, standard plugin) to prove the vulnerability.

Step-by-Step Plan:

  1. Login: Authenticate as a Subscriber-level user.
  2. Extract Nonce:
    • Navigate to /wp-admin/.
    • Execute browser_eval("afeb_admin.nonce") to retrieve the afeb_ajax_nonce. (If afeb_admin is not found, inspect the page source for wp_localize_script outputs).
  3. Execute Exploit:
    • Send a POST request to admin-ajax.php.
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body:
      action=afeb_activate_required_plugins&nonce=[EXTRACTED_NONCE]&slug=hello-dolly
      
    • Note: If slug does not work, try plugin=hello-dolly.

6. Test Data Setup

  1. Roles: Ensure a user with the subscriber role exists.
  2. Plugins:
    • Install elementor (required for Vertex Addons to load).
    • Install addons-for-elementor-builder version 1.6.4.
  3. Activation: Activate both plugins via WP-CLI.

7. Expected Results

  • Response: Even if the response returns a JSON error like {"success":false,"data":{"message":"You do not have permission..."}}, the plugin installation should have already occurred.
  • State Change: The hello-dolly plugin should be present in the wp-content/plugins directory and marked as "Active" in the database.

8. Verification Steps

After sending the HTTP request, use WP-CLI to confirm the installation:

wp plugin is-installed hello-dolly
wp plugin status hello-dolly

Successful exploitation is confirmed if the status is Active.

9. Alternative Approaches

If the afeb_activate_required_plugins function expects an array of plugins:

  • Payload: action=afeb_activate_required_plugins&nonce=[NONCE]&plugins[]=hello-dolly
  • Payload: action=afeb_activate_required_plugins&nonce=[NONCE]&slugs[]=hello-dolly

If the nonce is not found on the dashboard, check the Elementor editor page (if the Subscriber has access to any post):

  • Navigate to /wp-admin/post.php?post=[ID]&action=elementor.
  • Check for afeb related localized scripts there.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Vertex Addons for Elementor plugin for WordPress is vulnerable to unauthorized plugin installation and activation because the capability check in the 'activate_required_plugins' function fails to terminate execution upon failure. This allows authenticated users with Subscriber-level access or higher to install and activate any plugin from the WordPress repository by sending a crafted AJAX request with a valid nonce.

Vulnerable Code

// app/Ajax.php (lines 224-233 in version 1.6.4)
    public function activate_required_plugins()
    {
        check_ajax_referer('afeb_ajax_nonce', 'nonce');

        $error = '';

        if (!current_user_can('install_plugins'))
            $error = esc_html__('Sorry, you are not allowed to install plugins on this site.', 'addons-for-elementor-builder');

        $plugins = isset($_POST['plugins']) ? map_deep($_POST['plugins'], 'sanitize_text_field') : [];

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/addons-for-elementor-builder/1.6.4/app/Ajax.php /home/deploy/wp-safety.org/data/plugin-versions/addons-for-elementor-builder/1.7.0/app/Ajax.php
--- /home/deploy/wp-safety.org/data/plugin-versions/addons-for-elementor-builder/1.6.4/app/Ajax.php	2026-02-28 04:34:56.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/addons-for-elementor-builder/1.7.0/app/Ajax.php	2026-03-25 18:05:28.000000000 +0000
@@ -224,10 +224,14 @@
     {
         check_ajax_referer('afeb_ajax_nonce', 'nonce');
 
-        $error = '';
-
         if (!current_user_can('install_plugins'))
-            $error = esc_html__('Sorry, you are not allowed to install plugins on this site.', 'addons-for-elementor-builder');
+        {
+            wp_send_json_error([
+                'message' => esc_html__('Sorry, you are not allowed to install plugins on this site.', 'addons-for-elementor-builder'),
+            ], 403);
+        }
+
+        $error = '';
 
         $plugins = isset($_POST['plugins']) ? map_deep($_POST['plugins'], 'sanitize_text_field') : [];
         $time_limit = ini_get('max_execution_time');
@@ -294,6 +298,13 @@
     {
         check_ajax_referer('afeb_ajax_nonce', 'nonce');
 
+        if (!current_user_can('manage_options'))
+        {
+            wp_send_json_error([
+                'message' => esc_html__('Sorry, you are not allowed to import template kit settings on this site.', 'addons-for-elementor-builder'),
+            ], 403);
+        }
+
         $time_limit = ini_get('max_execution_time');
 
         if (!did_action('elementor/loaded') || !class_exists(Plugin::class))
@@ -386,6 +397,13 @@
     {
         check_ajax_referer('afeb_ajax_nonce', 'nonce');
 
+        if (!current_user_can('manage_options'))
+        {
+            wp_send_json_error([
+                'message' => esc_html__('Sorry, you are not allowed to import template kits on this site.', 'addons-for-elementor-builder'),
+            ], 403);
+        }
+

Exploit Outline

The exploit requires authentication as any registered user (e.g., Subscriber). First, the attacker logs in and navigates to the WordPress dashboard (/wp-admin/) to extract the 'afeb_ajax_nonce' from the localized script variables (the plugin enqueues these scripts for all admin users via the 'admin_enqueue_scripts' hook). Once the nonce is obtained, the attacker sends a POST request to '/wp-admin/admin-ajax.php' with the action parameter set to 'afeb_activate_required_plugins', the extracted nonce, and a 'plugins' array containing the slug of the target plugin from the WordPress repository (e.g., 'plugins[]=hello-dolly'). Because the capability check 'current_user_can('install_plugins')' in the plugin's AJAX handler does not stop the execution flow, the plugin installation and activation proceed despite the unauthorized user status.

Check if your site is affected.

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