
Writeup und Code für CVE-2025-11492, CVE-2025-11493 - RCE in ConnctWise Automate RMM über Adversary-in-the-Middle
Im Rahmen eines Penetrationstests entdeckte ich mehrere Schwachstellen im ConnectWise Automate Remote Monitoring and Management (RMM)-Agenten. ConnectWise wird von vielen Managed Service Providern (MSPs) zur Verwaltung und Überwachung von Kundengeräten eingesetzt. Diese Schwachstellen ermöglichten Remote-Codeausführung, wenn ein Angreifer einen Netzwerk-Adversary-in-the-Middle-Angriff durchführen konnte, oder konnten als lokale Privilegienausweitung und heimliche Persistenz genutzt werden, wenn ein Angreifer Codeausführung oder physischen Zugriff auf ein Gerät erlangte, auf dem der ConnectWise-Automate-Agent läuft.
Die Schwachstellen wurden ConnectWise am 20. August 2025 gemeldet. ConnectWise vergab CVE-IDs und veröffentlichte am 16. Oktober 2025 einen Patch in Version 2025.9.
ConnectWise-Bulletin:
CVE-IDs:
2025.9 und publiziert Sicherheitsbulletin und CVE-IDs.Ich schätzte ConnectWises schnelle Antworten und ihren kooperativen Ansatz bei der Behebung sowie ihre Bereitschaft, Diskussionen darüber zu führen, wie Klassifizierung und Behebung am besten angegangen werden.
Die Klassifizierung dieser Schwachstellen war eine interessante Herausforderung. Der Wechsel zu HTTPS löst zwar praktisch alle in diesem Bericht beschriebenen Szenarien, aber es war offensichtlich, dass dies ursprünglich eine Designentscheidung war (zur Unterstützung von HTTP), um die Zuverlässigkeit der Agent-Server-Kommunikation zu verbessern. Das Verschlüsselungsschema schien das Risiko von AiTM teilweise anzuerkennen/zu versuchen, es zu mindern, wurde aber nicht konsequent angewendet. Bei der Untersuchung ging es darum, einzuordnen, ob die Schwäche http selbst war oder das Fehlen von Verschlüsselung über HTTP sowie Replay-Schutz, Plugin-Validierung usw. eigene Schwachstellen darstellten. Zeitweise zog ConnectWise 5+ separate CVE-IDs für verschiedene Aspekte der Schwachstellen in Betracht.
Darüber hinaus änderten sich Umfang und Angriffsvektor je nachdem, ob die Schwachstelle aus einer AiTM-Perspektive, z. B. WLAN im Café, oder aus einer LPE/Physischer-Zugriff-Perspektive betrachtet wurde. Ein alternativer Ansatz wäre, jedes Szenario als separate Schwachstelle zu betrachten, z. B. AiTM-RCE, LPE, Persistenz-Übernahme usw.
Eine letzte Erkenntnis ist, dass wir selbst 2025 immer noch Schwierigkeiten haben, Dateien effektiv zu teilen :D (E-Mail-Sicherheit mochte es nicht, wenn ich .dll-Dateien oder .zips mit solchen Inhalten per E-Mail verschickte).
Dieser Bericht wird nach der Veröffentlichung eines Patches und der Offenlegung der CVE-IDs durch ConnectWise veröffentlicht, und zwar mit deren Zustimmung, dass eine solche Offenlegung ihren Benutzern nicht schadet. Darüber hinaus glaube ich, dass die öffentliche Offenlegung dieser Schwachstellen und ihrer Gegenmaßnahmen anderen Herstellern und Sicherheitsexperten helfen wird, Risiken sowohl in ConnectWise Automate als auch in anderen RMM-Systemen besser zu verstehen und zu mindern.
Der Inhalt ist ausschließlich für rechtmäßige, autorisierte Sicherheitsforschung und Bildungszwecke bestimmt. Die unbefugte Nutzung dieser Informationen zur Kompromittierung von Systemen, Netzwerken oder Daten ist illegal und unethisch. Der Inhalt wird ohne jegliche Gewährleistung bereitgestellt. Der/die Autor(en) lehnen jede Haftung für Schäden ab, die aus der Nutzung oder dem Missbrauch dieser Informationen entstehen.
Wenn Sie diesen Code oder diese Informationen für weitere Forschung verwenden, praktizieren Sie verantwortungsvolle Offenlegung, indem Sie entdeckte Schwachstellen an den/die betroffenen Hersteller melden.
Zusätzlich zum untenstehenden Bericht enthält dieses Repository PoC-Code zur Demonstration der Schwachstellen. Siehe automate_server/README.md für Details zur Fake-Server-Implementierung und Nutzungsanweisungen.
Dieser Code könnte auch verwendet werden, um weitere (ethische) Sicherheitsforschung an ConnectWise Automate durchzuführen.
Der folgende Bericht (oder eine Version nahe daran) sowie der PoC-Python-Code in diesem Repository wurden ConnectWise zusammen mit empfohlenen Gegenmaßnahmen zur Verfügung gestellt.
Der entfernte Abschnitt zu Gegenmaßnahmen geht detaillierter auf Änderungen ein, die am Automate-Agenten vorgenommen werden könnten, um ihn auf verschiedene Weise gegen diese Schwachstellen zu härten.
Da einige dieser Änderungen von ConnectWise noch geprüft werden, wurde dieser Abschnitt aus dieser öffentlichen Offenlegung entfernt.
Der ConnectWise Automate Remote Monitoring and Management (RMM)-Agent (getestet mit der neuesten Version vom August 2025, Versionszeichenkette 250.252) ist in bestimmten Konfigurationen anfällig für netzwerkbasierte Remote-Codeausführung. Wenn der Agent für seine Server Address einen unverschlüsselten HTTP-Transport verwendet (entweder primär oder als Fallback) und ein Angreifer einen Adversary-in-the-Middle-Angriff (AiTM) durchführen kann, kann er aus der Ferne Code als SYSTEM ausführen. Diese Konfiguration wurde in freier Wildbahn bei mehreren Managed Service Providern (MSPs) beobachtet.
Eine Ausnutzung ist auch möglich, wenn der Angreifer als Nicht-Administrator physischen Zugriff auf das Gerät erlangt oder das Gerät auf andere Weise mit einem vom Angreifer kontrollierten Netzwerk verbindet (d. h. die Schwachstelle kann als lokale Privilegienausweitung genutzt werden). Obwohl Automate ein Verschlüsselungssystem einsetzt, um die meisten RMM-Befehle zu verschlüsseln und zu validieren, fehlt es dem Plugin-System an angemessenem Schutz und es bleibt anfällig für Remote-Codeausführung.
Durch die Implementierung eines benutzerdefinierten Servers, der Automates Steuerserver nachahmt, kann der Automate-Agent dazu gebracht werden, ein bösartiges Plugin herunterzuladen und auszuführen.
Der kompromittierte Agent kann auch als attraktive Form der Persistenz dienen. Mithilfe der RCE zum Extrahieren der symmetrischen Verschlüsselungsschlüssel des Agents kann der benutzerdefinierte Server über den standardmäßigen RMM-Kanal beliebige Befehle an den Agenten senden. Im AiTM-Szenario kann der Angreifer so beliebige RMM-Befehle ausführen, einschließlich Dateiextraktion, Credential-Dumping, Befehlsausführung und Änderung der Konfiguration. Der Angreifer könnte auch die Server Address des RMM auf den eigenen Server ändern und so selbst nach dem AiTM-Angriff eine heimliche Persistenz erreichen. Alternativ kann die RCE genutzt werden, um direkt systemweite Befehle auszuführen.
Server Address, die einen http://-Endpunkt enthält. Verwundbare Konfigurationen wurden bei zwei verschiedenen MSPs beobachtet (tatsächliche MSP-Domains und IPs wurden ersetzt):
https://automate.msp-one.com|http://automate.msp-one.comhttps://msp.msp-two.com|http://msp.msp-two.com|http://12.346.6.78http://-Endpunkt als Fallback verwendet, wenn die https://-Verbindung fehlschlägt. Ein Angreifer kann dies jedoch simulieren, indem er https blockiert.Der Automate-Agent kann so konfiguriert werden, dass er eine http://-URL als Serveradresse verwendet. Diese Konfiguration wird wahrscheinlich vom Installationsskript/-paket festgelegt, kann aber durch Prüfung des Registrierungsschlüssels HKLM\SOFTWARE\LabTech\Service\Server Address validiert werden.

