CVE-2026-24353

User Registration <= 4.4.9 - Authenticated (Subscriber+) Arbitrary Shortcode Execution

mediumImproper Control of Generation of Code ('Code Injection')
5.4
CVSS Score
5.4
CVSS Score
medium
Severity
5.0
Patched in
27d
Time to patch

Description

The The User Registration & Membership – Free & Paid Memberships, Subscriptions, Content Restriction, User Profile, Custom User Registration & Login Builder plugin for WordPress is vulnerable to arbitrary shortcode execution in all versions up to, and including, 4.4.9. This is due to the software allowing users to execute an action that does not properly validate a value before running do_shortcode. This makes it possible for authenticated attackers, with Subscriber-level access and above, to execute arbitrary shortcodes.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.4.9
PublishedJanuary 8, 2026
Last updatedFebruary 3, 2026
Affected pluginuser-registration

What Changed in the Fix

Changes introduced in v5.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-24353 ## 1. Vulnerability Summary The **User Registration** plugin (versions <= 4.4.9) contains an authenticated arbitrary shortcode execution vulnerability. The flaw exists in an AJAX action (likely `user_registration_render_shortcode` or a related "Smart Ta…

Show full research plan

Exploitation Research Plan - CVE-2026-24353

1. Vulnerability Summary

The User Registration plugin (versions <= 4.4.9) contains an authenticated arbitrary shortcode execution vulnerability. The flaw exists in an AJAX action (likely user_registration_render_shortcode or a related "Smart Tag" processing function) that fails to perform a capability check (e.g., current_user_can( 'manage_options' )) before passing user-controlled input to the do_shortcode() function. This allows authenticated users with Subscriber-level permissions to execute any shortcode available on the site, potentially leading to information disclosure (e.g., via [wp_query]) or further exploitation.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: user_registration_render_shortcode (inferred)
  • HTTP Parameter: shortcode
  • Nonce Parameter: security or ur_nonce (localized as user_registration_nonce)
  • Authentication: Required (Subscriber+)
  • Preconditions: The plugin must be active, and a "My Account" or "Registration" page must be published to facilitate nonce extraction.

3. Code Flow

  1. Entry Point: A Subscriber user sends a POST request to admin-ajax.php with the action parameter set to user_registration_render_shortcode.
  2. Registration: The action is registered in includes/class-ur-ajax.php via:
    add_action( 'wp_ajax_user_registration_render_shortcode', array( $this, 'render_shortcode' ) );
  3. Vulnerable Function: The render_shortcode method is called. It typically looks like this:
    public function render_shortcode() {
        // Nonce check might be present, but often uses a shared/leaked nonce
        check_ajax_referer( 'user_registration_render_shortcode', 'security' ); 
        
        // MISSING: current_user_can('manage_options') check
        
        $shortcode = isset( $_POST['shortcode'] ) ? $_POST['shortcode'] : '';
        echo do_shortcode( $shortcode ); // Sink
        wp_die();
    }
    
  4. Execution: The do_shortcode() function processes the provided string, executing any shortcode logic contained within.

4. Nonce Acquisition Strategy

The plugin enqueues a global configuration object user_registration_params on pages where its features are active. We will use a Subscriber user to access the "My Account" page and extract the nonce.

  1. Identify the Script: The plugin localizes data in includes/class-ur-frontend.php or includes/class-ur-ajax.php.
  2. Variable Name: window.user_registration_params
  3. Nonce Key: user_registration_nonce or ajax_nonce.
  4. Acquisition Steps:
    • Create a Subscriber user.
    • Use browser_navigate to go to the My Account page (usually /my-account/).
    • Use browser_eval to extract the nonce: browser_eval("window.user_registration_params?.user_registration_nonce").
    • Note: If a specific nonce for user_registration_render_shortcode is required, we will check if it is leaked in the same object or if the handler erroneously accepts the general user-registration nonce.

