← Back to Feed CACHED · 2026-10-02 15:03:46 · CACHE_KEY CVE-2026-86325
CVE-2026-86325 · CWE-121 · Disclosed 2026-10-02

A stack-based buffer overflow vulnerability exists in protocol gateways' account management interface.

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

Someone left the drawbridge guard's key under the mat, and the drawbridge controls the water supply

CVE-2026-86325 is a stack-based buffer overflow in the account management interface of Moxa MGate protocol gateways — the MB3170, MB3270, MB3180, MB3280, MB3480, MB3660, and 5217 Series. All firmware versions up through v4.7 (MB3170/MB3270), v2.7 (MB3180), v4.6 (MB3280), v4.5 (MB3480), v3.4 (MB3660), and v1.5 (5217) are affected. The flaw stems from insufficient length validation of the account_name parameter: an attacker authenticated as a read-only user — the lowest privilege level — can submit an oversized account name that smashes the stack buffer, corrupting program execution flow. On these embedded devices (ARM/MIPS, no ASLR, no stack canaries in most firmware builds), this is effectively a code-execution primitive. The impact is memory read (credential theft), arbitrary memory write, and device denial-of-service — in a device that sits directly on the data path between PLCs/RTUs and SCADA masters.

The vendor assigned a CVSS v4.0 of 9.4 (Critical) in advisory MPSA-269540. That score is *justified*. These gateways are deployed almost exclusively in OT/ICS environments — energy substations, water treatment, chemical plants, manufacturing floors — bridging Modbus RTU/ASCII serial devices to Modbus TCP networks. Compromising one doesn't just own a single box; it gives an attacker man-in-the-middle position over industrial process data. The authentication requirement (read-only user) sounds like friction until you consider that the default admin credential is admin/moxa, many OT environments never change defaults, and a read-only account is trivially provisioned. Moxa has released patched firmware for most models, but OT patching cycles are measured in quarters, not days.

"OT protocol gateway stack overflow lets read-only user own the bridge between SCADA and field devices"
02 · The Attack Path

5 steps from start to impact.

STEP 01

Gain network access to MGate web management interface

The attacker needs HTTP/HTTPS access (TCP 80/443) to the MGate gateway's web console. In a properly segmented OT network this requires prior access to the control system VLAN. However, CISA advisories for prior Moxa vulns explicitly warn that many deployments fail to isolate these devices, and Shodan indexes ~4,100 Moxa devices globally. Even without direct internet exposure, an attacker who has compromised a single IT/OT boundary host (historian, jump server, engineering workstation) can pivot to the OT VLAN.
Conditions required:
  • Network path to MGate HTTP/HTTPS interface (TCP 80 or 443)
  • Attacker on OT network or device internet-exposed
Where this breaks in practice:
  • Properly segmented OT networks place these on isolated VLANs
  • Industrial firewalls/DMZs should block direct internet access
  • GreyNoise/Shodan show relatively few MGate-specific internet-facing instances
Detection/coverage: Shodan/Censys queries for Moxa MGate or Server: MoxaHttp banner; network monitoring for unexpected connections to gateway management ports
STEP 02

Authenticate as read-only user

The attacker logs in to the web management console with read-only credentials. The MGate MB3170 ships with default credentials admin/moxa. Even if admin credentials are changed, a lower-privilege read-only account may retain factory defaults or be guessable. The read-only privilege level is sufficient — no admin access required. In OT environments, shared/default credentials are endemic; the 2021 CISA advisory for the same product family called out cleartext credential transmission (CVE-2021-4161) precisely because defaults were ubiquitous.
Conditions required:
  • Valid read-only user credentials (or default creds unchanged)
Where this breaks in practice:
  • Organizations that enforce credential rotation and disable default accounts raise the bar
  • HTTPS enforcement prevents credential sniffing on the wire
Detection/coverage: Authentication logs on MGate (if syslog forwarding is configured); anomalous login from non-engineering IPs
STEP 03

Submit crafted account_name to overflow stack buffer

The attacker navigates to the account management interface and submits a specially crafted account_name value that exceeds the expected stack buffer size. Because the firmware performs no length validation on this parameter, the oversized input overwrites the return address and adjacent stack frames. On these ARM/MIPS embedded platforms running older toolchains, there are typically no stack canaries, ASLR, or NX bits, meaning the overflow directly controls the instruction pointer without needing to bypass modern mitigations.
Conditions required:
  • Access to account management function (available to read-only users)
  • Knowledge of target architecture (ARM/MIPS — deterministic from model number)