Die Verwendung sowohl der HTTPS- als auch der HTTP-Endpunkte, getrennt durch ein Pipe-Zeichen |, stellt theoretisch sicher, dass der Automate-Agent auf die HTTP-Verbindung zurückgreift, wenn die HTTPS-Verbindung auf ein Problem stößt.
Wenn ein Angreifer Adversary-in-the-Middle-Zugriff (AiTM) auf den Netzwerkverkehr zwischen dem Automate-Agenten und dem Server erlangt, kann er die HTTPS-Verbindung absichtlich stören, sodass sie auf HTTP zurückfällt. Dies ermöglicht es dem Angreifer, den zwischen Agent und Server ausgetauschten Verkehr abzufangen, zu überwachen und zu verändern. Ein Angreifer kann dann den Verkehr per Reverse-Proxy an https://automate.msp-one.com weiterleiten, was zum „Normalbetrieb“ des Agents führt, der Angreifer jedoch die Daten abhören kann. Zusätzlich kann er Antworten injizieren oder modifizieren oder sogar einen vollständig gefälschten Automate-Server einrichten, der auf Anfragen des Automate-Agenten antwortet.
Dies wurde durch die Einrichtung eines „Rogue“-WLAN-Zugangspunkts (hostapd, dnsmasq, IP-Forwarding + NAT) und die Verwendung von iptables-Regeln zur Verkehrsumleitung sowie eines mitmproxy-Skripts für den Reverse-Proxy erreicht.

