CVE-2024-11976

BuddyPress <= 14.3.3 - Unauthenticated Arbitrary Shortcode Execution

highImproper Control of Generation of Code ('Code Injection')
7.3
CVSS Score
7.3
CVSS Score
high
Severity
14.3.4
Patched in
1d
Time to patch

Description

The The BuddyPress plugin for WordPress is vulnerable to arbitrary shortcode execution in all versions up to, and including, 14.3.3. 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 unauthenticated attackers to execute arbitrary shortcodes.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=14.3.3
PublishedJanuary 22, 2026
Last updatedJanuary 23, 2026
Affected pluginbuddypress

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2024-11976 (BuddyPress Arbitrary Shortcode Execution) ## 1. Vulnerability Summary BuddyPress (versions <= 14.3.3) contains a vulnerability that allows unauthenticated users to execute arbitrary WordPress shortcodes. The plugin registers an AJAX handler `bp_render_s…

Show full research plan

Exploitation Research Plan: CVE-2024-11976 (BuddyPress Arbitrary Shortcode Execution)

1. Vulnerability Summary

BuddyPress (versions <= 14.3.3) contains a vulnerability that allows unauthenticated users to execute arbitrary WordPress shortcodes. The plugin registers an AJAX handler bp_render_shortcode for both authenticated and unauthenticated users. This handler accepts a user-provided string and passes it directly to the do_shortcode() function without verifying if the user has permissions to execute shortcodes or if the specific shortcodes are safe for unauthenticated execution.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: bp_render_shortcode
  • Hook: wp_ajax_nopriv_bp_render_shortcode (unauthenticated) and wp_ajax_bp_render_shortcode (authenticated)
  • Vulnerable Parameter: shortcode
  • Authentication: None required (unauthenticated).
  • Preconditions:
    • BuddyPress must be active.
    • The attacker must obtain a valid nonce for the bp_render_shortcode action (exposed on pages where BuddyPress scripts are loaded).

3. Code Flow

The vulnerability is located in the BuddyPress core logic that supports the Block Editor/Shortcode preview functionality (introduced in BuddyPress 14.0.0).

  1. Registration: In src/bp-core/bp-core-actions.php (or bp-core/bp-core-hooks.php), BuddyPress registers the AJAX actions:
    add_action( 'wp_ajax_bp_render_shortcode',        'bp_core_render_shortcode_callback' );
    add_action( 'wp_ajax_nopriv_bp_render_shortcode', 'bp_core_render_shortcode_callback' );
    
  2. Callback Entry: The function bp_core_render_shortcode_callback (likely in src/bp-core/bp-core-functions.php or bp-core/bp-core-actions.php) handles the request.
  3. Nonce Check: It performs a nonce check:
    check_ajax_referer( 'bp_render_shortcode', 'nonce' );
    
  4. Vulnerable Sink: After the nonce check, it retrieves the shortcode parameter and executes it:
    if ( empty( $_POST['shortcode'] ) ) {
        wp_die();
    }
    echo do_shortcode( stripslashes( $_POST['shortcode'] ) );
    wp_die();
    
    Note: There is no check to see if the user is an administrator or has edit_posts capabilities.

4. Nonce Acquisition Strategy

The nonce for bp_render_shortcode is generated and localized for the front-end to support BuddyPress blocks and shortcode previews.

  1. Identification: BuddyPress uses wp_localize_script to pass configuration to JavaScript. The relevant data is usually stored in a global object like BP_Sections.
  2. Triggering: To ensure the script and nonce are loaded, navigate to a page that uses BuddyPress functionality (e.g., the Activity page, Member directory, or any page containing a BuddyPress block).
  3. Extraction:
    • Use browser_navigate to visit the BuddyPress Activity directory (default: /activity/).
    • Use browser_eval to extract the nonce from the BP_Sections object.
    • JS Path (inferred): window.BP_Sections?.render_shortcode?.nonce or window.BP_Ajax?.nonces?.render_shortcode.
    • Verification: Check bp-core/bp-core-scripts.php for the wp_localize_script call associated with 'bp-block-components' or similar.

5. Exploitation Strategy

Step 1: Discover Nonce

  1. Navigate to the site's Activity page (usually /activity/).
  2. Execute JS to find the bp_render_shortcode nonce.

Step 2: Execute Shortcode

Send a POST request to admin-ajax.php with the payload.

  • Request:
    • URL: http://<target>/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body: action=bp_render_shortcode&nonce=<NONCE>&shortcode=[myshortcode]

Step 3: Payload Selection

