abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-export-key-get
クラス: 権限の取り残し 到達範囲: リモート
pfSense Plus MIM API (Netgate) のピン b4acd7ca — Nexus Multi-instance Management コントローラー向けの公開 OpenAPI と生成された Python クライアント。
GET /system/certauth/{refid}/export-key は「CA 証明書署名鍵をダウンロード」と文書化されている。GET /system/certificates/{refid}/export-key は「証明書の秘密鍵をダウンロード」。GET /system/certificates/{refid}/export-p12 はパスワード保護なしの統合 PKCS12 ファイルである。ドキュメントは /system 配下の GET を mim_system_read / mim_read_system にマッピングしている。mim_view は機密情報なしと文書化されている。仕様には securitySchemes も操作ごとのセキュリティもない。生成された _get_kwargs はメソッドと引用符付き URL だけである。Authorization はそこに決して追加されない。
これは php でもシェルでもファームウェア POST でもない。G9 サンプル TLS スキップや G6 フリートトークンから盗まれた JWT があれば、これらの GET を呼び出すには十分である。読み取り形の MIM JWT が Plus 上で十分かどうかが、この取り残しである。私は Plus を実行していない。Plus RBAC は実行されていない。
| ID | CVE はまだなし |
| クラス | 権限の取り残し |
| 到達範囲 | リモート (Nexus コントローラーへの認証済み HTTP。ラボは公開クライアント契約) |
| CWE | CWE-200, CWE-862 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N (読み取り形の MIM JWT がこれらの GET を呼び出せる場合) |
| 製品 | Netgate/pfsense-api (pfSense Plus Nexus MIM コントローラー OpenAPI + 生成クライアント) |
| 影響範囲 | ピン b4acd7ca21dbca739a530403a1f62a7440f7726f (2026-05-25)。OpenAPI 3.0.3 タイトル pfSense API バージョン 1.0。Plus 25.11+。CE REST パッケージではない。 |
| 認証 | 文書化された Nexus JWT (POST /login、Bearer)。ラボは公開 OpenAPI と生成された _get_kwargs 契約。Plus RBAC は実行されていない。 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:19141 のみ。Plus イメージなし。 |
私は github.com/Netgate/pfsense-api b4acd7ca21dbca739a530403a1f62a7440f7726f をピンした。その日以降の master ではない。サードパーティの CE パッケージ jaredhendrickson/pfsense-api でもない。
シリーズハブ: pfsense-api-nexus-mim。このパックは Part 4 である。
ドキュメントは /system 配下の GET を mim_system_read / mim_read_system にマッピングしている。mim_view は機密情報なしと文書化されている。取り残しは GET での秘密鍵エクスポートであり、PKCS12 は保護なしと文書化され、生成された _get_kwargs は Authorization を決して追加しない。
| Method | Path | Privilege |
|---|---|---|
GET DownloadCAKey | /system/certauth/{refid}/export-key | Recon(モック上でラボ実証済み): witness PEM を含む application/octet-stream ボディ。Plus での推測: RBAC が GET を許可する場合の CA 証明書署名鍵。 |
GET GetCertKey | /system/certificates/{refid}/export-key | Recon(モック上でラボ実証済み): witness PEM。Plus での推測: リーフ秘密鍵。 |
GET GetCertP12 | /system/certificates/{refid}/export-p12 | Recon(モック上でラボ実証済み): 同一の witness ボディ。Plus での推測: 証明書と鍵を PKCS12 として パスワード保護なし で出力(OpenAPI の概要より)。 |
生成された _get_kwargs | 上記 3 オペレーションすべて | Recon(ラボ実証済み): kwargs は method と引用符付きの url のみ。headers なし、Authorization なし、Bearer なし。 |
Client(トークンなし) | 上記 3 オペレーションすべて | Recon(ラボ実証済み): has_authorization=false と witness ボディ(client-no-auth=yes、witness-body=yes)でモックが 3 回ヒット。 |
AuthenticatedClient | 上記 3 オペレーションすべて | Recon(ラボ実証済み): Authorization: Bearer mock-token(authed-bearer=3)でモックが 3 回ヒット。Bearer はラッパープロパティであり、_get_kwargs ではない。 |
| G9 MITM から窃取した JWT、または G6 フリートトークン | 同じ 3 つの GET、加えてフリートの残存物が保持していれば /api/device/pfsense/{device_id}/api | Recon(推測、連鎖): コントローラおよびトークンが指定できるすべての登録済みインスタンスの CA / リーフ鍵を取得。 |
| 窃取した CA / リーフ鍵の使用 | TLS、VPN、IPsec、WebGUI 証明書 | Integrity(推測、ラボ未実施): CA として子孫証明書を発行。Nexus TLS 名をなりすまし。それらの証明書を使用するトンネルを復号。それ自体では Unix root ではない。 |
| 関連する一覧/詳細 GET | /system/certauth?withprivkey=true、証明書の prv / private_key フィールド | Recon(仕様、本ラボではない): 同じシークレットの一括ダンプ。ここでは検証していない。 |
Availability: 不要。
ラボ実証済み vs 推測: OpenAPI の 3 つの GET パス、PKCS12 の「パスワード保護なし」という文言、Authorization を含まない _get_kwargs、witness PEM を伴う Client の 3 回の no-auth ヒット、AuthenticatedClient の 3 回の Bearer ヒット、および pfapi_openapi.yml のピンクローンはラボ実証済み。Plus の mim_system_read / mim_view の 200、子孫証明書の発行、フリート全体の鍵取得は推測。Plus の RBAC は未実行。
Requires(推測、Plus 未実行): Nexus ログイン、および /system/certauth と /system/certificates 配下の GET を許可されたグループ。残存物が本物であれば admins / mim_superuser ではない。Diagnostics: Command ではない。JWT を用いたコントローラ :8443(またはデバイスプロキシ)へのネットワーク経路。
| Surface | Why |
|---|---|
| Plus RBAC | 未実行。 本パックは mim_system_read または mim_view に対するライブ Plus 200 を主張しない。 |
POST /diag/cmd/php、POST /diag/cmd/shell、GET/POST /diag/cmd/download /upload /diag/editfile | 意図された Diagnostics: Command。スーパーユーザー相当。本残存物ではない。 |
POST /system/firmware | 意図された system modify / スーパーユーザー。 |
GET .../export-ca および GET .../export-cert | 公開証明書 PEM。意図されたもの。 |
スーパーユーザーとしてパスワード付きの POST .../export-key および POST .../export-p12 | 意図されたラップ。GUI system_certmanager.php は既にその方法で鍵をエクスポートしている。 |
| 未認証のインターネットから 8443 へ | ログインは依然として JWT を発行する。OpenAPI の securitySchemes 欠落はジェネレータの落とし穴であり、実証された未認証サーバーではない。 |
| CE パッケージ jaredhendrickson/pfsense-api / pfrest.org | 別製品。 |
生成ライブラリの verify_ssl デフォルト | True。公式例は False を設定。それは G9 であり、本 GET ではない。 |
pfSense CE 2.9.0-DEVELOPMENT の波の後に b4acd7ca21dbca739a530403a1f62a7440f7726f をピン留めし、pfapi_openapi.yml の証明書マネージャルートを読んだ。3 つの GET が秘密鍵をエクスポートする。GetCertP12 の概要にはパスワード保護なしと書かれている。DownloadCAKey はラップなしの GET のみ。生成モジュールは client: AuthenticatedClient | Client と型付けし、_get_kwargs は決して Authorization を設定しない。
スキップリスト: CE REST パッケージ; 意図された管理者としての POST php/shell (CVE-2025-69691 は係争中); CE WebGUI の残存物は既にメール済み (QinQ、OpenVPN ウィザード、CARP VHID、リミッター番号、IPsec ログインバナー)。これらのシンクはこのスキーマにも現れる。私はそれらを再申請しなかった。
誤った方向: 省略された OAS セキュリティを未認証の php/shell として扱うこと (ログインは依然として JWT を返す; モックは JWT なしのサーバー 200 の証明ではない)。スーパーユーザーエクスポートを残存物として扱うこと (GUI system_certmanager.php は既に鍵をエクスポートする)。Plus は有償かつクローズドソースであるため、私は公開コントラクトで止めた。
茶番: リバースシェル。オラクルは witness PEM と plus-rbac=not-executed である。
ピンからベンダリングされ、download_ca_key.py、get_cert_key.py、get_cert_p12.py と同一:
def download_ca_key_get_kwargs(refid: str) -> dict[str, Any]:
_kwargs: dict[str, Any] = {
"method": "get",
"url": "/system/certauth/{refid}/export-key".format(
refid=quote(str(refid), safe=""),
),
}
return _kwargs
GetCertKey と GetCertP12 は /system/certificates/{refid}/export-key と .../export-p12 で同じ形をしています。ピン上の OpenAPI:
DownloadCAKey: "CA 証明書署名鍵をダウンロードする"GetCertKey: "証明書の秘密鍵をダウンロードする"GetCertP12: "証明書と鍵をパスワード保護なしの統合 PKCS12 ファイルとしてダウンロードする"AuthenticatedClient.get_httpx_client は httpx クライアントに Authorization: Bearer {token} を設定します。_get_kwargs は設定しません。
python3 pfsense-api-export-key-get-Abraxas-Labs.py
または