
安全にVeeam Service Provider Consoleの認証バイパスCVE-2026-58073を検出する
Veeam Service Provider Console における KB4893 脆弱性(2026-08-04 公開)のための、安全で認証不要の検出ツールです。認証や TLS の前に、ターゲットごとに1つの質問に答えます:このコンソールに KB4893 の修正が適用されているか?
主役となる2つの脆弱性は連鎖します。CVE-2026-58073(CVSS 9.5)は、認証されていないネットワーク上のピアが、接続済みの管理エージェントになりすまし、そのエージェントの実際の証明書を発行されることを可能にします。これは、エージェントのハンドシェイクが、ピアが自身の証明書に書き込んだ GUID から認可を決定するためです。CVE-2026-58072(CVSS 9.0)は、エージェントの ID を取得すると到達可能な任意のファイル書き込みです。連鎖すると、すべてのテナントのバックアップを管理するコンソール上での、認証なしのリモートコード実行となります。同じアドバイザリでは、CVE-2026-58071(CVSS 8.2、Portal Administrator としてのプロキシ化されたアプライアンス API)と CVE-2026-58067(CVSS 8.7、認証なしのメモリ枯渇 DoS)も修正されています。CVE-2026-58073 と CVE-2026-58072 は HackerOne を通じて Veeam に報告されました。アドバイザリは報告者を明示していません。
このスクリプトは、偽装の試行、証明書の要求、ファイルの書き込みを行いません。ルーターがアドバタイズするプロトコル世代を読み取るだけです。
はい。この検出器は本番環境および評価での使用を想定して設計されています:
Connector ハンドシェイクのみを送信します。TLS セッションはネゴシエーションされず、証明書は提示されず、SaveFiles は呼び出されません。ChannelHostProxy.m_multiplexers での失敗する辞書検索です。レシーバーは登録されず、チャネルやマルチプレクサーは構築されず、エージェントレコードには触れません。Receiver タイプのハンドシェイクは名前を登録しますが、このツールは決して送信しません。ConnectionHub.log の6行で、それぞれにレシーバー名 bf-probe-<uuid4> が含まれるため、防御側はスキャンと攻撃を区別できます。正確な行は以下に示します。VULNERABLE と報告されます(下記参照)。したがって、静かな TCP サービスが未パッチのコンソールと誤認されることはありません。ツールはターゲットごとに2つの TCP 接続を開き、それぞれに1つの ConnectionHub ハンドシェイクを送信し、存在しないレシーバー bf-probe-<uuid4> を指定します。
デフォルトの --transport auto では、ポートが示すトランスポートと異なるトランスポートのターゲットは、追加で1接続を消費します:誤ったトランスポートのプローブは、レシーバー名が読み取られる前にハンドシェイク中に拒否され、その後、正しいトランスポートが両方の実際のプローブに使用されます。--transport direct または --transport gateway を指定すると、正確に2接続に固定できます — 変更要求で接続数を提示している場合は、これを行う価値があります。
サーバー上で変更される状態:なし。 Connector コードパスは ChannelHostProxy.m_multiplexers で辞書検索を実行し、見つからず、エラーを返します。レシーバーは登録されず、マルチプレクサーやチャネルは作成されず、TLS セッションはネゴシエーションされず、エージェントレコードには触れません。このツールは、名前を登録する唯一のタイプである Receiver タイプのハンドシェイクを決して送信しません。
ログエントリは %ProgramData%\Veeam\Veeam Availability Console\Log\Server\ConnectionHub.log に書き込まれます。ライブの 9.2.1.33875 ConnectionHub からの逐語的な内容(タイムスタンプとスコープ JSON は省略):
probe 1 (version 6)、パッチ適用済み・未適用の両ビルド:
[INFO] ChannelHostProxy: Accept connection begin {"RemoteEndPoint":"<ip>:<port>","Line":"1"}
[INFO] ChannelHostProxy: Accept connection end {"RemoteEndPoint":"<ip>:<port>","Line":"2",...}
[WARN] ChannelHostProxy: Cannot connect transmitter. Requested receiver not found
(receiver name:bf-probe-<uuid>) {"RemoteEndPoint":"<ip>:<port>","Line":"3",...}
probe 2 (version 7)、パッチ適用済みビルドのみ:
同じ3行
probe 2 (version 7)、未適用ビルド:
[INFO] ChannelHostProxy: Accept connection begin
[WARN] ChannelHostProxy: Handshake failed. Reason:Unsupported client version "7"
[INFO] ChannelHostProxy: Accept connection end
2接続、6行、他のエントリなし、状態変更なし — ライブホストで確認済みです。
ConnectionHub.log 内のリテラル文字列 bf-probe- はこのツールのトラフィックを識別するため、防御側はそれを帰属でき、スキャンチームは送信した内容を証明できます。別のマーカーが必要な場合は、ソース内の RECEIVER_PREFIX を変更してください。
ConnectionHub 管理エージェントルーターは、認証や TLS の前にクライアントハンドシェイクを読み取り、Request.Read はクライアントがアドバタイズするプロトコルバージョンをハードコードされた範囲に対して検証します。修正により、CVE を修正した同じビルドでその範囲が拡大されました:
| ビルド | チェック | 受け入れ |
|---|---|---|
<= 9.2.1.33875(脆弱) | (uint)(versionByte - 3) <= 3 | 3, 4, 5, 6 |
>= 9.3.0.35057(パッチ適用済み) | (uint)(versionByte - 3) <= 4 | 3, 4, 5, 6, 7 |
したがって、バージョン7をアドバタイズするハンドシェイクは、明確なバイナリ判別子となります。検出器はターゲットごとに2つのプローブを送信します。この順序には理由があります(トランスポート検出により3つ目が追加される場合があります — 下記参照):
| プローブ | アドバタイズ | 目的 |
|---|---|---|
| 1 | バージョン 6 | Requested receiver not found を返す必要があり、ターゲットが実際に VSPC ConnectionHub であることを証明 |
| 2 | バージョン 7 | 応答があれば PATCHED、沈黙なら VULNERABLE |
ステージ1のゲートがないと、プローブ2の沈黙はインターネット上の静かな TCP サービスにも一致し、ファイアウォールが脆弱な Veeam コンソールとして報告されることになります。
管理エージェントが使用する両方のパスで動作します:
| トランスポート | ポート | 露出 |
|---|---|---|
| ConnectionHub への直接 | 9999 | 通常は内部 |
| Veeam Cloud Connect ゲートウェイ経由 | 6180 | 設計上インターネットに面している |
ゲートウェイパスには、直接パスにはないリレープロローグが必要です。そのため、プローブ1はトランスポート検出を兼ねます。デフォルトの --transport auto では、1つのトランスポートを試し、フィンガープリントゲートが通過しない場合は、もう1つを試します。通過した方がラッチされ、プローブ2はそれを再利用します — 混在するターゲットファイルにホストごとの注釈は不要です。
ラッチは重要な役割を果たします。プローブ2が他のトランスポートで再試行できる場合、沈黙はバージョンチェックに帰属できなくなり、「2つのバイトパスのうち1つが応答しなかった」というだけになり、それが誤った VULNERABLE が生成される方法です。
どちらのトランスポートが最初に試されるかはポートによって決まり、これは見た目だけの問題ではありません — 2つの不一致は非常に異なる速度で失敗します:
| 不一致 | 相手側の解釈 | コスト |
|---|---|---|
| リレープローローグ → 直接ハブ | hostType 44 / versionByte 0 の int16 メタ、Request.Read の範囲チェックに失敗 | 1ラウンドトリップで破棄 |
| 直接ハンドシェイク → ゲートウェイ | 1,012,729,346 の int32 フレーム長 | ゲートウェイは決して届かないバイトを待ち、完全なタイムアウトを消費 |
したがって、auto はポートを所有するサービスを先頭にします:6180 ではゲートウェイが先、それ以外では直接が先です。これにより、一般的なケースは単一の試行に保たれ、高コストの不一致は高速パスから外れます。TCP を開けないプローブは、2番目のトランスポートを試さずに短絡するため、広範囲スイープでの死んだホストは1タイムアウトで済み、2つではありません。
VULNERABLE は「KB4893 の修正が存在しない」ことを意味し、「これが 9.2.1.33875 である」ことを意味しません。9.2.1 より古いビルドは同じバージョンチェックを共有するため、プロトコル6を報告し、脆弱として報告されるべきです(コードから推定され、測定されたものではありません — 制限事項 を参照)。ただし、ツールは 9.2.1 と 9.1 や 8.1 を区別できません。正確なビルドが必要な場合は、コンソール UI で確認してください。
# 単一ホスト(デフォルト TCP/9999)
./cve_2026_58073_check.py vspc.example.com
# 明示的なポート、複数ホスト
./cve_2026_58073_check.py vspc.example.com:9999 10.0.0.5
# リストをスキャン、1行に1ターゲット('#' コメント可)、コンパクト出力
./cve_2026_58073_check.py -f targets.txt --brief
# パイプライン用の機械可読出力
./cve_2026_58073_check.py -f targets.txt --json > results.json
# Veeam Cloud Connect ゲートウェイ — リレートランスポートは自動検出されます
./cve_2026_58073_check.py cc-gw.example.com:6180
# トランスポートを固定して検出をスキップ(ポートはデフォルトで 6180 になります)
./cve_2026_58073_check.py --transport gateway cc-gw.example.com
# ネットワークアクセスなしでワイヤーコーデックを検証
./cve_2026_58073_check.py --self-test
| フラグ | 説明 |
|---|---|
targets | 1つ以上の HOST[:PORT](ポートはデフォルトで 9999、--transport gateway では 6180) |
-f, --targets-file FILE | ファイルからターゲットを読み取る(1行に1つ、# コメント) |
--transport {auto,direct,gateway} | ConnectionHub への到達方法。auto(デフォルト)はターゲットごとに検出、gateway は Cloud Connect リレープローグを前置し、ポートをデフォルトで 6180 にします |
-p, --port PORT | デフォルトポートを上書き |
--timeout SECS | プローブごとのタイムアウト(デフォルト:8) |
--workers N | 同時ターゲット数(デフォルト:16)、出力は入力順を維持 |
-b, --brief | ターゲットごとに1つの整列された行 — 多数のホストのスキャンに最適 |
--json | 構造化 JSON を出力、ターゲットごとに送信されたすべてのプローブを含む |
--no-color | 色付き出力を無効化(NO_COLOR と非 TTY も尊重) |
--self-test | .NET ワイヤーコーデックを検証して終了、ネットワークアクセスなし |
未パッチのコンソール(デフォルトの2行出力)。[!] マーカーと VULNERABLE は TTY で赤く表示されます:
$ ./cve_2026_58073_check.py vspc.example.com
[!] vspc.example.com:9999: VULNERABLE [protocol-7-rejected]
ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)
パッチ適用済みのコンソール:
$ ./cve_2026_58073_check.py patched.example.com
[+] patched.example.com:9999: PATCHED [protocol-7-accepted]
ConnectionHub accepts protocol 7, so the KB4893 fixes are present (>= 9.3.0.35057)
ゲートウェイターゲット、リレートランスポートが自動検出されます。(gateway) サフィックスは、判定が行われたトランスポートを示します:
$ ./cve_2026_58073_check.py cc-gw.example.com:6180
[!] cc-gw.example.com:6180 (gateway): VULNERABLE [protocol-7-rejected]
ConnectionHub rejects protocol 7 but accepts 6, so the KB4893 fixes are absent (<= 9.2.1.33875)
環境全体のスイープ、ホストごとに1つの整列された行(--brief)。終了ステータスは、いずれかのホストが VULNERABLE の場合は 1、それ以外は 0 — スクリプトに便利です:
$ ./cve_2026_58073_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE vspc.example.com:9999 protocol-7-rejected
PATCHED patched.example.com:9999 protocol-7-accepted
UNAFFECTED fileserver.example.com:9999 not-vspc
ERROR unused.example.com:9999 unreachable
exit: 1
パイプライン用の機械可読出力(--json)。ターゲットごとにすべてのプローブが含まれるため、発見事項は証拠から再導出でき、信頼する必要はありません。transport は判定が行われたトランスポートであり、各プローブは使用したトランスポートを保持します — したがって、自動検出されたターゲットは拒否された試行も表示します: