← Back to Feed CACHED · 2026-09-21 15:04:07 · CACHE_KEY CVE-2025-10035
CVE-2025-10035 · CWE-77 · Disclosed 2025-09-18

A deserialization vulnerability in the License Servlet of Fortra's GoAnywhere MFT

ASSESSED — NOISGATE
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Someone left the vault door unlocked, and the burglars brought a forklift

CVE-2025-10035 is a deserialization-to-command-injection chain in the License Servlet of Fortra GoAnywhere MFT — a managed file transfer gateway that enterprises deploy in the DMZ specifically to move sensitive data between business partners. All versions prior to 7.8.4 (standard release) and 7.6.3 (sustain release) are affected. The chain combines three issues: an authentication bypass on the License Servlet endpoint (known since 2023), hard-coded encryption keys that let an attacker recover session tokens offline, and the unsafe deserialization of attacker-controlled Java objects inside a SignedObject wrapper. The net result is unauthenticated remote code execution — full SYSTEM-level compromise of the MFT host from the internet.

Fortra rated this CVSS 10.0/CRITICAL, and for once the vendor score is exactly right. GoAnywhere MFT is *designed* to be internet-facing; its entire purpose is external file exchange. The auth bypass requires a single crafted GET request. The hard-coded keys are identical across all installations. Microsoft confirmed Storm-1175 was exploiting this as a zero-day starting September 10, 2025 — a full week before Fortra disclosed it on September 18 — dropping SimpleHelp and MeshAgent persistence tools and deploying Medusa ransomware within 24 hours of initial access. watchTowr Labs published a full PoC on September 24. CISA added it to KEV on September 29. The EPSS score of 0.998 puts it in the top 0.2% of all CVEs for exploitation probability. There is no legitimate reason to disagree with the vendor here.

"Unauthenticated RCE on an internet-facing MFT gateway, actively exploited for Medusa ransomware"
02 · The Attack Path

6 steps from start to impact.

STEP 01

Locate exposed GoAnywhere admin/license endpoint

The attacker scans for GoAnywhere MFT instances using Shodan, Censys, or FOFA dorks targeting the /goanywhere/ web path on ports 8000/8001 (admin console) or 443. Censys identified 740 internet-facing instances as of late September 2025. The License Servlet at /goanywhere/license/ is reachable on the same port as the admin console and does not require separate credentials.
Conditions required:
  • Target GoAnywhere MFT instance is reachable from the internet on the admin console port
Where this breaks in practice:
  • Fortra advises restricting admin console to internal networks, but MFT appliances are internet-facing by design and many orgs expose the full web interface
Detection/coverage: Censys, Shodan, and Qualys external attack surface scans can enumerate exposed GoAnywhere instances. GreyNoise reported mass scanning activity for GoAnywhere endpoints post-disclosure.
STEP 02

Trigger authentication bypass via exception routing

The attacker sends a crafted GET request to /goanywhere/license/Unlicensed.xhtml/x with an invalid javax.faces.ViewState parameter and GARequestAction=activate. This triggers a JSF exception that routes to the AdminErrorHandlerServlet, which generates a valid license request token and attaches it to the attacker's HTTP session — no credentials required. The bypass has been possible since at least 2023 but was not publicly documented until watchTowr's analysis.
Conditions required:
  • Reachable License Servlet endpoint
  • GoAnywhere MFT version < 7.8.4 or sustain < 7.6.3
Where this breaks in practice:
  • A WAF with strict path-traversal rules might block the /Unlicensed.xhtml/x suffix, but this is a valid JSF path and most WAFs would pass it
Detection/coverage: WAF logs showing requests to /goanywhere/license/Unlicensed.xhtml/ with appended path segments and GARequestAction=activate parameter are strong indicators of exploitation attempts.
STEP 03

Extract session token via hard-coded key decryption

The server responds with a 302 redirect to Fortra's license server, including an encrypted bundle parameter. Because GoAnywhere uses hard-coded encryption keys identical across all installations, the attacker decrypts the bundle offline to extract the GUID session token. This token is required for the next stage and proves the attacker holds a valid session. watchTowr's PoC and the ThemeHackers GitHub repository both implement this decryption step.
Conditions required:
  • Successful auth bypass from Step 2
  • Knowledge of the hard-coded encryption key (published in PoC code)
