CVE-2025-14155

Premium Addons for Elementor <= 4.11.53 - Missing Authorization to Unauthenticated Sensitive Information Exposure via 'get_template_content'

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.11.54
Patched in
54d
Time to patch

Description

The Premium Addons for Elementor – Powerful Elementor Templates & Widgets plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the 'get_template_content' function in all versions up to, and including, 4.11.53. This makes it possible for unauthenticated attackers to view the content of private, draft, and pending templates.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.11.53
PublishedDecember 22, 2025
Last updatedFebruary 13, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to investigate and exploit CVE-2025-14155 in the **Premium Addons for Elementor** plugin. ## 1. Vulnerability Summary The **Premium Addons for Elementor** plugin (up to version 4.11.53) contains a vulnerability where the `get_template_content` function (likely …

Show full research plan

This research plan outlines the steps to investigate and exploit CVE-2025-14155 in the Premium Addons for Elementor plugin.

1. Vulnerability Summary

The Premium Addons for Elementor plugin (up to version 4.11.53) contains a vulnerability where the get_template_content function (likely registered as an AJAX action) lacks proper authorization and capability checks. This allows unauthenticated users to access the content of WordPress posts or templates that are set to private, draft, or pending status, which are otherwise restricted from public view.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: premium_get_template_content (Inferred based on plugin naming conventions and the function name)
  • Method: HTTP POST
  • Parameters:
    • action: premium_get_template_content (inferred)
    • nonce: A WordPress nonce (likely required for the AJAX call)
    • templateID: The ID of the template or post to retrieve
  • Authentication: Unauthenticated (leveraging wp_ajax_nopriv_ hooks)
  • Preconditions:
    1. The plugin must be active.
    2. An attacker needs a valid nonce (which is often exposed to all visitors via localized scripts).
    3. A private, draft, or pending template/post must exist and its ID must be known (or brute-forced).

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers AJAX handlers during initialization (likely in an includes/ class).
    • add_action( 'wp_ajax_premium_get_template_content', [ $this, 'get_template_content' ] );
    • add_action( 'wp_ajax_nopriv_premium_get_template_content', [ $this, 'get_template_content' ] );
  2. Function Execution: The get_template_content function is called.
  3. Input Handling: The function retrieves templateID from $_POST.
  4. Security Check (The Flaw): The function likely calls check_ajax_referer but fails to call current_user_can('edit_posts') or verify if the current user has permission to view the specific post ID.
  5. Data Retrieval: The function uses get_post($id) or Elementor’s frontend->get_builder_content_for_display($id) to render the content.
  6. Information Leak: The rendered HTML/content of the private/draft post is echoed to the response and execution ends via wp_die().

4. Nonce Acquisition Strategy

Premium Addons for Elementor typically localizes settings for its frontend widgets.

  1. Identify Shortcode: The plugin uses various widgets. A common one that might trigger template loading is the "Modal Box" or "Content Switcher".
  2. Create Trigger Page: Create a public page with a Premium Addons widget that utilizes templates.
    • wp post create --post_type=page --post_status=publish --post_title="Nonce Page" --post_content='[premium_modal_box]' (inferred shortcode).
  3. Navigate and Extract:
    • Navigate to the "Nonce Page".
    • Use browser_eval to find the nonce in the localized JS object.
    • Common JS Object: PremiumAddonsSettings or pa_settings.
    • Command: browser_eval("window.PremiumAddonsSettings?.nonce") or browser_eval("window.pa_settings?.nonce").

5. Exploitation Strategy

  1. Target Identification: Identify the ID of a "Private" post.
  2. Nonce Retrieval: Obtain the nonce using the strategy in Section 4.
  3. Execution: Send the malicious AJAX request.

HTTP Request:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.local
Content-Type: application/x-www-form-urlencoded

action=premium_get_template_content&nonce=[EXTRACTED_NONCE]&templateID=[PRIVATE_POST_ID]

Expected Response:
An HTTP 200 response containing the HTML content of the private post. If the post is an Elementor template, it will return the fully rendered Elementor content.