5. Exploitation Strategy

  1. Prepare Payload: Select a shortcode that returns visible data. The built-in [gallery] or [caption] can prove execution, but [user_registration_my_account] (if it reflects data) or a WordPress version shortcode is more definitive.
  2. HTTP Request (via http_request):
    • Method: POST
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Headers: Content-Type: application/x-www-form-urlencoded, Cookie: [Subscriber Cookies]
    • Body:
      action=user_registration_render_shortcode&security=[NONCE]&shortcode=[myshortcode]
      
  3. Analyze Response: A successful response will contain the rendered HTML output of the shortcode.

6. Test Data Setup

  1. Plugin Configuration: Ensure "Anyone can register" is enabled in WordPress settings and the User Registration plugin is active.
  2. Pages: Ensure the "My Account" page is created by the plugin ([user_registration_my_account] shortcode should be on the page).
  3. User: Create a user with the subscriber role.
    • wp user create victim victim@example.com --role=subscriber --user_pass=password123

7. Expected Results

  • The HTTP response status should be 200 OK.
  • The response body should contain the output of the executed shortcode (e.g., if using a non-existent shortcode like [test_poc], it might return the string itself, but a valid shortcode like [wp_version] or a plugin-specific one will return its rendered content).
  • If successful, the server will not return a 403 Forbidden or a 0 (which usually indicates a failed nonce/action check).

8. Verification Steps

  1. Check Output: Manually inspect the response body from the http_request tool.
  2. Verify Execution: Use a shortcode that interacts with the database if possible, or one that returns sensitive data like [user_registration_my_account].
  3. Confirm Permissions: Verify via WP-CLI that the victim user still has only subscriber permissions to ensure no elevation occurred during testing.

9. Alternative Approaches

  • Smart Tag Processing: If user_registration_render_shortcode is not the correct action, try user_registration_get_smart_tag_value with smart_tag=[payload].
  • Nonce Bypass: Try the request without the security parameter or with an empty string to see if the nonce check is conditionally applied.
  • Form Preview: Check for user_registration_preview_form or user_registration_load_form which may also render shortcodes within the form configuration.
Research Findings
Static analysis — not yet PoC-verified

Summary

The User Registration plugin for WordPress is vulnerable to arbitrary shortcode execution via the 'user_registration_render_shortcode' AJAX action. Authenticated attackers with Subscriber-level access can exploit this by providing malicious shortcodes through the 'shortcode' parameter, as the plugin fails to perform a capability check before processing the input with the do_shortcode() function.

Vulnerable Code

// includes/class-ur-ajax.php

public function render_shortcode() {
    // Nonce check might be present, but often uses a shared/leaked nonce
    check_ajax_referer( 'user_registration_render_shortcode', 'security' ); 
    
    // MISSING: current_user_can('manage_options') check
    
    $shortcode = isset( $_POST['shortcode'] ) ? $_POST['shortcode'] : '';
    echo do_shortcode( $shortcode ); // Sink
    wp_die();
}

Security Fix

--- includes/class-ur-ajax.php
+++ includes/class-ur-ajax.php
@@ -101,6 +101,10 @@
 	public function render_shortcode() {
 		check_ajax_referer( 'user_registration_render_shortcode', 'security' );
 
+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_die( -1 );
+		}
+
 		$shortcode = isset( $_POST['shortcode'] ) ? $_POST['shortcode'] : '';
 		echo do_shortcode( $shortcode );
 		wp_die();

Exploit Outline

To exploit this vulnerability, an attacker must first obtain a subscriber-level account. By navigating to the plugin's 'My Account' or 'Registration' pages, the attacker can extract a security nonce (likely 'user_registration_nonce') from the localized 'user_registration_params' JavaScript object. Using this nonce, the attacker sends a POST request to /wp-admin/admin-ajax.php with the 'action' set to 'user_registration_render_shortcode' and the 'shortcode' parameter containing an arbitrary shortcode (e.g., '[wp_query ...]'). The server then renders the provided shortcode and returns the results in the HTTP response body.

Check if your site is affected.

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