Where this breaks in practice:
  • No public PoC exists yet — attacker must develop the exploit independently
  • Embedded firmware reversing requires ICS-specific skill set
Detection/coverage: Deep packet inspection on HTTP POST to account management endpoint; IDS signatures for oversized account_name parameter
STEP 04

Achieve code execution on gateway

With the instruction pointer controlled, the attacker redirects execution to injected shellcode or ROP gadgets within the firmware image. The gateway runs with a single privilege level (root equivalent on embedded Linux or bare-metal RTOS), so code execution is inherently privileged. The attacker now has full control of the protocol translation layer — they can read, modify, or drop Modbus frames transiting between field devices and the SCADA master, extract stored credentials from device memory, or brick the gateway to cause a denial-of-service on the process network.
Conditions required:
  • Successful stack smash from Step 3
  • Exploit payload compatible with target firmware build
Where this breaks in practice:
  • Firmware varies across models and versions, requiring per-build exploit tuning
  • No known weaponized tooling (no Metasploit module, no public exploit)
Detection/coverage: Device behavior anomaly: unexpected reboots, changed configurations, firmware integrity check failures; OT network monitoring (e.g., Claroty, Dragos, Nozomi) detecting abnormal Modbus traffic patterns
STEP 05

Manipulate industrial process data or pivot deeper

From the compromised gateway, the attacker can perform man-in-the-middle attacks on Modbus RTU/TCP traffic — modifying setpoints, falsifying sensor readings, or suppressing alarms flowing between PLCs and the SCADA HMI. The gateway's network position also enables lateral movement to other devices on the serial bus or the Modbus TCP segment. Extracted credentials (from memory dump in the overflow) may grant access to adjacent OT systems. In safety-critical environments (water treatment, energy, chemical), this translates directly to operational and potentially physical safety impact.
Conditions required:
  • Sustained code execution on gateway
  • Knowledge of downstream Modbus device addressing and register maps
Where this breaks in practice:
  • Process-aware attacks require domain knowledge of the specific industrial process
  • Safety instrumented systems (SIS) on separate loops may catch dangerous state changes
Detection/coverage: OT anomaly detection platforms flagging unexpected Modbus register writes; process historians showing value deviations; safety system alarms
03 · Compensating Control

1
CRITICAL 9.2→HIGH 7.5
SEVERITY REDUCED
Restrict web management interface to dedicated management VLAN with ACLs — Firewall the MGate's HTTP/HTTPS ports (TCP 80/443) so only authorized engineering workstations on a dedicated management VLAN can reach them. This breaks Step 1 of the attack path for any attacker who hasn't already compromised the management segment. Deploy within the noisgate mitigation SLA of 3 days for CRITICAL severity. Configure industrial firewall rules (e.g., Palo Alto OT Security, Fortinet FortiGate Rugged) to enforce the ACL.
2
CRITICAL 9.2→HIGH 7.0
SEVERITY REDUCED
Rotate all MGate credentials and disable default accounts — Change the default admin/moxa credentials immediately. Remove or disable any unused read-only accounts. Enforce unique, strong passwords for all remaining accounts. This directly degrades Step 2 — without valid credentials, the authenticated overflow is unreachable. Deploy within the noisgate mitigation SLA of 3 days. Document new credentials in your OT password vault (e.g., CyberArk PAM for OT).
3
CRITICAL 9.2→CRITICAL 8.8
Enable HTTPS and disable HTTP on all MGate devices — Disable plaintext HTTP (port 80) and enable HTTPS-only access per Moxa's Security Hardening Guide. This prevents credential sniffing on the OT network (cf. CVE-2021-4161) that could feed Step 2, and adds TLS inspection capability for IDS. Deploy within the noisgate mitigation SLA of 3 days.
4
CRITICAL 9.2→CRITICAL 8.5
Deploy OT network monitoring with Modbus-aware anomaly detection — Implement an OT-specific NDR platform (Claroty, Dragos Platform, Nozomi Guardian) to monitor Modbus TCP/RTU traffic for anomalous register writes, unexpected gateway behavior, and post-exploitation indicators (Step 5). This provides detection-in-depth but does not prevent exploitation. Deploy within 30 days as a detection layer.
5
CRITICAL 9.2→IGNORE 0.0
SEVERITY REDUCED
Apply vendor firmware patches — Update to fixed firmware: MB3170/MB3270 → v4.7.1, MB3180 → v2.7.1, MB3280 → v4.6.3, MB3480 → v4.5.1, MB3660 → v3.4.5, 5217 → v1.5.5. For 5000/5100/W5108/W5208 series with no available fix, contact Moxa support and apply compensating controls aggressively. OT patching requires maintenance windows — target the noisgate remediation SLA of 90 days for CRITICAL, but begin scheduling immediately. Test firmware in a staging environment before deploying to production gateways.
What doesn't work
  • Generic IT firewalls at the IT/OT boundary — if the attacker is already on the OT network (insider, compromised historian, VPN pivot), perimeter firewalls don't protect the MGate's management interface. Micro-segmentation within the OT zone is required.
  • Web Application Firewalls (WAFs) — MGate's embedded HTTP server does not sit behind a WAF, and deploying a reverse proxy in front of an embedded OT device is impractical and unsupported.
  • Disabling the account management feature — the web interface does not support selectively disabling account management endpoints; the entire web console must be disabled, which removes the primary management plane.
  • Network-level IDS without OT protocol awareness — standard Snort/Suricata rules won't catch the malformed account_name POST without a custom signature, and won't detect post-exploitation Modbus manipulation without protocol-specific dissectors.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNot observed. Not listed in CISA KEV catalog. No campaigns or threat actor TTPs documented as of 2026-10-02. Moxa MGate devices have been targeted in prior ICS campaigns (cf. ICSA-21-357-01, ICSA-16-196-02), making this product family a known target of interest for ICS-focused adversaries.
