Team – Team Members Showcase Plugin <= 5.0.11 - Missing Authorization
Description
The Team – Team Members Showcase Plugin plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 5.0.11. 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:NTechnical Details
What Changed in the Fix
Changes introduced in v5.0.12
Source Code
WordPress.org SVN# Research Plan: CVE-2026-25026 - Missing Authorization in Team Members Showcase Plugin ## 1. Vulnerability Summary The **Team – Team Members Showcase Plugin** (up to version 5.0.11) is vulnerable to **Missing Authorization** and **Insecure Direct Object Reference (IDOR)**. The AJAX handler `tlp_te…
Show full research plan
Research Plan: CVE-2026-25026 - Missing Authorization in Team Members Showcase Plugin
1. Vulnerability Summary
The Team – Team Members Showcase Plugin (up to version 5.0.11) is vulnerable to Missing Authorization and Insecure Direct Object Reference (IDOR). The AJAX handler tlp_team_smart_popup, registered for both authenticated and unauthenticated users, fails to validate the id parameter. Specifically, it does not check if the requested ID belongs to the expected team post type or if the user has permission to view the content of that specific ID.
This allows an unauthenticated attacker to retrieve the content and metadata of arbitrary posts (including private posts, pages, or sensitive metadata from other plugins) by providing their numeric ID.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
tlp_team_smart_popup - Vulnerable Parameter:
id(The ID of the post to retrieve) - Nonce Parameter:
rt_nonce(verified viaFns::getNonce()) - Authentication: Unauthenticated (via
wp_ajax_nopriv_tlp_team_smart_popup) - Preconditions:
- The plugin must be active.
- An attacker needs a valid WordPress nonce for the
tlp-team-nonceaction (obtainable from any page rendering a Team shortcode). - The attacker needs to guess or discover the ID of a target private post/page.
3. Code Flow
- Entry Point: The plugin registers the AJAX actions in
app/Controllers/Frontend/Ajax/SmartPopup.php:add_action( 'wp_ajax_tlp_team_smart_popup', [ $this, 'response' ] ); add_action( 'wp_ajax_nopriv_tlp_team_smart_popup', [ $this, 'response' ] ); - Nonce Check: The
response()method first verifies a nonce:if ( ! wp_verify_nonce( Fns::getNonce(), Fns::nonceText() ) ) { ... } - Object Retrieval: It then fetches a post object directly from the user-supplied
id:$post = get_post( absint( $_REQUEST['id'] ) ); setup_postdata( $post ); - Data Extraction: It extracts the post title and content:
Note:$name = $post->post_title; $tlp_member_content = wpautop( get_the_content() );get_the_content()insidesetup_postdatawill return the content of the post object even if it is private, as long as the object was successfully retrieved by ID. - Metadata Leakage: It also attempts to fetch various meta fields (e.g.,
email,telephone,ttp_my_resume). While these are specific to the "team" type, an attacker can also see the main content of any post type. - Response: The gathered data is returned in a JSON response:
wp_send_json( [ 'data' => wp_kses_post( $html ), ... ] );
4. Nonce Acquisition Strategy
The plugin enqueues its scripts and localizes the required nonce on pages where the team showcase is displayed.
- Trigger: The shortcode
[tlpteam](as inferred fromREADME.txt). - JS Variable:
rt_team_ajax(standard for RadiusTheme/TLP plugins). - Nonce Key:
rt_nonce. - Extraction Steps:
- Create a "Team Member" post so the shortcode has something to render.
- Create a public page containing the
[tlpteam]shortcode. - Use the
browser_navigatetool to visit that page. - Use
browser_evalto extract the nonce:window.rt_team_ajax?.rt_nonce.
5. Exploitation Strategy
- Target Identification: Determine the ID of a private post or page (e.g., ID 123).
- AJAX Request: Use the
http_requesttool to send a POST request toadmin-ajax.php.- Method: POST
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=tlp_team_smart_popup&id=123&rt_nonce=[EXTRACTED_NONCE]
- Response Parsing: Check the
datafield in the JSON response for the title and content of the private post.
6. Test Data Setup
- Target Content: Create a private post containing sensitive information:
wp post create --post_type=post --post_title="Confidential Internal Note" --post_content="The secret password is: Flag{IDOR_DATA_LEAK}" --post_status=private # Note the returned ID (e.g., 5) - Plugin Setup: Create a dummy team member to ensure shortcode functionality:
wp post create --post_type=team --post_title="Visible Member" --post_status=publish - Nonce Page: Create a page to expose the nonce:
wp post create --post_type=page --post_title="Team Showcase" --post_content='[tlpteam]' --post_status=publish
7. Expected Results
- The AJAX response should have a
success: truestatus. - The
dataproperty in the JSON response will contain the HTML markup including the string:"The secret password is: Flag{IDOR_DATA_LEAK}". - This confirms that an unauthenticated user accessed the content of a
privatepost via the vulnerable AJAX endpoint.
8. Verification Steps
- Execute the HTTP request as described in Section 5.
- Verify the response contains the content of the private post created in Section 6.
- To confirm the vulnerability is due to missing type checks, attempt to retrieve the content of a
pageor ashop_order(if WooCommerce is present) by ID.
9. Alternative Approaches
- Metadata Enumeration: If the target post is a "Team" member but set to private/draft, the exploit can leak their
email,telephone, andlocationmeta fields even if they aren't published. - Parameter Variation: If
rt_noncefails, check if the plugin falls back to_wpnonceby inspecting theFns::getNonce()logic (if accessible) or trying_wpnoncein the request body. - Different Layouts: If the
[tlpteam]shortcode doesn't load the script, try more specific variants mentioned in the README like[tlpteam layout="layout1"].
Summary
The Team – Team Members Showcase Plugin is vulnerable to unauthorized data disclosure due to a lack of authorization and post-status validation in its AJAX popup handler. Unauthenticated attackers can exploit this to retrieve the title, content, and metadata of any WordPress post or page, including those set to private or belonging to other post types, by supplying a numeric post ID.
Vulnerable Code
// app/Controllers/Frontend/Ajax/SmartPopup.php lines 38-55 public function response() { $html = $htmlCInfo = null; $success = false; $error = true; if ( ! wp_verify_nonce( Fns::getNonce(), Fns::nonceText() ) ) { wp_send_json_error( [ 'data' => __('Security Issue','tlp-team'), 'error' => $error, ] ); } if ( ! empty( $_REQUEST['id'] ) ) { global $post; $post = get_post( absint( $_REQUEST['id'] ) ); setup_postdata( $post ); $settings = get_option( rttlp_team()->options['settings'] ); $resume_btn_text = isset( $settings['resume_btn_text'] ) ? $settings['resume_btn_text'] : "Resume";
Security Fix
@@ -45,6 +45,14 @@ 'error' => $error, ] ); } + + $member_post = get_post(absint($_REQUEST['id']) ); + if ( + !$member_post || + $member_post->post_type !== rttlp_team()->post_type || + $member_post->post_status !== 'publish' + ) { + wp_send_json_error(array('error' => __('Unauthorized or member not found','tlp-team')), 403); + } + if ( ! empty( $_REQUEST['id'] ) ) { global $post; $post = get_post( absint( $_REQUEST['id'] ) );
Exploit Outline
1. Locate a public page on the target site that uses the plugin's team showcase (e.g., via the `[tlpteam]` shortcode) to extract a valid nonce. 2. Extract the security nonce from the global JavaScript object `rt_team_ajax.rt_nonce` found in the page source. 3. Identify the target post ID (e.g., a private post or sensitive page) via enumeration or discovery. 4. Send a POST request to `/wp-admin/admin-ajax.php` with the action set to `tlp_team_smart_popup`, the `id` parameter set to the target post ID, and the `rt_nonce` parameter set to the extracted nonce. 5. The server will respond with a JSON object where the `data` field contains the rendered HTML of the targeted post, revealing its title and content regardless of its visibility status or post type.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.