|
@@ -0,0 +1,68 @@
|
|
|
|
|
+#!/usr/bin/env python3
|
|
|
|
|
+"""芯葶真key恢复: SSH隧道→查DB→直写容器(不打印完整token)"""
|
|
|
|
|
+import subprocess, threading, socketserver, time, json, base64, sys
|
|
|
|
|
+
|
|
|
|
|
+sys.path.insert(0, "/opt/data/venv-ops/lib/python3.13/site-packages")
|
|
|
|
|
+import paramiko
|
|
|
|
|
+
|
|
|
|
|
+ssh = paramiko.SSHClient()
|
|
|
|
|
+ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
|
+ssh.connect("server.fmode.cn", port=22, username="root", password="bofang666.", timeout=30)
|
|
|
|
|
+transport = ssh.get_transport()
|
|
|
|
|
+
|
|
|
|
|
+class H(socketserver.BaseRequestHandler):
|
|
|
|
|
+ def handle(self):
|
|
|
|
|
+ try:
|
|
|
|
|
+ chan = transport.open_channel("direct-tcpip", ("127.0.0.1", 25432), self.request.getpeername())
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ return
|
|
|
|
|
+ if chan is None:
|
|
|
|
|
+ return
|
|
|
|
|
+ try:
|
|
|
|
|
+ while True:
|
|
|
|
|
+ d = self.request.recv(4096)
|
|
|
|
|
+ if not d:
|
|
|
|
|
+ break
|
|
|
|
|
+ chan.sendall(d)
|
|
|
|
|
+ finally:
|
|
|
|
|
+ try:
|
|
|
|
|
+ chan.close()
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+class S(socketserver.ThreadingTCPServer):
|
|
|
|
|
+ allow_reuse_address = True
|
|
|
|
|
+
|
|
|
|
|
+srv = S(("127.0.0.1", 15433), H)
|
|
|
|
|
+threading.Thread(target=srv.serve_forever, daemon=True).start()
|
|
|
|
|
+time.sleep(1)
|
|
|
|
|
+
|
|
|
|
|
+import psycopg2
|
|
|
|
|
+from urllib.parse import urlparse, unquote
|
|
|
|
|
+r = subprocess.run(["bash", "-c",
|
|
|
|
|
+ "python3 -c \"import json;d=json.load(open('/opt/data/git-repos/future-server/config/config.nova.json'));print(d['fmodeApi']['databaseURI'])\""],
|
|
|
|
|
+ capture_output=True, text=True)
|
|
|
|
|
+p = urlparse(r.stdout.strip())
|
|
|
|
|
+conn = psycopg2.connect(host="127.0.0.1", port=15433, dbname=p.path[1:],
|
|
|
|
|
+ user=p.username, password=unquote(p.password), connect_timeout=15)
|
|
|
|
|
+cur = conn.cursor()
|
|
|
|
|
+cur.execute("SELECT u.username, 'sk-'||t.\"key\" FROM tokens t JOIN users u ON t.user_id=u.id WHERE u.username IN ('fmode18170957536','fmode13133826287','fmode18691770343')")
|
|
|
|
|
+rows = cur.fetchall()
|
|
|
|
|
+for name, tok in rows:
|
|
|
|
|
+ print(f"{name}: len={len(tok)} {tok[:6]}...{tok[-4:]}")
|
|
|
|
|
+
|
|
|
|
|
+xinting_tok = [t for n, t in rows if n == "fmode18170957536"][0]
|
|
|
|
|
+b64t = base64.b64encode(xinting_tok.encode()).decode()
|
|
|
|
|
+cmd = f'''docker exec agent-node-xinting bash -c 'echo {b64t} | base64 -d > /tmp/t && python3 -c "
|
|
|
|
|
+import json
|
|
|
|
|
+p=\\"/opt/data/fmode-identity.json\\"
|
|
|
|
|
+d=json.load(open(p)); d[\\"newapi_token\\"]=open(\\"/tmp/t\\").read().strip()
|
|
|
|
|
+json.dump(d,open(p,\\"w\\"),ensure_ascii=False,indent=2)
|
|
|
|
|
+print(\\"xinting identity len:\\", len(d[\\"newapi_token\\"]))
|
|
|
|
|
+" && rm /tmp/t' '''
|
|
|
|
|
+r2 = subprocess.run(["/opt/data/venv-ops/bin/python", "/opt/data/scripts/r730_root.py", cmd],
|
|
|
|
|
+ capture_output=True, text=True, timeout=120)
|
|
|
|
|
+print(r2.stdout[:150])
|
|
|
|
|
+conn.close()
|
|
|
|
|
+srv.shutdown()
|
|
|
|
|
+ssh.close()
|