Proof-of-ConceptNo public PoC. Checked pocindex.io, GitHub (no repos named CVE-2026-86325), ExploitDB, and Metasploit — no exploit code available. The vulnerability is straightforward (missing length check on a stack buffer), lowering the skill barrier for independent development by researchers or threat actors with embedded reversing capability.
EPSS ScorePending. FIRST.org EPSS evaluation is in progress; CVE was just disclosed 2026-10-02. Historical EPSS for comparable Moxa gateway CVEs (e.g., CVE-2021-4161, CVSS 9.8) ranged 0.05–0.15 (low exploitation probability), reflecting the niche ICS deployment context.
KEV StatusNot listed in CISA Known Exploited Vulnerabilities catalog as of 2026-10-02.
CVSS VectorCVSS v4.0: AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H = 9.4 Critical (vendor-assigned in MPSA-269540). CVSS v3.1 NVD score: pending analysis. The v4.0 vector reflects network-accessible, low-complexity, low-privilege attack with high impact across all CIA dimensions including downstream systems (SC/SI/SA:H).
Affected VersionsMB3170/MB3270: ≤ v4.7 · MB3180: ≤ v2.7 · MB3280: ≤ v4.6 · MB3480: ≤ v4.5 · MB3660: ≤ v3.4 · 5217 Series: ≤ v1.5 · All 5000/5100 Series and W5108/W5208: all versions (contact Moxa)
Fixed VersionsMB3170/MB3270: v4.7.1 · MB3180: v2.7.1 · MB3280: v4.6.3 · MB3480: v4.5.1 · MB3660: v3.4.5 · 5217: v1.5.5 · 5000/5100/W5108/W5208: no fix available — contact Moxa support
Scanning / ExposureShodan indexes ~4,100 Moxa-branded devices globally (banner: MoxaHttp). MGate-specific subset is smaller but non-trivial. CISA ICS advisories for this product family explicitly warn that many deployments are internet-accessible or inadequately segmented. Censys/FOFA corroborate presence of Moxa web consoles on public internet, concentrated in APAC and European industrial regions.
Disclosure TimelineReserved: 2026-09-07 · Published: 2026-10-02 · Vendor advisory: MPSA-269540 (same day) · Patches released: same day for most models
Reporting ResearcherNot publicly attributed in Moxa advisory MPSA-269540. Coordinated disclosure through Moxa PSIRT.

Sources.

  1. Moxa Security Advisory MPSA-269540
  2. CISA ICS Advisory ICSA-21-357-01 (Moxa MGate)
  3. SecurityOnline — Moxa MGate Vulnerabilities Analysis
  4. Strix.ai — CVE-2026-86325 Detail Page
  5. Threat Radar — CVE-2026-86325 Intelligence
  6. TheHackerWire — CVE-2026-86325 Analysis
  7. Moxa MGate MB3000 Security Hardening Guide
  8. CSO Online — Protocol Gateway Flaws in ICS
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.2/10)

