pfSense Plus MIM API toolkit b4acd7ca - 高 - リモート - 権限の残存 - Paramiko AutoAddPolicy enroll
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-enroll-autoadd
クラス: 特権の残存 到達範囲: リモート
pfSense Plus MIM API (Netgate/pfsense-api) b4acd7ca - Netgate
example-add-devices.py は、Nexus コントローラーを各 pfSense デバイスに登録するための文書化された方法です。これは load_system_host_keys() を決して呼び出しません。paramiko.AutoAddPolicy() を設定し、次に connect、次に exec_command(device_script) を実行します。コメントには、デバイスがすでに known_hosts にある場合は AutoAdd を削除するよう書かれています。出荷時のデフォルトは AutoAdd です。
新しいボックスへの初回接触 SSH は、応答したホスト鍵をそのまま受け入れます。パスワードまたは鍵認証がそのピアに提示されます。stdout は json.loads され、実際のコントローラーへ POST /mim/devices されます。
これはサードパーティの CE REST パッケージではありません。これは公式の OpenAPI と、pfSense Plus Nexus Multi-instance Management 用に生成された Python クライアントです。サーバーは Plus 専用です。ラボは Paramiko SSH ガジェットです。私は稼働中の Plus コントローラーとは通信していません。
| ID | CVE はまだなし |
| クラス | 特権の残存 (登録 SSH における Paramiko AutoAddPolicy) |
| 到達範囲 | リモート (初回接触時のデバイス SSH への on-path) |
| CWE | CWE-322 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 製品 | Netgate/pfsense-api (Plus Nexus MIM クライアントツールキット) |
| 影響対象 | main b4acd7ca21dbca739a530403a1f62a7440f7726f example-add-devices.py |
| 認証 | オペレーターが公式サンプルを実行し、攻撃者はデバイス SSH への on-path にいる |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:19111 のみ。Plus イメージなし。 |
AC:H は初回接触 / on-path です。実際のデバイス鍵がすでに known_hosts にあり、かつ AutoAdd 行が削除されているワークステーションは、この残存には該当しません。
同じピンに残る問題: ControllerSummary の登録シェルへの JSON 補間 (G1) と サンプルが verify_ssl=False を強制 (G9)。シリーズハブ: pfsense-api-nexus-mim。
オペレーターがサンプルを実行している間、pfsense_addresses 内の初回接触 SSH アドレスへの on-path に位置します。AutoAdd は依然として有効です。
| Method | Sink | Privilege |
|---|---|---|
pfsense_addresses 内の初回接触 SSH アドレスに対して on-path に座る | set_missing_host_key_policy(paramiko.AutoAddPolicy()) の後に connect (example-add-devices.py:151-160) | Integrity (lab-proven): 未知のホスト鍵が受け入れられる。Lab: AutoAddPolicy は接続成功 (autoadd=yes)。RejectPolicy は失敗 (reject-control=yes)。 |
同一セッションで exec_command(device_script) に応答 | stdout が DeviceIdentity としてパースされる (example-add-devices.py:161-187) | Integrity (lab-proven): exec が PFSENSE-API-ENROLL-AUTOADD-WITNESS を含む identity JSON を返した (identity-json=yes)。 |
| 同一 MITM で exec ペイロードを読む | device_script は G1 の ControllerSummary に対する curl -d の残骸 | Recon (inferred from source): コントローラの identity key、Netgard の vpn_pubkey / vpn_netkey / listen addrs。この lab ではダンプしていない。 |
| 同一 MITM でパスワードまたは鍵認証 | SSHUSER / SSHPASS または agent/keys (example-add-devices.py:156-160) | Recon (inferred): 偽ホストに提示された資格情報または鍵。Lab ではサンプルの SSHPASS パスとしてパスワード認証のみを使用。 |
同一 stdout JSON、add_controlled_device.sync | 実コントローラ上の POST /mim/devices | Integrity (inferred): 攻撃者の Noise/VPN 鍵と address を登録する。さらにこの lab ではハンドシェイクは実行されていない。 |
| MITM が SSH サーバーである | クライアントが送った exec の内容すべて、SSHUSER として | Integrity / availability (inferred): 登録スクリプトを実行、破棄、またはスキップする。実デバイス上の Unix-socket 呼び出しは、MITM がそれを転送した場合にのみ発生する。 |
Lab-proven vs inferred: AutoAdd 接続、RejectPolicy 失敗、および witness を含む identity JSON は lab 実証。コントローラ鍵のダンプ、資格情報窃取、偽デバイスの POST /mim/devices、および実際の unix-socket curl の実行は、同じサンプルパスからの推測である。
Requires: オペレーターが公式サンプルを、ホスト鍵がまだピン留めされていない SSH アドレスに対して、AutoAdd を有効にしたまま実行すること。その SSH へのネットワーク経路。AC:H は初回接触 / on-path。
| Surface | Why |
|---|---|
同じ未知ホストに対する RejectPolicy | Lab: reject-control=yes。Paramiko は鍵を拒否する。 |
known_hosts に実デバイス鍵があり、かつ AutoAdd 行が削除されたワークステーション | コメントが意図するモード。呼び出しを追加しない限り、サンプルはそれらの鍵を読み込まない。 |
| HTTPS コントローラログイン | verify_ssl=False は兄弟サンプルの残骸 (G9) であり、この sink ではない。 |
| 実ファイアウォール上の Unix-socket MIM | MITM が exec を転送する場合のみ。この lab は /var/run/pfnet-controller.sock と一切通信しない。 |
生成された Client のデフォルト verify_ssl=True | ライブラリのデフォルトは残骸ではない。サンプルは False を強制する。 |
Plus RBAC / ライブ :8443 | この lab は Paramiko ガジェットである。Plus コントローラとは通信していない。 |
| 未認証のインターネットから 8443 へ | ログインは依然として JWT を発行する。この所見ではない。 |
| Diagnostics PHP/shell | フリート JWT に対する意図された管理者権限。この所見ではない。 |
CE WebGUI の残骸の後、github.com/Netgate/pfsense-api の main b4acd7ca21dbca739a530403a1f62a7440f7726f をピン留めした。このツリーは OpenAPI と Plus Nexus MIM 向けに生成された Python である。example-add-devices.py の登録ループを読んだ。ホスト鍵ポリシーは AutoAdd。シークレットは同じ exec チャネル上にある。サンプルは load_system_host_keys() を一切呼び出さない。
記録済みの誤った道: AutoAdd を意図された lab 専用とみなすこと (コメントは opt-out であり opt-in ではない)、known_hosts が読み込まれると仮定すること、これを ControllerSummary のシェル補間の残骸に混ぜること、Plus をライブで lab 検証すること、これを :8443 への未認証 HTTPS だと主張すること。
Theatre: リバースシェル。オラクルは RejectPolicy fail と AutoAdd connect、そして witness を含む identity JSON である。
python3 pfsense-api-enroll-autoadd-Abraxas-Labs.py
または
cd lab
./run.sh
Loopback SSH 127.0.0.1:19111。Compose プロジェクト pfsense-api-enroll-autoadd。CONTROL: RejectPolicy は未知のホストで失敗する。INJECT: 公式サンプルの AutoAddPolicy、connect、登録スクリプトの exec_command。stdout は witness を含む identity JSON。ライブの Plus コントローラーはなし。Witness PFSENSE-API-ENROLL-AUTOADD-WITNESS。実行後にスタックは破棄される。
SUCCESS PFSENSE-API-ENROLL-AUTOADD autoadd=yes reject-control=yes identity-json=yes PFSENSE-API-ENROLL-AUTOADD-WITNESS
paramiko.RejectPolicy() を使用するか、known_hosts を固定してください。接続前に load_system_host_keys()(および専用の known_hosts ファイル)を呼び出してください。公式サンプルに AutoAddPolicy() を含めないでください。「すべての pfsense デバイスが known_hosts にある場合はこの行をコメントアウトしてください」というコメントが意図されたモードです。これをデフォルトにしてください。
b4acd7ca21dbca739a530403a1f62a7440f7726fexample-add-devices.pyGNU Affero GPL v3.0。LICENSE を参照してください。ループバックラボ専用。保証なし。