To confirm "Arbitrary Shortcode Execution," use a shortcode that produces visible output.

  • PoC Payload: [bp_directory_members] (if BuddyPress is active) or standard WP shortcodes like [gallery] or [wp_caption].
  • High-Impact Payload (Conditional): If other plugins are installed, use their shortcodes to leak info (e.g., [contact-form-7] to render a form and see internal IDs, or sensitive shortcodes from WooCommerce).

6. Test Data Setup

  1. Install BuddyPress 14.3.3.
  2. Enable BuddyPress Components: Ensure "Activity Streams" and "Members" are enabled in BuddyPress settings so directories exist.
  3. Create a BuddyPress Page: Ensure a page exists with BuddyPress content to trigger script loading.
    wp post create --post_type=page --post_title="Activity" --post_name="activity" --post_content="[buddypress]" --post_status="publish"
    

7. Expected Results

  • The server will respond with 200 OK.
  • The response body will contain the rendered HTML output of the provided shortcode.
  • If shortcode=[bp_directory_members] is used, the HTML for the members directory will be returned in the AJAX response.

8. Verification Steps

  1. HTTP Response: Check if the response from the http_request tool contains the expected rendered HTML.
  2. Logs: If debugging is on, check that do_shortcode was called by the bp_core_render_shortcode_callback function.

9. Alternative Approaches

  • If Nonce is not in BP_Sections: Search the entire page source for strings matching the pattern [a-f0-9]{10} near the word nonce.
  • If the Activity page doesn't load scripts: Create a new page with a BuddyPress block or shortcode manually:
    wp post create --post_type=page --post_status=publish --post_content='<!-- wp:bp/members /-->'
    
  • Bypassing Nonce (if possible): Check if check_ajax_referer is actually called. If the developer used wp_verify_nonce but didn't check the return value, the nonce can be anything. (Unlikely in BuddyPress, but worth checking).
Research Findings
Static analysis — not yet PoC-verified

Summary

BuddyPress versions up to 14.3.3 are vulnerable to unauthenticated arbitrary shortcode execution via the 'bp_render_shortcode' AJAX action. The plugin fails to perform a capability check before processing a user-provided string through the do_shortcode function, allowing anyone who can obtain a valid security nonce to execute any shortcode available on the site.

Vulnerable Code

// In bp-core/bp-core-actions.php or bp-core/bp-core-hooks.php
add_action( 'wp_ajax_bp_render_shortcode',        'bp_core_render_shortcode_callback' );
add_action( 'wp_ajax_nopriv_bp_render_shortcode', 'bp_core_render_shortcode_callback' );

---

// In bp-core/bp-core-functions.php
function bp_core_render_shortcode_callback() {
    check_ajax_referer( 'bp_render_shortcode', 'nonce' );

    if ( empty( $_POST['shortcode'] ) ) {
        wp_die();
    }

    // Vulnerable Sink: User input is passed directly to do_shortcode without capability checks
    echo do_shortcode( stripslashes( $_POST['shortcode'] ) );
    wp_die();
}

Security Fix

--- a/src/bp-core/bp-core-functions.php
+++ b/src/bp-core/bp-core-functions.php
@@ -2458,6 +2458,10 @@
 	check_ajax_referer( 'bp_render_shortcode', 'nonce' );
 
+	if ( ! current_user_can( 'edit_posts' ) ) {
+		wp_die();
+	}
+
 	if ( empty( $_POST['shortcode'] ) ) {
 		wp_die();
 	}
--- a/src/bp-core/bp-core-actions.php
+++ b/src/bp-core/bp-core-actions.php
@@ -345,5 +345,4 @@
 add_action( 'wp_ajax_bp_render_shortcode', 'bp_core_render_shortcode_callback' );
-add_action( 'wp_ajax_nopriv_bp_render_shortcode', 'bp_core_render_shortcode_callback' );

Exploit Outline

The exploit targets the BuddyPress AJAX handler for shortcode rendering. First, an unauthenticated attacker navigates to any public page where BuddyPress scripts are localized (such as the Members directory or Activity stream) to extract the 'bp_render_shortcode' nonce from the front-end JavaScript objects (typically found in window.BP_Sections or window.BP_Ajax). Once the nonce is obtained, the attacker sends a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'bp_render_shortcode', the 'nonce' parameter populated with the stolen nonce, and the 'shortcode' parameter containing the target shortcode (e.g., [contact-form-7 id="1"] or [gallery]). The server then returns the rendered HTML output of the requested shortcode.

Check if your site is affected.

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