CVE-2026-24556

ElementCamp <= 2.3.2 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.3.6
Patched in
7d
Time to patch

Description

The ElementCamp plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.3.2. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.3.2
PublishedJanuary 22, 2026
Last updatedJanuary 28, 2026
Affected pluginelement-camp

What Changed in the Fix

Changes introduced in v2.3.6

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-24556 (ElementCamp) ## 1. Vulnerability Summary The **ElementCamp** plugin (versions <= 2.3.2) is vulnerable to **Missing Authorization** in its AJAX handlers. Specifically, the function `tcg_create_dynamic_block` is registered for unauthenticated users (`wp_a…

Show full research plan

Exploitation Research Plan: CVE-2026-24556 (ElementCamp)

1. Vulnerability Summary

The ElementCamp plugin (versions <= 2.3.2) is vulnerable to Missing Authorization in its AJAX handlers. Specifically, the function tcg_create_dynamic_block is registered for unauthenticated users (wp_ajax_nopriv_tcg_create_dynamic_block) in elementor/elementor-addon.php.

The function likely lacks both a capability check (current_user_can) and a nonce check (check_ajax_referer), allowing any unauthenticated attacker to create new dynamic blocks/templates (Post Type: tcg_teb) on the WordPress site. This results in a low-integrity impact as attackers can inject unauthorized content into the database.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: tcg_create_dynamic_block (Registered for both authenticated and unauthenticated users).
  • Method: POST
  • Authentication: None required (unauthenticated).
  • Preconditions: Plugin must be active. Elementor should ideally be installed (though the AJAX handler may run regardless).

3. Code Flow

  1. Entry Point: admin-ajax.php receives a request with action=tcg_create_dynamic_block.
  2. Hook Registration: In elementor/elementor-addon.php, the action is registered:
    add_action( 'wp_ajax_nopriv_tcg_create_dynamic_block', 'tcg_create_dynamic_block' );
    add_action( 'wp_ajax_tcg_create_dynamic_block', 'tcg_create_dynamic_block' );
    
  3. Vulnerable Sink: The function tcg_create_dynamic_block (truncated in source) is called. Based on the plugin's structure and function naming:
    • It retrieves parameters such as title, template_type, and potentially data.
    • It calls wp_insert_post() to create a post of type tcg_teb (identified in themescamp_notification_choices and themescamp_offcanvas_choices).
    • It likely uses update_post_meta() to set the template_type.
  4. Missing Check: No authorization check is performed before the database write.

4. Nonce Acquisition Strategy

Based on elementor/controls/Select2.php, the plugin does not localize a nonce for its Select2 AJAX actions, and the corresponding JavaScript in elementor/assets/js/tcg-select2.js does not send one. If tcg_create_dynamic_block follows this pattern, no nonce is required.

If a nonce is discovered during manual inspection:

  1. Identify where dynamic-editor.js or tcg-select2.js is enqueued.
  2. Create a post using the [element-camp] (or similar) shortcode if required to load the scripts.
  3. Navigate to the page.
  4. Use browser_eval to extract the nonce from the localized object (likely tcg_select2_localize or a similar global variable).

Current Assumption: No nonce is enforced for tcg_create_dynamic_block.

5. Exploitation Strategy

The goal is to create an unauthorized post of type tcg_teb.

Request Details

  • Tool: http_request
  • URL: {{BASE_URL}}/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=tcg_create_dynamic_block&title=Unauthorized+Template&template_type=notification
    
    (Note: template_type values like notification or offcanvas are valid per themescamp_notification_choices).

Expected Response

A successful request should return a JSON response, likely containing a success: true flag and the newly created post_id.

{"success":true,"data":{"post_id":123}}

6. Test Data Setup

  1. Install and activate the ElementCamp plugin (v2.3.2).
  2. Install and activate Elementor (dependency).
  3. Confirm the existence of the tcg_teb post type (can be checked via wp post-type list).

7. Expected Results

  • The AJAX request returns a 200 OK with a success JSON body.
  • A new post is created in the WordPress database with the title "Unauthorized Template" and post type tcg_teb.
  • The post meta template_type for the new post is set to notification.

8. Verification Steps

After the HTTP request, use WP-CLI to verify the state:

# Check if the post was created
wp post list --post_type=tcg_teb --fields=ID,post_title,post_status