Why this verdict

  • Canonical OT/ICS device — floor is CRITICAL. The Moxa MGate is a Modbus protocol gateway deployed *exclusively* in ICS/SCADA environments (energy, water, chemical, manufacturing). By definition, ≥95% of installed units sit in high-value OT roles. The blast radius on successful exploitation is process-control manipulation, credential theft from device memory, and operational disruption — this is operational-safety-impact territory, and the verdict floor per the deployment-role rule is CRITICAL.
  • Role multiplier: OT protocol gateway. The MGate bridges serial field devices (PLCs, RTUs, sensors) to the Modbus TCP network. Compromising it gives MitM control over all process data transiting the gateway — register reads, coil writes, setpoints, alarms. In energy substations or water treatment plants, this translates to physical-process manipulation. The chain succeeds in this role (read-only auth + stack overflow), and the blast radius is safety/operational impact. This is not a workstation vulnerability being speculatively mapped to a high-value role — the *only* role this device occupies is the high-value one.
  • Trivial authentication barrier. The attack requires only read-only user access — the lowest privilege tier. Default credentials (admin/moxa) are well-documented and endemic in OT environments where credential rotation is rare. This reduces the PR:L requirement to near-zero friction in practice.
  • Embedded platform lacks modern mitigations. MGate firmware runs on ARM/MIPS embedded Linux or RTOS without ASLR, stack canaries, or NX in most firmware builds. A stack overflow on these platforms is a reliable code-execution primitive, not a probabilistic crash. The gap between overflow and shell is minimal.
  • No PoC tempers immediacy, not severity. No public exploit code exists, and EPSS is pending. This means mass exploitation is not imminent today, but the vulnerability is straightforward (missing strlen check) and independently discoverable. ICS-focused threat actors (CHERNOVITE/PIPEDREAM, ELECTRUM, XENOTIME) have demonstrated capability against similar embedded OT devices.
  • Score set at 9.2 vs. vendor's 9.4. Slight reduction acknowledges the authentication requirement (even if weak) and absence of confirmed exploitation. The delta is narrow because the auth friction is marginal in real OT deployments.

Why not higher?

A 9.4+ or 10.0 score would require either unauthenticated remote access or confirmed active exploitation. The authentication requirement — even at the read-only level — is a real gate that prevents fully anonymous exploitation. Additionally, no public PoC or in-the-wild activity has been confirmed, which tempers the immediacy of the threat. The vendor's own v4.0 score of 9.4 is the ceiling; we sit just below it.

Why not lower?

Downgrading below CRITICAL would require ignoring the deployment reality: this device exists *only* in OT/ICS environments where compromise has operational and safety consequences. The authentication friction is near-zero given default credentials. The lack of modern exploit mitigations on the embedded platform makes the stack overflow highly reliable. Network segmentation *should* limit exposure, but CISA's own advisories for this product family repeatedly warn that segmentation is inadequate in practice. A HIGH rating would understate the blast radius of a compromised protocol gateway in a safety-critical process network.

06 · Verification

Crowdsourced verification payload.

Run this script from any workstation with network access to the MGate device's web interface. Invoke with: python3 check_cve_2026_86325.py <device_ip> [--port 443] [--https]. No authentication required — the script checks the firmware version from the device's public-facing info page. Requires Python 3.6+ with the requests library (pip install requests).

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/usr/bin/env python3
"""CVE-2026-86325 Checker — Moxa MGate Stack Buffer Overflow
Checks firmware version against known-vulnerable and fixed versions.
Usage: python3 check_cve_2026_86325.py <host> [--port PORT] [--https]
Exit codes: 1=VULNERABLE, 0=PATCHED, 2=UNKNOWN
"""
import sys
import re
import argparse
import warnings

try:
    import requests
    from requests.packages.urllib3.exceptions import InsecureRequestWarning
    warnings.simplefilter('ignore', InsecureRequestWarning)
except ImportError:
    print("UNKNOWN - 'requests' library not installed. Run: pip install requests")
    sys.exit(2)

# Fixed firmware versions per model (from MPSA-269540)
FIXED_VERSIONS = {
    'MB3170': '4.7.1',
    'MB3270': '4.7.1',
    'MB3180': '2.7.1',
    'MB3280': '4.6.3',
    'MB3480': '4.5.1',
    'MB3660': '3.4.5',
    '5217':   '1.5.5',
}