Andere, sensiblere Daten, darunter laufende Programme, vollständige Netzwerkkonfiguration und Dokumentpfade, wurden gelegentlich in den Antworten des Automate-Agenten beobachtet.
iptables -t nat -A PREROUTING -i wlx90916440139a -p tcp --dport 80 -j REDIRECT --to-port 8080 iptables -A FORWARD -i wlx90916440139a -p tcp --dport 443 -j DROP
#### mitmproxy Skript:```python
# run with AiTMweb --mode transparent@8080 -s automate_AiTM.py
def request(flow: http.HTTPFlow):
if flow.request.pretty_host == 'automate.msp-one.com':
flow.request.url = 'https://automate.msp-one.com' + flow.request.path
ZTNA-Lösungen können dieses Abfangen etwas erschweren, aber diese wurden zuverlässig durch weitere mitmproxy-Skripte umgangen, die ZTNA bedingt erkennen und blockieren, was zu einem Fallback auf nicht getunneltes HTTP führte.
Der Automate-Agent verwendet ein benutzerdefiniertes Protokoll auf Basis von HTTP, um mit dem Server zu kommunizieren.
Der RMM-Agent auf dem Gerät sendet regelmäßig HTTP(S)-Anfragen an den Endpunkt /LabTech/agent.aspx des Servers. Die relevanten Anfragetypen sind:
Beachten Sie, dass die inkonsistente Groß-/Kleinschreibung der Pfade kein Tippfehler ist; so sendet der Automate-Agent diese Anfragen. Alle Endpunktpfade sind zur besseren Übersicht in Code-Ticks gesetzt.
/LabTech/Agent.aspx?DEPS an und erhält eine XML-Antwort mit einer Liste der Abhängigkeitsdateien, deren Versionsnummern und Prüfsummen./LabTech/Agent.Aspx?DepCheck=1&DependancyId=<id> an und erhält eine verschleierte Binärdatei, die die Abhängigkeit enthält und als Bilddatei getarnt ist (vermutlich soll die Verschleierung verhindern, dass Inhaltsfilter den Download blockieren)./LabTech/agent.aspx?<id>?c<CMD id>&<arg count> an und erhält eine benutzerdefiniert verpackte Antwort mit befehlsspezifischen Daten.InitialCommandRetrieve), Ergebnisse von Befehlen zurückzugeben und Chat durchzuführen.Sensible „Remote-Befehle“ sind oft mit einem auf DES3 basierenden Verschlüsselungsschema verschlüsselt, das eine benutzerdefinierte Schlüsselableitung aus einem voreingestellten system password und computer password verwendet. Ohne die korrekten Passwörter kann ein Angreifer legitime, an den Agenten gesendete Befehle weder einsehen, injizieren noch modifizieren; allerdings sind Befehlsantworten unverschlüsselt und enthalten nachweislich häufig sensible Klartextdaten wie geöffnete Dateien, Pfade, Benutzernamen, installierte Programme usw.
Die Abhängigkeitsprüfung (/LabTech/Agent.aspx?DEPS) und die Downloads (/LabTech/Agent.Aspx?DepCheck=1&DependancyId=<id>) sind weder verschlüsselt noch signiert, sodass ein Angreifer die Antwort manipulieren kann, um schädliche Abhängigkeiten einzuschließen, die vom RMM-Agenten heruntergeladen und geladen werden. Wenn die Abhängigkeitsprüfung gefälscht wird und eine andere Prüfsumme enthält, lädt der RMM-Agent die nicht übereinstimmende Abhängigkeitsdatei frisch herunter und lädt sie (sofern die neu heruntergeladene Datei der gefälschten Prüfsumme entspricht). Plugins sind .NET-Assemblys, die ein bestimmtes Interface implementieren, und der Automate-Agent lädt jede .NET-Assembly, die dem erwarteten Plugin-Interface entspricht, und ruft dann das Interface des Plugins auf, was zur Codeausführung führt.
Für heruntergeladene Plugin-Abhängigkeiten gibt es eine zweite Validierungsebene: Der Agent sendet einen cmdGetPlugins-Befehl und validiert auch hier, dass die Prüfsumme übereinstimmt, aber dieser Befehl verwendet das Verschlüsselungsschema nicht.
Mit dnSpy war es möglich, schädlichen Code in die legitime, vom Agenten verwendete ScreenConnectRemotePlugin.dll zu injizieren. Es wurde ein eigener Automate-Server mit der Funktionalität der Befehle DEPS, DepCheck und cmdGetPlugins erstellt. Der gefälschte Server replizierte die erwarteten Plugins und Abhängigkeiten, änderte jedoch den Hash der ScreenConnectRemotePlugin.dll auf einen berechneten Hash des bösartig modifizierten Plugins. Der gefälschte Server stellte die bösartig modifizierte ScreenConnectRemotePlugin.dll auch als Antwort auf die DepCheck-Anfrage bereit (im verschleierten Fake-Bild-Format) und implementierte cmdGetPlugins ebenfalls mit dem manipulierten Hash. Schließlich wurde das mitmproxy-Skript aktualisiert, um den Automate-Agenten anstelle des legitimen (HTTPS-)Servers an den gefälschten Server zu leiten.
Bei der Verbindung wird das schädliche Plugin vom Agenten heruntergeladen und geladen. Der injizierte Code exfiltriert die Passwörter „system“ und „computer“ an den gefälschten Server. Die Passwörter system und computer sind in der Registrierung gespeichert, werden jedoch von einer stark verschleierten C#- und nativen Bibliothek dekodiert. Anstatt die Registrierungswerte zu extrahieren, verwendet das gepatchte Plugin Reflection, um die dekodierten Werte zu erhalten, was den Aufwand des Reverse Engineering der Verschleierung erspart. Alternativ könnten die gesamten Inhalte des Registrierungsschlüssels HKLM\SOFTWARE\LabTech\Service exfiltriert und mit einer Kopie des RMM-Agenten in einer kontrollierten Umgebung verwendet werden, um die Passwörter zur Laufzeit mit einem .NET-Debugger zu extrahieren.


