CVE-2026-5149

RTMKit <= 2.0.7 - Authenticated (Contributor+) Missing Authorization to Arbitrary Form Submission Access via 'entries_id' Parameter

mediumIncorrect Authorization
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
2.0.8
Patched in
1d
Time to patch

Description

The RTMKit plugin for WordPress is vulnerable to Incorrect Authorization in all versions up to, and including, 2.0.7 This is due to the get_submission_content AJAX endpoint lacking a capability check to verify that a user has permission to access the requested form submission data. This makes it possible for authenticated attackers, with Contributor-level access and above, to view arbitrary form submissions from other users by iterating the entries_id parameter.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.0.7
PublishedJune 15, 2026
Last updatedJune 16, 2026

What Changed in the Fix

Changes introduced in v2.0.8

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan focuses on **CVE-2026-5149**, an Incorrect Authorization vulnerability in the **RTMKit (RomeThemeKit)** plugin for WordPress. --- ### 1. Vulnerability Summary The RTMKit plugin (versions ≤ 2.0.7) registers an AJAX endpoint `get_submission_content` (likely within the…

Show full research plan

This exploitation research plan focuses on CVE-2026-5149, an Incorrect Authorization vulnerability in the RTMKit (RomeThemeKit) plugin for WordPress.


1. Vulnerability Summary

The RTMKit plugin (versions ≤ 2.0.7) registers an AJAX endpoint get_submission_content (likely within the SubmissionModule) that is intended to retrieve form submission data. The vulnerability arises because this endpoint fails to perform a capability check (e.g., current_user_can('manage_options')) or an ownership check on the requested data.

