WP Database Backup <= 7.11 - Authenticated (Administrator+) OS Command Injection via 'wp_db_exclude_table' Parameter
Description
The WP Database Backup – Unlimited Database & Files Backup by Backup for WP plugin for WordPress is vulnerable to OS Command Injection in all versions up to and including 7.11 via the `wp_db_exclude_table` parameter. This is due to the direct concatenation of user-supplied `$_POST['wp_db_exclude_table']` values into the `mysqldump` shell command string in the `mysqldump()` function of `includes/admin/class-wpdb-admin.php` without wrapping them in `escapeshellarg()`—every other argument in the same command (DB_USER, DB_PASSWORD, host, filename, DB_NAME) is properly escaped, making the exclude-table values the sole exception—and because the only applied filtering, `sanitize_text_field()` via `recursive_sanitize_text_field()`, strips HTML tags but leaves shell metacharacters such as `;`, `|`, `` ` ``, and `$()` intact. This makes it possible for authenticated attackers, with administrator-level access and above, to execute arbitrary operating system commands on the server, potentially enabling full remote code execution. The injection is stored: malicious values submitted through the plugin settings form are persisted to the WordPress options table via `update_option('wp_db_exclude_table')` and later retrieved with `get_option()` and passed unsanitized to `shell_exec()` whenever a backup operation runs.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=7.11What Changed in the Fix
Changes introduced in v7.12
Source Code
WordPress.org SVNI cannot fulfill your request to provide a detailed exploitation research plan or actionable payloads for CVE-2026-9834. My purpose is to be helpful and harmless, and generating instructions that facilitate the exploitation of security vulnerabilities—even for research or proof-of-concept purposes—p…
Show full research plan
I cannot fulfill your request to provide a detailed exploitation research plan or actionable payloads for CVE-2026-9834. My purpose is to be helpful and harmless, and generating instructions that facilitate the exploitation of security vulnerabilities—even for research or proof-of-concept purposes—poses significant real-world risks.
Instead, I can provide a technical analysis of the vulnerability from a defensive perspective and explain how such issues can be identified and remediated in WordPress plugin development.
Technical Analysis: OS Command Injection in PHP
OS Command Injection occurs when an application passes unvalidated or improperly sanitized user input to a system shell. In the case of CVE-2026-9834, the vulnerability stems from how the plugin constructs and executes the mysqldump command.
The Role of shell_exec() and mysqldump
In WordPress backup plugins, it is common to use the system's mysqldump utility via PHP functions like exec(), passthru(), or shell_exec(). These functions execute a string as a command in the underlying operating system.
A vulnerable implementation might look like this:
// Vulnerable Code Example
$exclude_table = get_option('wp_db_exclude_table'); // User-controlled value
$command = "mysqldump --user=$user --password=$pass $db_name --ignore-table=$exclude_table > $backup_file";
shell_exec($command);
If the $exclude_table variable contains shell metacharacters, the shell will interpret them. For example, if a user provides mytable; touch /tmp/pwned, the resulting command becomes:
mysqldump ... --ignore-table=mytable; touch /tmp/pwned > ...
The semicolon (;) acts as a command separator, causing the system to execute touch /tmp/pwned after the mysqldump attempt.
Limitations of sanitize_text_field()
The vulnerability report indicates that the input was processed with sanitize_text_field(). This is a common point of failure because sanitize_text_field() is designed to prevent Cross-Site Scripting (XSS) and other text-based injection by stripping HTML tags and trailing whitespace. It does not, however, neutralize shell metacharacters like ;, |, &, $(), or `.
Remediation Strategies
To prevent OS Command Injection, developers should follow these best practices:
Use
escapeshellarg()for Every Argument: Any variable that is part of a shell command must be wrapped inescapeshellarg(). This function adds single quotes around the string and quotes/escapes any existing single quotes, ensuring the entire string is treated as a single literal argument by the shell.// Secure Remediation $command = sprintf( "mysqldump --user=%s --password=%s %s --ignore-table=%s > %s", escapeshellarg($user), escapeshellarg($pass), escapeshellarg($db_name), escapeshellarg($exclude_table), escapeshellarg($backup_file) ); shell_exec($command);Input Validation (Allowlisting): For parameters like table names, the most secure approach is to validate the input against an allowlist (e.g., ensuring the table name actually exists in the database) or ensuring it only contains alphanumeric characters and underscores.
Avoid Shell Execution When Possible: Whenever possible, use native PHP libraries or APIs (like
PDOormysqlifor database operations) instead of calling system binaries via the shell.
For further information on secure coding practices in WordPress, I recommend reviewing the WordPress Plugin Handbook section on Security and the OWASP Command Injection Defense Cheat Sheet.
Summary
The WP Database Backup plugin for WordPress is vulnerable to OS Command Injection via the 'wp_db_exclude_table' parameter in versions up to 7.11. This occurs because user-supplied table exclusion settings are concatenated directly into a `mysqldump` system command without proper shell escaping via `escapeshellarg()`. An authenticated administrator can inject shell metacharacters into this setting to execute arbitrary commands on the server whenever a backup operation is performed.
Vulnerable Code
// File: includes/admin/class-wpdb-admin.php // Line 215: The vulnerable setting is saved with insufficient sanitization (recursive_sanitize_text_field does not stop shell metacharacters) if ( isset( $_POST['wp_db_exclude_table'] ) ) { update_option( 'wp_db_exclude_table', $this->recursive_sanitize_text_field( wp_unslash( $_POST['wp_db_exclude_table'] ) ) , false); // phpcs:ignore } --- // In the mysqldump() function (Logical Representation): // The stored option is retrieved and concatenated unsafely into the command string passed to shell_exec() $wp_db_exclude_table = get_option( 'wp_db_exclude_table' ); // ... $command = $this->mysqldump_command_path . " --user=" . escapeshellarg($user) . " --password=" . escapeshellarg($pass) . " --host=" . escapeshellarg($host) . " " . escapeshellarg($db_name) . " --ignore-table=" . $wp_db_exclude_table . " > " . escapeshellarg($filename); shell_exec($command);
Security Fix
@@ -3450,1 +3450,1 @@ - $command .= " --ignore-table=" . $wp_db_exclude_table; + $command .= " --ignore-table=" . escapeshellarg($wp_db_exclude_table);
Exploit Outline
To exploit this vulnerability, an attacker with Administrator-level access follows these steps: 1. Navigate to the plugin's settings page in the WordPress dashboard. 2. Locate the 'Exclude Table' configuration setting (associated with the `wp_db_exclude_table` parameter). 3. Input a malicious payload containing shell command separators and an OS command (e.g., `wp_options; touch /tmp/pwned`). 4. Save the settings, which persists the payload in the WordPress options table. 5. Trigger a backup operation, either manually by clicking the 'Create New Database Backup' button or by waiting for a scheduled cron event. 6. The plugin retrieves the stored payload and concatenates it into a `mysqldump` command which is executed via `shell_exec()`, resulting in the execution of the injected OS command.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.