Alternativ kann das Plugin verwendet werden, um direkt Systembefehle auszuführen; das Extrahieren der Geheimnisse ermöglichte jedoch die Nutzung des RMM-Agenten selbst als Command-and-Control-Kanal und führte dazu, dass der persistente Kanal von EDR unentdeckt blieb. Persistenz kann erreicht werden, indem die Server Address auf einen angreiferkontrollierten Server aktualisiert wird, der optional Befehle an den legitimen Server weiterleiten kann, um zu vermeiden, dass das Gerät als fehlend angezeigt wird. Weitere Einzelheiten finden Sie unter 3. RMM Command-and-Control-Übernahme.
Es ist anzunehmen, dass selbst bei einer Standardkonfiguration ohne installierte Plugins ein leeres Plugin (das die für Plugins erforderlichen C#-Interfaces erfüllt) hätte kompiliert und in die DEPS- und cmdGetPlugins-Antworten eingefügt werden können, um denselben Effekt zu erzielen.
Des Weiteren wurde beobachtet, dass der Server einen „Remote-Befehl“ namens UpdatePlugins zurückgeben kann, der den Agenten dazu veranlasst, ein Plugin-Update zu starten. Da Befehle keinen Replay-Schutz enthalten, kann ein Angreifer, der den von einem legitimen Server gesendeten Befehl beobachten kann, diesen an beliebige andere Agenten erneut abspielen, um das Update auszulösen. Dadurch kann die RCE-Schwachstelle in zusätzlichen Szenarien ausgenutzt werden, was die Auswirkungen dieser Schwachstelle erhöht.
Auch die Selbstaktualisierung wurde als unverschlüsselt und unsigniert beobachtet. Eine Demonstration der Remote-Codeausführung über die Selbstaktualisierung wurde nicht durchgeführt, es wird jedoch angenommen, dass sie ähnlich anfällig ist. Eine böswillige Modifikation der Selbstaktualisierung wäre schwieriger heimlich durchzuführen und birgt ein höheres Risiko, den Automate-Agenten zu beschädigen; allerdings würde wahrscheinlich ein ähnlicher Ansatz des Injizierens von .NET-Code in die ausführbaren Dateien/DLLs funktionieren. Der Prozess der Selbstaktualisierung wurde nicht weiter untersucht, da die Plugin-RCE ausreichte und als zuverlässiger erachtet wurde.
Es ist auch möglich, dass die Ausnutzung des Selbstaktualisierungsprozesses eine praktikable Lösung für die Einschränkung darstellt, dass die Schwachstelle nur bei einem Neustart ausnutzbar ist (z. B. wenn eine Antwort injiziert oder erneut abgespielt werden könnte, um eine Selbstaktualisierung auszulösen).
Mit dem Ansatz aus 2.1 zum Extrahieren des system password und computer password war es möglich, beliebige „Remote-Befehl“-Payloads und -Antworten zu erstellen. Anstatt das Schlüsselableitungsschema vollständig zu reverse-engineeren und neu zu implementieren, war es möglich, einfach LabTechCommonBase.dll zu importieren und Utilities.LabTechHash.ComputeHash zu verwenden, um den DES3-Schlüssel aus dem „computer password“ zu generieren. Mit dem berechneten DES-Schlüssel und der aus der DLL extrahierten hartkodierten IV war es dann möglich, mit beliebigen Befehlen auf den RMM-Agenten zu antworten.```python
# IV extracted from decompiled LabTechSecurity.cs:
# this._initializationVector = new byte[] { 240, 3, 45, 29, 0, 76, 173, 59 };
iv = [240, 3, 45, 29, 0, 76, 173, 59]
# Helper functions for pythonnet, clr_loader, clr to load LabTechCommonBase.dll into python
labtech_net.setup_paths_and_references(str((Path(__file__).parent.parent / 'LTSvc').resolve()))
from LabTechCommonBase import Utilities
labtech_hash = Utilities.LabTechHash()
labtech_hash.ComputeHash(computer_password.encode('ascii')) # Use the exfiltrated computer password
byts = bytes(labtech_hash.GetDigestBytes())
cipher = DES3.new(byts, DES3.MODE_CBC, bytes(iv))
padded_data = pad(data.encode('utf-8'), DES3.block_size)
encrypted_data = cipher.encrypt(padded_data)
return base64.b64encode(encrypted_data).decode('utf-8')
Handler für eine Vielzahl von „Agent Command“-Typen wurden im Fake-Automate-Server implementiert, sodass dieser „Remote Commands“ an den Agenten zurücksenden kann. Diese Befehle können verwendet werden, um beliebigen Code auf dem Gerät auszuführen, z. B. um eine Payload herunterzuladen und auszuführen oder Netzwerktunnel auf das Gerät aufzubauen (z. B. die Einrichtung eines SOCKS-Proxys, der genutzt werden könnte, um durch den ZTNA-Zugriff des Geräts zu pivotieren).
Für die sofortige Bereinigung aus 2.1 kann der Server den verschlüsselten `UpdatePlugins`-Befehl senden und das ursprüngliche legitime Plugin ausliefern, um das bösartig modifizierte Plugin zu überschreiben. Der Angreifer kann weiterhin mit dem Agenten interagieren (vorausgesetzt, die Passwörter wurden extrahiert) und kann die Persistenz aufrechterhalten, indem er die `Server Address` auf einen vom Angreifer kontrollierten Server aktualisiert.

Auch die beliebige Ausführung von Befehlen wurde mithilfe des `Execute`-Befehls demonstriert, um einen Ping auszuführen, der erfolgreich auf dem Gerät in einem Administratorkontext ausgeführt wurde. Dies kann als `InitialCommandRetrieve`-Befehl bereitgestellt oder als Antwort auf andere „agent commands“/Check-ins zurückgegeben werden.```python
# Extract the RemoteCommandIDs enum from LabTechCommonBase.Constants using pythonnet
REMOTE_CMD_IDS = get_RemoteCommandIDs()
REMOTE_CMD_IDS_r = {str(v): k for k, v in REMOTE_CMD_IDS.items()}
# `register_cmd_handler` registers a command handler for the `/LabTech/agent.aspx?c<id>` endpoint.
# The string 'InitialCommandRetrieve' is mapped back to ID `36`.
# The full set of "Agent Command" and their IDs can be extracted from `LabTechCommonBase.Constants.modEnums.AgentCommandIDs`
@register_cmd_handler('InitialCommandRetrieve')
async def initial_command_retrieve(_req: dict) -> str:
cmd = '*!*'.join([
'202706506',
str(REMOTE_CMD_IDS_r['Execute']),
'!!!'.join([
'CMD.exe',
'/c ping -t -l 1337 192.168.20.2'
])
])
encrypted_cmd = encrypt(cmd)
return '|||'.join([
len_b64_gzip( # Simple helper to return '{len(data)}-{base64(gzip(data))}'
encrypted_cmd
),
# Generate common [latest-version, FILETIME(), queued command(s), MD5 hashes] encoding string expected in "agent command" responses
make_p2(),
])

Die Verwendung von -l 1337 weist ping an, eine Payload-Größe von 1337 Bytes zu verwenden, die dann im zweiten Screenshot (1337 Payload-Bytes + 42 Header-Bytes = 1379 Bytes insgesamt) als „Canary" erkennbar ist.
Abschnitt aus der öffentlichen Offenlegung entfernt.