# Verify the meta value
wp post meta get <ID> template_type

9. Alternative Approaches

If tcg_create_dynamic_block fails, examine the other Select2 AJAX actions which are likely also missing authorization:

  1. Action: tcg_select2_search_post
    • Parameters: post_type=post&term=secret
    • Goal: Information Disclosure of private post titles (though CVSS suggests Integrity impact is primary).
  2. Action: tcg_select2_get_title
    • Parameters: post_type=post&id[]=1
    • Goal: Retrieve titles of private posts by ID.

If the tcg_teb post type requires specific Elementor data to be "valid," the payload may need to include a data parameter containing a JSON-encoded Elementor structure (e.g., data=[{"elType":"section",...}]).

Research Findings
Static analysis — not yet PoC-verified

Summary

The ElementCamp plugin for WordPress (versions <= 2.3.2) is vulnerable to unauthorized access because it fails to perform capability and nonce checks on several AJAX handlers. This allow unauthenticated attackers to perform actions such as creating unauthorized dynamic block templates (post type tcg_teb) or querying existing post information.

Vulnerable Code

// elementor/elementor-addon.php:351
add_action( 'wp_ajax_nopriv_tcg_create_dynamic_block', 'tcg_create_dynamic_block' );
add_action( 'wp_ajax_tcg_create_dynamic_block', 'tcg_create_dynamic_block' );

if ( ! function_exists( 'tcg_create_dynamic_block' ) ) {
function tcg_create_dynamic_block() {
// ... lacks current_user_can() and check_ajax_referer() ...

---

// elementor/controls/Select2.php:31
wp_localize_script(
    'tcg-select2',
    'tcg_select2_localize',
    [
        'ajaxurl'         => esc_url( admin_url( 'admin-ajax.php' ) ),
        'search_text'     => esc_html__( 'Search', 'themescamp-plugin' ),
        // Missing security nonce field
    ]
);

---

// elementor/assets/js/tcg-select2.js:10
data: function ( params ) {
    return {
        action: 'tcg_select2_search_post',
        post_type: obj.data.source_type,
        // ... no security token passed ...
    }
}

Security Fix

diff -ru element-camp/elementor/assets/js/tcg-select2.js element-camp/elementor/assets/js/tcg-select2.js
--- element-camp/elementor/assets/js/tcg-select2.js
+++ element-camp/elementor/assets/js/tcg-select2.js
@@ -11,6 +11,7 @@
                     data: function ( params ) {
                         return {
                             action: 'tcg_select2_search_post',
+                            security: tcg_select2_localize.security,
                             post_type: obj.data.source_type,
                             source_name: obj.data.source_name,
@@ -42,6 +43,7 @@
                             url: tcg_select2_localize.ajaxurl,
                             data: {
                                 action: 'tcg_select2_get_title',
+                                security: tcg_select2_localize.security,
                                 post_type: obj.data.source_type, 
diff -ru element-camp/elementor/controls/Select2.php element-camp/elementor/controls/Select2.php
--- element-camp/elementor/controls/Select2.php
+++ element-camp/elementor/controls/Select2.php
@@ -28,6 +28,7 @@
     			'tcg_select2_localize',
     			[
     				'ajaxurl'         => esc_url( admin_url( 'admin-ajax.php' ) ),
+    				'security'        => wp_create_nonce( 'tcg_select2_nonce' ),
     				'search_text'     => esc_html__( 'Search', 'themescamp-plugin' ),
diff -ru element-camp/elementor/elementor-init.php element-camp/elementor/elementor-init.php
--- element-camp/elementor/elementor-init.php
+++ element-camp/elementor/elementor-init.php
@@ -3,5 +3,4 @@
 
 include('controls/Select2.php');
 include('controls/helper.php');
-include('elementor-addon.php');
 include('extender/class-extender.php');

Exploit Outline

An unauthenticated attacker can exploit this vulnerability by sending a POST request to the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) with the action 'tcg_create_dynamic_block'. The payload should include a 'title' and 'template_type' (e.g., 'notification' or 'offcanvas'). Because the handler lacks authorization and nonce verification, the plugin will create a new post of type 'tcg_teb' in the database. Furthermore, attackers can use the 'tcg_select2_search_post' and 'tcg_select2_get_title' actions without authentication to search for and retrieve titles of existing posts.

Check if your site is affected.

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