BuddyPress <= 14.3.3 - Unauthenticated Arbitrary Shortcode Execution
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:LTechnical Details
<=14.3.3Source Code
WordPress.org SVN# 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) andwp_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_shortcodeaction (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).
- Registration: In
src/bp-core/bp-core-actions.php(orbp-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' ); - Callback Entry: The function
bp_core_render_shortcode_callback(likely insrc/bp-core/bp-core-functions.phporbp-core/bp-core-actions.php) handles the request. - Nonce Check: It performs a nonce check:
check_ajax_referer( 'bp_render_shortcode', 'nonce' ); - Vulnerable Sink: After the nonce check, it retrieves the
shortcodeparameter and executes it:
Note: There is no check to see if the user is an administrator or hasif ( empty( $_POST['shortcode'] ) ) { wp_die(); } echo do_shortcode( stripslashes( $_POST['shortcode'] ) ); wp_die();edit_postscapabilities.
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.
- Identification: BuddyPress uses
wp_localize_scriptto pass configuration to JavaScript. The relevant data is usually stored in a global object likeBP_Sections. - 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).
- Extraction:
- Use
browser_navigateto visit the BuddyPress Activity directory (default:/activity/). - Use
browser_evalto extract the nonce from theBP_Sectionsobject. - JS Path (inferred):
window.BP_Sections?.render_shortcode?.nonceorwindow.BP_Ajax?.nonces?.render_shortcode. - Verification: Check
bp-core/bp-core-scripts.phpfor thewp_localize_scriptcall associated with 'bp-block-components' or similar.
- Use
5. Exploitation Strategy
Step 1: Discover Nonce
- Navigate to the site's Activity page (usually
/activity/). - Execute JS to find the
bp_render_shortcodenonce.
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]
- URL:
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
- Install BuddyPress 14.3.3.
- Enable BuddyPress Components: Ensure "Activity Streams" and "Members" are enabled in BuddyPress settings so directories exist.
- 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
- HTTP Response: Check if the response from the
http_requesttool contains the expected rendered HTML. - Logs: If debugging is on, check that
do_shortcodewas called by thebp_core_render_shortcode_callbackfunction.
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 wordnonce. - 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_refereris actually called. If the developer usedwp_verify_noncebut didn't check the return value, the nonce can be anything. (Unlikely in BuddyPress, but worth checking).
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
@@ -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(); } @@ -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.