Authenticated users with Contributor-level permissions or higher can exploit this to view arbitrary form submissions—potentially containing sensitive PII (Personally Identifiable Information)—by iterating through the entries_id parameter.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: get_submission_content (Inferred AJAX action)
  • Vulnerable Parameter: entries_id
  • Authentication: Authenticated (Contributor+)
  • Required Header: Content-Type: application/x-www-form-urlencoded
  • Nonce Action: rtmkit_nonce (Required by the plugin's API pattern)

3. Code Flow

While the specific source for the SubmissionModule is truncated, the execution flow is grounded in the provided PluginApi.php and Plugin.php files:

  1. Registration: The Plugin class initializes SubmissionModule (Line 183 of Plugin.php).
  2. AJAX Hook: The module likely registers wp_ajax_get_submission_content.
  3. Vulnerable Handler: The handler function (likely get_submission_content) is invoked.
  4. Insecure Authorization: Unlike PluginApi::get_content() (which checks for manage_options), the submission handler fails to verify if the current user should have access to the entry identified by $_POST['entries_id'].
  5. Data Sink: The code queries the database for the submission corresponding to the ID and returns the content via wp_send_json_success().

4. Nonce Acquisition Strategy

The plugin uses a nonce check: check_ajax_referer('rtmkit_nonce', 'nonce'). To obtain a valid nonce as a Contributor:

  1. Identify Trigger: The nonce is likely localized for the "System Panel" or the Form Submission management area in the admin dashboard.
  2. Setup Page: A Contributor can access the WordPress admin dashboard.
  3. Extraction:
    • Navigate to the RTMKit dashboard or a page where the plugin's admin scripts are loaded (e.g., /wp-admin/admin.php?page=rtmkit).
    • Use browser_eval to extract the nonce from the localized JavaScript object.
    • Inferred Variable: Based on the script handle rtmkit-system-panel, the variable is likely rtmkit_panel_vars or similar.
    • Command: browser_eval("window.rtmkit_panel_vars?.nonce") or search for rtmkit_nonce in the global scope.

5. Exploitation Strategy

The goal is to demonstrate unauthorized access to a form submission created by another user (e.g., an Admin or a public visitor).

Step 1: Authenticate
Authenticate as a Contributor-level user.

Step 2: Nonce Retrieval
Fetch the nonce using the strategy in Section 4.

Step 3: Data Iteration
Send a series of POST requests to retrieve submissions.

  • Request URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Body:
    action=get_submission_content&nonce=[NONCE]&entries_id=[ID]
    
  • Example Payload (entries_id=1):
    action=get_submission_content&nonce=a1b2c3d4e5&entries_id=1
    

Step 4: Analyze Response
A successful exploit will return a JSON object with success: true and the submission data in the data field, even if the user is not an admin.

6. Test Data Setup

  1. Form Creation: Create a form using the RTMKit Form widget (requires Elementor).
  2. Submission: Submit the form as an unauthenticated visitor or an Admin user with test data (e.g., email: admin-secret@example.com).
  3. User Creation: Create a user with the Contributor role.
  4. Note ID: Identify the ID of the submission in the database (e.g., via wp_rtmkit_submissions table) to target it specifically.

7. Expected Results

  • Unauthorized Access: The Contributor receives the full content of the submission (e.g., name, email, message) in the JSON response.
  • HTTP 200 OK: The server returns a successful response instead of an "Access Denied" error or 403 status.

8. Verification Steps

After the HTTP request, verify the vulnerability using WP-CLI:

  1. Check Capability: Verify that the current user lacks the manage_options capability:
    wp user cap list [CONTRIBUTOR_ID]
  2. Compare Data: Verify that the data returned in the AJAX response matches the data stored in the database for that entries_id:
    wp db query "SELECT * FROM wp_rtmkit_submissions WHERE id = [ID]" (Note: Table name is inferred).

9. Alternative Approaches

  • Direct Parameter Manipulation: If entries_id is not the only parameter, check for entry_id or submission_id.
  • GET Request: While check_ajax_referer usually looks at $_REQUEST, try sending the payload via GET if POST is blocked, as some plugins do not restrict the method.
  • ID Brute-forcing: If a specific ID is unknown, use a loop to iterate IDs from 1 to 500 to discover existing submissions.
Research Findings
Static analysis — not yet PoC-verified

Summary

The RTMKit plugin for WordPress is vulnerable to Incorrect Authorization in versions up to 2.0.7. The 'get_submission_content' AJAX endpoint fails to verify if the requesting user has administrative permissions, allowing authenticated attackers with Contributor-level access to view arbitrary form submissions by iterating the 'entries_id' parameter.

Vulnerable Code

// Inc/Core/Plugin.php
// The plugin initializes the SubmissionModule which handles form data
$this->modules = [
    // ...
    'submission' => \RTMKit\Modules\Submission\SubmissionModule::class,
    // ...
];

--- 

// Inferred logic within the SubmissionModule handler for 'get_submission_content'
// The vulnerability occurs because the function lacks authorization checks
public function get_submission_content() {
    check_ajax_referer('rtmkit_nonce', 'nonce');
    // Missing: if (!current_user_can('manage_options')) { wp_die(); }
    $id = $_POST['entries_id'];
    // ... query database and return submission content
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/rometheme-for-elementor/2.0.7/Inc/Core/PluginApi.php /home/deploy/wp-safety.org/data/plugin-versions/rometheme-for-elementor/2.0.8/Inc/Core/PluginApi.php
--- /home/deploy/wp-safety.org/data/plugin-versions/rometheme-for-elementor/2.0.7/Inc/Core/PluginApi.php	2026-04-20 10:59:40.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/rometheme-for-elementor/2.0.8/Inc/Core/PluginApi.php	2026-06-11 05:50:12.000000000 +0000
@@ -2,6 +2,8 @@
 
 namespace RTMKit\Core;
 
+if (! defined('ABSPATH')) exit;
+
 class PluginApi
 {
@@ -55,14 +57,27 @@
 
     public function get_content()
     {
-        check_ajax_referer('rtmkit_nonce', 'nonce');
+        $nonce = isset($_POST['nonce'])
+            ? sanitize_text_field(wp_unslash($_POST['nonce']))
+            : '';
+
+        if (! wp_verify_nonce($nonce, 'rtmkit_nonce')) {
+            die(__('Security check', 'rometheme-for-elementor'));
+        }
+        
+        // check_ajax_referer('rtmkit_nonce', 'nonce');
         if (!current_user_can('manage_options')) {
             wp_send_json_error('Access Denied.');
             wp_die();
         }
-        $path = sanitize_text_field($_POST['path']);
-        $menus = \RTMKit\Modules\Menu::instance()->get_menu_by_path($_POST['path']);
 
+        $path = isset($_POST['path'])
+            ? sanitize_text_field(wp_unslash($_POST['path']))
+            : '';
+        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+        $menus = \RTMKit\Modules\Menu::instance()->get_menu_by_path($path);

Exploit Outline

1. Authenticate to the WordPress dashboard as a user with Contributor-level privileges. 2. Identify and extract the 'rtmkit_nonce' value, which is commonly localized for scripts in the RTMKit dashboard or system panel. 3. Construct an AJAX POST request to '/wp-admin/admin-ajax.php' with the following body: 'action=get_submission_content&nonce=[NONCE]&entries_id=[TARGET_ID]'. 4. Send the request and capture the response. Because the server does not verify administrative capabilities for this action, it will return the full submission data for the specified ID, including any PII submitted via forms.

Check if your site is affected.

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