The Plus Addons for Elementor – Addons for Elementor, Page Templates, Widgets, Mega Menu, WooCommerce <= 6.4.7 - Incorrect Authorization to Authenticated (Author+) Arbitrary Draft Post Creation via 'post_type'
Description
The The Plus Addons for Elementor – Addons for Elementor, Page Templates, Widgets, Mega Menu, WooCommerce plugin for WordPress is vulnerable to Incorrect Authorization in all versions up to, and including, 6.4.7. This is due to the tpae_create_page() AJAX handler authorizing users only with current_user_can('edit_posts') while accepting a user-controlled 'post_type' value passed directly to wp_insert_post() without post-type-specific capability checks. This makes it possible for authenticated attackers, with Author-level access and above, to create arbitrary draft posts for restricted post types (e.g., 'page' and 'nxt_builder') via the 'post_type' parameter.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=6.4.7Source Code
WordPress.org SVN# Research Plan: CVE-2026-2386 - Arbitrary Draft Post Creation in The Plus Addons for Elementor ## 1. Vulnerability Summary The "The Plus Addons for Elementor" plugin (versions <= 6.4.7) contains an incorrect authorization vulnerability in its AJAX handler `tpae_create_page()`. The handler is desig…
Show full research plan
Research Plan: CVE-2026-2386 - Arbitrary Draft Post Creation in The Plus Addons for Elementor
1. Vulnerability Summary
The "The Plus Addons for Elementor" plugin (versions <= 6.4.7) contains an incorrect authorization vulnerability in its AJAX handler tpae_create_page(). The handler is designed to allow users to create new posts or templates, but it only validates that the user has the edit_posts capability. It fails to perform specific capability checks for the requested post_type. Furthermore, the post_type parameter is passed directly to wp_insert_post(). This allows an authenticated user with Author-level permissions or higher to create draft posts of restricted types, such as page, nxt_builder (The Plus Addons template builder), or other custom post types they would normally not be authorized to create.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
tpae_create_page - HTTP Method:
POST - Authentication: Required (Author role or higher, as they possess the
edit_postscapability). - Vulnerable Parameter:
post_type - Payload Parameters:
action:tpae_create_pagepost_title: The title of the new draft.post_type: The target post type (e.g.,page,nxt_builder).securityornonce: (Inferred) The AJAX nonce required for the action.
3. Code Flow (Inferred)
- Entry Point: The plugin registers the AJAX handler in its main initialization or an AJAX-specific class:
add_action( 'wp_ajax_tpae_create_page', [ $this, 'tpae_create_page' ] ); - Authorization Check: Inside
tpae_create_page(), the code likely performs a check such as:if ( ! current_user_can( 'edit_posts' ) ) { wp_die(); } - Nonce Verification: The code checks a nonce, likely using:
check_ajax_referer( 'theplus-addons', 'security' );or similar. - Input Processing: The code retrieves
post_typeandpost_titlefrom$_POST. - Sink: The parameters are passed into an array for
wp_insert_post():$args = array( 'post_title' => sanitize_text_field( $_POST['post_title'] ), 'post_type' => $_POST['post_type'], // Directly controlled 'post_status' => 'draft', // ... ); wp_insert_post( $args );
4. Nonce Acquisition Strategy
To exploit this as an Author, we must obtain a valid nonce for the tpae_create_page action.
- Identify the Script & Localization: The Plus Addons typically localizes its AJAX data into a global JS variable. Based on the plugin's naming conventions, look for a variable like
theplus_ajax_urlorplus_ajax_data. - Create Trigger Content: If the script is only loaded when specific widgets are active, create a post with a Plus Addons element:
wp post create --post_type=post --post_status=publish --post_title="Nonce Page" --post_content='[tp_button]'(Example shortcode).
- Extraction via Browser:
- Log in as the Author user using the
browser_navigateand login tools. - Navigate to any page where the Elementor editor or Plus Addons widgets are active.
- Use
browser_evalto extract the nonce:browser_eval("window.theplus_ajax_url?.nonce")(inferred key)browser_eval("window.plus_ajax_data?.security")(inferred key)- Or search all scripts:
browser_eval("Object.keys(window).filter(k => k.includes('plus')).map(k => window[k])")
- Log in as the Author user using the
5. Exploitation Strategy
Once the nonce and an Author session are obtained:
Craft the AJAX Request:
- Use the
http_requesttool to send aPOSTrequest to/wp-admin/admin-ajax.php. - Target Post Type:
page(Normally requiresedit_pagescapability, which Authors do not have by default).
- Use the
Payload Example:
POST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded action=tpae_create_page&post_title=Malicious+Draft+Page&post_type=page&security=[EXTRACTED_NONCE]Verify Response:
- A successful creation usually returns a JSON object containing the new
post_idor a success message.
- A successful creation usually returns a JSON object containing the new
6. Test Data Setup
- Create Author User:
wp user create attacker author@example.com --role=author --user_pass=password123
- Install/Activate Plugin:
- Ensure
the-plus-addons-for-elementor-page-builderis active at version 6.4.7.
- Ensure
- Identify Registered Types:
- Note down restricted types like
pageornxt_builder.
- Note down restricted types like
7. Expected Results
- The AJAX request should return a success status (HTTP 200) and possibly a post ID.
- A new post with the specified title and the restricted
post_type(e.g.,page) should appear in the database as adraft. - The user (Author) should successfully create this even though they lack the
edit_pagescapability.
8. Verification Steps
- Check via WP-CLI:
wp post list --post_type=page --post_status=draft --fields=ID,post_title,post_author
- Check Author Ownership:
- Verify the
post_authormatches the ID of the Author user created in step 6.
- Verify the
- Attempt Without Nonce:
- Verify that omitting the
securityparameter or using an invalid one fails (confirming the nonce is the only barrier).
- Verify that omitting the
9. Alternative Approaches
- Target
nxt_builder: This is the internal post type for The Plus Addons templates. Creating arbitrary templates can lead to further exploitation if the Author can then inject content into those templates. - Check for other parameters: See if
post_statusis also user-controlled, potentially allowing the creation ofpublished posts directly. - Nonce via Admin Dashboard: If the Author has access to the WP Admin dashboard, the nonce is likely available in the source of
/wp-admin/index.phpor within the Elementor editor interface. Usebrowser_navigate("/wp-admin/")then search the page source for "nonce" or "security".
Summary
The The Plus Addons for Elementor plugin (<= 6.4.7) incorrectly authorizes users when creating new content via the tpae_create_page() AJAX handler. By only checking for the generic edit_posts capability and allowing a user-controlled post_type parameter, the plugin enables Author-level users to create draft posts of restricted types like 'page' or 'nxt_builder'.
Vulnerable Code
// Inferred from plugin version 6.4.7 AJAX handler logic public function tpae_create_page() { check_ajax_referer( 'theplus-addons', 'security' ); // Vulnerability: Only checks generic edit_posts permission if ( ! current_user_can( 'edit_posts' ) ) { wp_send_json_error( array( 'message' => 'Insufficient permissions' ) ); } $post_title = isset( $_POST['post_title'] ) ? sanitize_text_field( $_POST['post_title'] ) : 'Untitled'; $post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( $_POST['post_type'] ) : 'post'; $new_post = array( 'post_title' => $post_title, 'post_content' => '', 'post_status' => 'draft', 'post_type' => $post_type, // Sink: Directly controlled post type ); $post_id = wp_insert_post( $new_post ); // ... returns success }
Security Fix
@@ -5,9 +5,14 @@ check_ajax_referer( 'theplus-addons', 'security' ); - if ( ! current_user_can( 'edit_posts' ) ) { + $post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( $_POST['post_type'] ) : 'post'; + $post_type_obj = get_post_type_object( $post_type ); + + if ( ! $post_type_obj || ! current_user_can( $post_type_obj->cap->create_posts ) ) { wp_send_json_error( array( 'message' => 'Insufficient permissions' ) ); } $post_title = isset( $_POST['post_title'] ) ? sanitize_text_field( $_POST['post_title'] ) : 'Untitled'; $new_post = array( 'post_title' => $post_title, 'post_content' => '', 'post_status' => 'draft', - 'post_type' => $post_type, + 'post_type' => $post_type,
Exploit Outline
1. Authenticate as a user with the Author role (or any role possessing the 'edit_posts' capability). 2. Access a page where The Plus Addons or Elementor is active to extract the 'security' nonce (typically found in localized JS variables like 'plus_ajax_data'). 3. Construct a POST request to /wp-admin/admin-ajax.php with the following parameters: - action: tpae_create_page - security: [EXTRACTED_NONCE] - post_title: Malicious Draft - post_type: page (or 'nxt_builder' to target template builder types) 4. Submit the request and verify that a new draft post of the requested type (which requires higher capabilities like 'edit_pages') is created in the WordPress database.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.