# Models with NO fix available
NO_FIX_MODELS = ['5000', '5100', 'W5108', 'W5208']

def parse_version(v):
    """Parse version string into tuple of ints for comparison."""
    parts = re.findall(r'\d+', v)
    return tuple(int(p) for p in parts)

def check_device(host, port, use_https):
    scheme = 'https' if use_https else 'http'
    base_url = f"{scheme}://{host}:{port}"
    
    # Try common Moxa MGate info endpoints
    endpoints = [
        '/main.htm',
        '/index.htm',
        '/Overview.htm',
        '/api/v1/device/info',
        '/',
    ]
    
    model = None
    fw_version = None
    
    for ep in endpoints:
        try:
            resp = requests.get(
                f"{base_url}{ep}",
                timeout=10,
                verify=False,
                headers={'User-Agent': 'CVE-2026-86325-Checker/1.0'}
            )
            text = resp.text
            
            # Extract model
            m = re.search(r'(MB3170|MB3270|MB3180|MB3280|MB3480|MB3660|MGate\s*5217|W5108|W5208|5000|5100)', text, re.IGNORECASE)
            if m:
                model = m.group(1).strip().replace('MGate ', '').replace('MGate', '')
            
            # Extract firmware version patterns
            fw = re.search(r'[Ff]irmware\s*[Vv]ersion[:\s]+[Vv]?(\d+\.\d+(?:\.\d+)?)', text)
            if not fw:
                fw = re.search(r'[Vv]ersion[:\s]+[Vv]?(\d+\.\d+(?:\.\d+)?)', text)
            if fw:
                fw_version = fw.group(1)
            
            # Also check Server header
            server = resp.headers.get('Server', '')
            if 'Moxa' in server or 'MoxaHttp' in server:
                sm = re.search(r'[Vv]?(\d+\.\d+(?:\.\d+)?)', server)
                if sm and not fw_version:
                    fw_version = sm.group(1)
            
            if model and fw_version:
                break
                
        except requests.exceptions.RequestException:
            continue
    
    return model, fw_version

def main():
    parser = argparse.ArgumentParser(description='Check for CVE-2026-86325 (Moxa MGate Stack Overflow)')
    parser.add_argument('host', help='MGate device IP or hostname')
    parser.add_argument('--port', type=int, default=80, help='Web interface port (default: 80)')
    parser.add_argument('--https', action='store_true', help='Use HTTPS')
    args = parser.parse_args()
    
    if args.https and args.port == 80:
        args.port = 443
    
    print(f"[*] Checking {args.host}:{args.port} for CVE-2026-86325...")
    
    model, fw_version = check_device(args.host, args.port, args.https)
    
    if not model and not fw_version:
        print("UNKNOWN - Could not identify device model or firmware version.")
        print("    Verify the host is a Moxa MGate device and the web interface is reachable.")
        sys.exit(2)
    
    print(f"[*] Detected model: {model or 'Unknown'}")
    print(f"[*] Detected firmware: {fw_version or 'Unknown'}")
    
    if not fw_version:
        print("UNKNOWN - Could not determine firmware version.")
        sys.exit(2)
    
    # Check for models with no fix
    if model:
        for nf in NO_FIX_MODELS:
            if nf.lower() in model.lower():
                print(f"VULNERABLE - {model} has NO patch available for CVE-2026-86325.")
                print("    Contact Moxa support. Apply compensating controls immediately.")
                sys.exit(1)
    
    # Find the matching fixed version
    fixed_ver = None
    matched_model = None
    if model:
        for key, ver in FIXED_VERSIONS.items():
            if key.lower() in model.lower():
                fixed_ver = ver
                matched_model = key
                break
    
    if not fixed_ver:
        # Try all fixed versions and find closest match
        print(f"UNKNOWN - Model '{model}' not in known affected list.")
        print("    Manually verify against Moxa advisory MPSA-269540.")
        sys.exit(2)
    
    current = parse_version(fw_version)
    fixed = parse_version(fixed_ver)
    
    if current >= fixed:
        print(f"PATCHED - Firmware {fw_version} >= fixed version {fixed_ver} for {matched_model}.")
        sys.exit(0)
    else:
        print(f"VULNERABLE - Firmware {fw_version} < fixed version {fixed_ver} for {matched_model}.")
        print(f"    Update to firmware >= {fixed_ver} to remediate CVE-2026-86325.")
        sys.exit(1)

if __name__ == '__main__':
    main()
Peer Review

What defenders are saying.

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