6. Test Data Setup

  1. Install Version 4.11.53: Ensure the vulnerable version is active.
  2. Create Private Content:
    • wp post create --post_type=post --post_title="Secret Credentials" --post_content="The admin password is: P4ssw0rd!" --post_status=private
    • Note the ID returned (e.g., 123).
  3. Create Nonce Source:
    • wp post create --post_type=page --post_status=publish --post_title="Public Page" --post_content='[premium_content_switcher]' (or any Premium Addons widget).

7. Expected Results

  • The unauthenticated request to admin-ajax.php returns the string "The admin password is: P4ssw0rd!".
  • Accessing the same ID via the standard frontend URL /?p=123 should result in a 404 for an unauthenticated user, confirming the "Sensitive Information Exposure" via the AJAX endpoint.

8. Verification Steps

  1. Check for existence of private post:
    • wp post get [ID] --field=post_status (Should be private).
  2. Confirm public access via standard URL fails:
    • Use http_request to GET /?p=[ID] and confirm it returns a 404 or redirect.
  3. Confirm exploit success:
    • Verify the string found in the AJAX response matches the post_content of the private post.

9. Alternative Approaches

  • Brute Forcing IDs: If no specific private ID is known, script a loop to iterate from 1 to 500 on the templateID parameter.
  • Different Actions: If premium_get_template_content is incorrect, search the plugin directory for the string get_template_content:
    • grep -r "get_template_content" /var/www/html/wp-content/plugins/premium-addons-for-elementor/
  • Check other status types: Test with --post_status=draft and --post_status=pending to verify the scope of the exposure.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Premium Addons for Elementor plugin is vulnerable to unauthorized information exposure via its AJAX-based template retrieval functionality. This occurs because the 'get_template_content' function lacks proper authorization and status checks, allowing unauthenticated attackers to view the content of private, draft, or pending WordPress posts and templates.

Vulnerable Code

// Likely located in includes/class-premium-addons-ajax.php or similar

public function get_template_content() {
    // Nonce check exists, but nonces are often public
    check_ajax_referer( 'premium-addons-nonce', 'nonce' );

    $template_id = isset( $_POST['templateID'] ) ? $_POST['templateID'] : '';

    if ( ! empty( $template_id ) ) {
        // VULNERABILITY: No check to see if the user has permission to view the specific post ID
        // No check to ensure the post status is 'publish'
        $content = \Elementor\Plugin::instance()->frontend->get_builder_content_for_display( $template_id );
        echo $content;
    }
    wp_die();
}

Security Fix

--- includes/class-premium-addons-ajax.php
+++ includes/class-premium-addons-ajax.php
@@ -102,6 +102,11 @@
 		public function get_template_content() {
 			check_ajax_referer( 'premium-addons-nonce', 'nonce' );
 
+			$post_id = isset( $_POST['templateID'] ) ? $_POST['templateID'] : '';
+			if ( ! current_user_can( 'edit_posts' ) && 'publish' !== get_post_status( $post_id ) ) {
+				wp_send_json_error( array( 'message' => 'Unauthorized' ) );
+			}
+
 			$template_id = isset( $_POST['templateID'] ) ? $_POST['templateID'] : '';
 
 			if ( ! empty( $template_id ) ) {

Exploit Outline

The exploit targets the AJAX endpoint of the plugin to leak content from restricted posts (Private, Draft, or Pending status). 1. **Identify the AJAX Action**: The vulnerable action is `premium_get_template_content`, which is accessible to unauthenticated users via the `wp_ajax_nopriv_` hook. 2. **Obtain a Nonce**: Attackers can find the required security nonce (`premium-addons-nonce`) by viewing the source code of any public page on the site where the plugin is active. The nonce is typically localized within the `PremiumAddonsSettings` or `pa_settings` JavaScript object. 3. **Request Private Content**: An unauthenticated HTTP POST request is sent to `/wp-admin/admin-ajax.php` with the following parameters: - `action`: `premium_get_template_content` - `nonce`: [EXTRACTED_NONCE] - `templateID`: The ID of the private or draft post/template to be retrieved. 4. **Data Extraction**: The server responds with the rendered HTML content of the target post, bypassing standard WordPress visibility restrictions.

Check if your site is affected.

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