Where this breaks in practice:
  • None — the key is static and publicly known post-PoC publication
Detection/coverage: Network IDS/IPS signatures for the redirect containing the encrypted bundle parameter to external license servers. Fortra published IOCs including specific .jsp files dropped post-exploitation.
STEP 04

Deliver malicious serialized object to deserialization sink

Using the extracted GUID, the attacker POSTs to /goanywhere/lic/accept/<GUID> with a crafted bundle parameter containing a malicious serialized Java object wrapped in a SignedObject. The LicenseResponseServlet.doPost() method passes this to BundleWorker.verify(), which calls SignedObject.getObject() — triggering unrestricted deserialization. Gadget chains such as CommonsBeanutils1 (present in GoAnywhere's classpath) convert the deserialization into arbitrary OS command execution. The signature verification against the baked-in public key is the one non-trivial step, but real-world exploitation by Storm-1175 proves it is solvable — possibly via private key compromise or an alternate code path.
Conditions required:
  • Valid session GUID from Step 3
  • Crafted serialized payload with appropriate gadget chain
  • Ability to satisfy or bypass SignedObject signature verification
Where this breaks in practice:
  • The signature verification is the only technical friction point, but Storm-1175 demonstrated it is bypassable in production — the patch hardens deserialization but leaves signature logic untouched, suggesting the private key may have been compromised
Detection/coverage: Java deserialization payloads in POST bodies to /goanywhere/lic/accept/ paths. EDR on the MFT host should flag java.exe or the GoAnywhere process spawning unexpected child processes (cmd.exe, powershell.exe, bash).
STEP 05

Achieve SYSTEM-level code execution and deploy persistence

The deserialized gadget chain executes arbitrary OS commands as the GoAnywhere service account — typically SYSTEM on Windows or root on Linux. Microsoft observed Storm-1175 immediately dropping SimpleHelp and MeshAgent RMM tools for persistence, creating malicious .jsp webshells in GoAnywhere web directories, and performing system/user discovery. The MFT host's position in the DMZ with access to both external networks and internal file shares makes it an ideal pivot point.
Conditions required:
  • Successful deserialization and command execution from Step 4
Where this breaks in practice:
  • EDR on the MFT host should detect RMM tool installation and webshell creation, but many MFT appliances run on hardened Linux without endpoint agents
Detection/coverage: EDR alerts for RMM tool binaries (SimpleHelp, MeshAgent). File integrity monitoring on GoAnywhere web directories for unexpected .jsp files. Microsoft published specific IOCs including file hashes and C2 domains.
STEP 06

Lateral movement and ransomware deployment

From the compromised MFT host, Storm-1175 pivots into the internal network using harvested credentials and the MFT system's existing network trust relationships (it needs access to internal file shares and databases by design). Within 24 hours of initial access, the group deploys Medusa ransomware across reachable systems. The MFT host likely contains credentials or connection strings for backend storage, LDAP/AD service accounts, and partner SFTP keys — all of which accelerate lateral movement.
Conditions required:
  • SYSTEM-level access on MFT host
  • Network connectivity to internal systems (standard for DMZ MFT)
Where this breaks in practice:
  • Network segmentation between DMZ and internal LAN should slow lateral movement, but MFT hosts require firewall rules to internal file stores and databases
Detection/coverage: Network detection for lateral movement patterns originating from MFT host IP. SIEM correlation of authentication events from the MFT service account to unusual targets.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed and active. Microsoft attributed exploitation to Storm-1175 starting September 10, 2025 — 8 days before public disclosure. Multiple organizations compromised with Medusa ransomware deployed within 24 hours of initial access. watchTowr Labs independently confirmed exploitation evidence from the same timeframe.
Proof-of-ConceptPublic. watchTowr Labs published a detailed technical analysis and PoC on September 24, 2025. ThemeHackers/CVE-2025-10035 on GitHub provides a weaponized implementation. Multiple security vendors have published detection-oriented reproduction steps.
EPSS Score0.99799 — top 0.2 percentile. This is near the theoretical maximum, reflecting confirmed mass exploitation, public PoC availability, and trivial attack complexity.
CISA KEV StatusListed September 29, 2025. Federal agencies subject to BOD 22-01 must remediate per CISA deadlines. Active exploitation confirmed prior to KEV listing.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H10.0 Critical. Network-accessible, low complexity, no privileges or user interaction required, scope changed (attacker can pivot beyond the vulnerable component). Every metric is at maximum severity.
Affected VersionsAll GoAnywhere MFT versions prior to 7.8.4 (standard release) and prior to 7.6.3 (sustain release). No version floor has been identified — the auth bypass predates 2023.
Fixed VersionsGoAnywhere MFT 7.8.4 (standard) and 7.6.3 (sustain). Patch hardens the deserialization routine with type restrictions but notably does not modify the signature verification logic.
Internet ExposureCensys identified 740 internet-facing GoAnywhere MFT instances globally. Of the 65 reporting version numbers, 40 (~61%) run vulnerable versions. Actual vulnerable population is likely higher given 91% did not report versions. Fortra proactively contacted customers with exposed admin consoles.
Disclosure TimelineExploitation began ~Sept 10, 2025. Fortra disclosed and patched Sept 18, 2025. watchTowr PoC published Sept 24. CISA KEV added Sept 29. Microsoft attribution blog published Oct 6.
Reporting ResearchersFortra internal discovery. Independent analysis by watchTowr Labs (Sean Yeoh, Orange Tsai), Rapid7 Labs, and Microsoft Threat Intelligence Center. Storm-1175 attribution by Microsoft MSTIC.
04 · The Call

Final Verdict
= UNCHANGED to CRITICAL (10.0/10)

Why this verdict

  • Unauthenticated remote attack surface: The entire chain — from auth bypass through deserialization to SYSTEM-level command execution — requires zero credentials and zero user interaction. The attacker needs only network reachability to the GoAnywhere admin/license port, which is internet-exposed by design in the majority of MFT deployments.
  • Confirmed zero-day exploitation with ransomware impact: Storm-1175 weaponized this vulnerability a full week before public disclosure, deploying Medusa ransomware within 24 hours of initial access. This is not theoretical — organizations have already been encrypted. The EPSS score of 0.998 and KEV listing confirm this is among the most actively exploited CVEs of 2025.
  • Minimal friction in the attack chain: The auth bypass is a single GET request. The encryption keys are hard-coded and identical across all installations. The PoC is public and weaponized. The only non-trivial step (signature verification) has been demonstrably solved by threat actors in the wild. No step requires specialized tooling or insider knowledge post-PoC publication.
  • Role multiplier: GoAnywhere MFT is canonically a network-edge, high-value-role component. MFT gateways sit in the DMZ bridging external partners and internal infrastructure. They hold SFTP keys, AD service account credentials, database connection strings, and sensitive files in transit. >90% of GoAnywhere deployments occupy this exact high-value network-edge role — it is the product's entire purpose. Blast radius is fleet-scale: the compromised MFT host provides direct pivot access to internal file shares, databases, and partner networks. Storm-1175 demonstrated domain-to-ransomware escalation within 24 hours. This firmly exceeds the CRITICAL floor.
  • No meaningful friction downgrades apply: Unlike vulnerabilities requiring internal network access or authenticated sessions, this chain starts from the public internet against a product designed to be public-facing. WAF bypass is trivial (the path is valid JSF). The only population limiter is the ~740 internet-facing instances, but each instance protects an entire enterprise's file transfer infrastructure — the per-instance blast radius is enormous.

Why not higher?

CVSS 10.0 is the maximum possible score. The vendor has correctly assigned the ceiling. There is no higher severity to assign.

Why not lower?

Downgrading would require meaningful friction or a narrow blast radius, neither of which exists here. The product is internet-facing by design (no 'requires internal access' discount). The chain is fully unauthenticated (no 'requires credentials' discount). Exploitation is confirmed at scale by a ransomware group (not theoretical). The MFT gateway role means every compromised instance exposes an entire enterprise's file transfer data and provides a DMZ-to-LAN pivot. Even a strict friction audit finds nothing to subtract.

05 · Compensating Control

What to do — in priority order.

  1. Restrict admin console and License Servlet to internal/VPN-only access immediately — The entire attack chain requires network reachability to the GoAnywhere admin port (typically 8000/8001). Blocking internet access to these ports via firewall rules eliminates the unauthenticated attack vector. Deploy within hours — this is your noisgate mitigation SLA for CRITICAL: ≤ 3 days, but given active exploitation and KEV listing, treat this as an emergency change within hours. If the admin console must remain accessible, restrict it to known management IPs via allowlist.
  2. Upgrade to GoAnywhere MFT 7.8.4 or sustain release 7.6.3 — The vendor patch hardens the deserialization routine with type restrictions. This is the definitive fix. Deploy within the noisgate remediation SLA of ≤ 90 days, but given active ransomware exploitation, prioritize emergency patching within days, not weeks. Test in a staging environment first if possible, but do not let testing delay deployment beyond 72 hours.
  3. Deploy EDR or endpoint monitoring on GoAnywhere MFT hosts — Many MFT appliances run without endpoint agents, leaving post-exploitation activity invisible. Install EDR capable of detecting: RMM tool installation (SimpleHelp, MeshAgent), unexpected child process spawning from the Java/GoAnywhere process, and .jsp file creation in web directories. This provides detection-in-depth if the network control fails.
  4. Audit GoAnywhere host for IOCs published by Microsoft and Fortra — Check for: unexpected .jsp files in GoAnywhere web directories, SimpleHelp or MeshAgent binaries, unusual outbound connections to C2 infrastructure, and new local accounts. Microsoft's October 6 blog contains specific file hashes and C2 domains. If any IOCs are found, treat the host and all credentials it holds as compromised.
  5. Rotate all credentials stored on or accessible from the MFT host — GoAnywhere MFT hosts typically store AD service account credentials, SFTP partner keys, database connection strings, and LDAP bind credentials. If exploitation cannot be ruled out, rotate these credentials immediately. The MFT host's DMZ position means a compromise exposes every system it connects to.
  6. Implement network segmentation between DMZ MFT hosts and internal LAN — Even if the MFT host is compromised, strict firewall rules limiting its internal connectivity to only required file share and database ports will slow lateral movement. Block all outbound RDP, SMB, and WMI from the MFT host to internal subnets except explicitly required destinations.
What doesn't work
  • WAF alone does not mitigate this. The auth bypass uses a valid JSF path (/Unlicensed.xhtml/x) with standard HTTP parameters. Generic WAF rules for path traversal or SQL injection will not flag this. A custom WAF rule targeting the specific path pattern could help but is fragile and easily evaded with encoding variations.
  • Disabling the License Servlet is not a supported configuration. The servlet is integrated into GoAnywhere's core web application and cannot be independently disabled without breaking license management functionality.
  • Network-level IDS signatures provide detection, not prevention. Snort/Suricata rules for the exploit pattern will alert but will not block the attack unless deployed inline as IPS. Even then, encrypted traffic (HTTPS) renders payload inspection ineffective without TLS termination upstream.
  • Application-layer authentication (MFA on admin console) does not help. The vulnerability bypasses the authentication layer entirely — MFA on the admin login has no bearing on the License Servlet exception-routing bypass.
06 · Verification

Crowdsourced verification payload.

Run this script on each GoAnywhere MFT host (Linux/Windows via bash or WSL) as any user with read access to the GoAnywhere installation directory. Example: bash check_cve_2025_10035.sh /opt/GoAnywhere. The script checks the installed version against the patched versions and probes the License Servlet endpoint for the auth bypass indicator.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2025-10035 Verification Script for GoAnywhere MFT
# Usage: bash check_cve_2025_10035.sh [GOANYWHERE_INSTALL_DIR] [OPTIONAL_URL]
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -euo pipefail

GA_DIR="${1:-/opt/GoAnywhere}"
GA_URL="${2:-}"
STATUS="UNKNOWN"

echo "=== CVE-2025-10035 Check ==="
echo "GoAnywhere directory: $GA_DIR"

# Method 1: Version file check
if [ -f "$GA_DIR/version.txt" ]; then
  VERSION=$(cat "$GA_DIR/version.txt" | grep -oP '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
  echo "Detected version: $VERSION"
  if [ -n "$VERSION" ]; then
    MAJOR=$(echo "$VERSION" | cut -d. -f1)
    MINOR=$(echo "$VERSION" | cut -d. -f2)
    PATCH=$(echo "$VERSION" | cut -d. -f3)
    # Fixed in 7.8.4 (standard) or 7.6.3 (sustain)
    if [ "$MAJOR" -gt 7 ]; then
      STATUS="PATCHED"
    elif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -gt 8 ]; then
      STATUS="PATCHED"
    elif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -eq 8 ] && [ "$PATCH" -ge 4 ]; then
      STATUS="PATCHED"
    elif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -eq 6 ] && [ "$PATCH" -ge 3 ]; then
      STATUS="PATCHED"
    else
      STATUS="VULNERABLE"
    fi
  fi
elif [ -f "$GA_DIR/build.properties" ]; then
  VERSION=$(grep -oP 'version=\K[0-9]+\.[0-9]+\.[0-9]+' "$GA_DIR/build.properties" 2>/dev/null || true)
  echo "Detected version from build.properties: ${VERSION:-not found}"
  if [ -n "$VERSION" ]; then
    MAJOR=$(echo "$VERSION" | cut -d. -f1)
    MINOR=$(echo "$VERSION" | cut -d. -f2)
    PATCH=$(echo "$VERSION" | cut -d. -f3)
    if [ "$MAJOR" -gt 7 ]; then
      STATUS="PATCHED"
    elif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -gt 8 ]; then
      STATUS="PATCHED"
    elif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -eq 8 ] && [ "$PATCH" -ge 4 ]; then
      STATUS="PATCHED"
    elif [ "$MAJOR" -eq 7 ] && [ "$MINOR" -eq 6 ] && [ "$PATCH" -ge 3 ]; then
      STATUS="PATCHED"
    else
      STATUS="VULNERABLE"
    fi
  fi
else
  echo "WARNING: Could not find version file at $GA_DIR"
fi

# Method 2: HTTP endpoint probe (optional)
if [ -n "$GA_URL" ]; then
  echo "Probing endpoint: $GA_URL"
  PROBE_URL="${GA_URL}/goanywhere/license/Unlicensed.xhtml/noisgate_check?javax.faces.ViewState=noisgate&GARequestAction=activate"
  HTTP_RESP=$(curl -sk -o /dev/null -w '%{http_code}:%{redirect_url}' -L --max-redirs 0 "$PROBE_URL" 2>/dev/null || echo "000:")
  HTTP_CODE=$(echo "$HTTP_RESP" | cut -d: -f1)
  REDIRECT_URL=$(echo "$HTTP_RESP" | cut -d: -f2-)
  echo "HTTP response code: $HTTP_CODE"
  if echo "$REDIRECT_URL" | grep -q 'bundle='; then
    echo "RESULT: Redirect contains bundle parameter - VULNERABLE"
    STATUS="VULNERABLE"
  elif [ "$HTTP_CODE" = "302" ] || [ "$HTTP_CODE" = "301" ]; then
    if ! echo "$REDIRECT_URL" | grep -q 'bundle='; then
      echo "RESULT: Redirect without bundle parameter - likely PATCHED"
      if [ "$STATUS" = "UNKNOWN" ]; then STATUS="PATCHED"; fi
    fi
  elif [ "$HTTP_CODE" = "403" ] || [ "$HTTP_CODE" = "404" ]; then
    echo "RESULT: Endpoint blocked or not found - likely mitigated"
    if [ "$STATUS" = "UNKNOWN" ]; then STATUS="PATCHED"; fi
  else
    echo "RESULT: Inconclusive HTTP response"
  fi
fi

echo ""
echo "=== VERDICT: $STATUS ==="

case "$STATUS" in
  VULNERABLE) exit 1 ;;
  PATCHED)    exit 0 ;;
  *)          exit 2 ;;
esac
07 · Sources

Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.