
pfSense Plus MIM API toolkit b4acd7ca - High - Remote - Privilege leftover - GET export-key private keys
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-export-key-get
Class: Privilege leftover Reach: Remote
pfSense Plus MIM API (Netgate) pin b4acd7ca - public OpenAPI + generated Python client for the Nexus Multi-instance Management controller.
GET /system/certauth/{refid}/export-key is documented as "Download the CA certificate signing key". GET /system/certificates/{refid}/export-key is "Download the certificate's private key". GET /system/certificates/{refid}/export-p12 is a unified PKCS12 file without password protection. Docs map GET under /system to mim_system_read / mim_read_system. mim_view is documented as no confidential information. The spec has no securitySchemes and no per-op security. Generated _get_kwargs is method plus a quoted URL. Authorization is never added there.
This is not php, not shell, and not firmware POST. A stolen JWT from the G9 sample TLS skip or a G6 fleet token is enough to call these GETs. Whether a read-shaped MIM JWT is enough on Plus is the leftover. I did not run Plus. Plus RBAC was not executed.
| ID | no CVE yet |
| Class | Privilege leftover |
| Reach | Remote (authenticated HTTP to the Nexus controller; lab is the public client contract) |
| 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 if a read-shaped MIM JWT can call these GETs |
| Product | Netgate/pfsense-api (pfSense Plus Nexus MIM controller OpenAPI + generated client) |
| Affected | pin b4acd7ca21dbca739a530403a1f62a7440f7726f (2026-05-25). OpenAPI 3.0.3 title pfSense API version 1.0. Plus 25.11+. Not the CE REST package. |
| Auth | Documented Nexus JWT (POST /login, Bearer). Lab is the public OpenAPI plus generated _get_kwargs contract. Plus RBAC was not executed. |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:19141 only. No Plus image. |
I pinned github.com/Netgate/pfsense-api b4acd7ca21dbca739a530403a1f62a7440f7726f. Not master after that day. Not the third-party CE package jaredhendrickson/pfsense-api.
Series hub: pfsense-api-nexus-mim. This pack is Part 4.
Docs map GET under /system to mim_system_read / mim_read_system. mim_view is documented as no confidential information. The leftover is private-key export on GET, with PKCS12 documented as unprotected, and generated _get_kwargs that never adds Authorization.
| Method | Path | Privilege |
|---|---|---|
GET DownloadCAKey | /system/certauth/{refid}/export-key | Recon (lab-proven on mock): application/octet-stream body containing the witness PEM. Inferred on Plus: CA certificate signing key if RBAC allows the GET. |
GET GetCertKey | /system/certificates/{refid}/export-key | Recon (lab-proven on mock): witness PEM. Inferred on Plus: leaf private key. |
GET GetCertP12 | /system/certificates/{refid}/export-p12 | Recon (lab-proven on mock): same witness body. Inferred on Plus: cert plus key as PKCS12 without password protection (OpenAPI summary). |
Generated _get_kwargs | all three ops | Recon (lab-proven): kwargs are method plus quoted url only. No headers, no Authorization, no Bearer. |
Client (no token) | all three ops | Recon (lab-proven): three mock hits with has_authorization=false and witness body (client-no-auth=yes, witness-body=yes). |
AuthenticatedClient | all three ops | Recon (lab-proven): three mock hits with Authorization: Bearer mock-token (authed-bearer=3). Bearer is a wrapper property, not _get_kwargs. |
| Stolen JWT from G9 MITM, or G6 fleet token | same three GETs, plus /api/device/pfsense/{device_id}/api if the fleet leftover holds | Recon (inferred, chained): pull CA / leaf keys for the controller and every enrolled instance the token can name. |
| Use stolen CA / leaf keys | TLS, VPN, IPsec, WebGUI certs | Integrity (inferred, not labbed): mint descendant certs as the CA; impersonate the Nexus TLS name; decrypt tunnels that use those certs. Not Unix root by itself. |
| Related list/detail GETs | /system/certauth?withprivkey=true, cert prv / private_key fields | Recon (spec, not this lab): bulk dump of the same secrets. Not exercised here. |
Availability: none required.
Lab-proven vs inferred: OpenAPI three GET paths, PKCS12 "without password protection" phrase, _get_kwargs with no Authorization, Client three no-auth hits with witness PEM, AuthenticatedClient three Bearer hits, and pin clone of pfapi_openapi.yml are lab-proven. Plus mim_system_read / mim_view 200s, minting descendant certs, and fleet-wide key pull are inferred. Plus RBAC was not executed.
Requires (inferred, Plus not executed): Nexus login plus a group allowed GET under /system/certauth and /system/certificates. Not admins / mim_superuser if the leftover is real. Not Diagnostics: Command. Network path to the controller :8443 (or the device proxy) with a JWT.
| Surface | Why |
|---|---|
| Plus RBAC | Not executed. This pack does not claim a live Plus 200 for mim_system_read or mim_view. |
POST /diag/cmd/php, POST /diag/cmd/shell, GET/POST /diag/cmd/download /upload /diag/editfile | Intended Diagnostics: Command. Superuser-shaped. Not this leftover. |
POST /system/firmware | Intended system modify / superuser. |
GET .../export-ca and GET .../export-cert | Public cert PEM. Intended. |
POST .../export-key and POST .../export-p12 with a password as superuser | Intended wrap. GUI system_certmanager.php already exports keys that way. |
| Unauthenticated Internet-to-8443 | Login still issues a JWT. Missing OpenAPI securitySchemes is a generator footgun, not a proven unauth server. |
| CE package jaredhendrickson/pfsense-api / pfrest.org | Different product. |
Generated library verify_ssl default | True. Official examples set False. That is G9, not this GET. |
I pinned b4acd7ca21dbca739a530403a1f62a7440f7726f after the pfSense CE 2.9.0-DEVELOPMENT wave and read pfapi_openapi.yml cert manager routes. Three GETs export private keys. GetCertP12 summary says without password protection. DownloadCAKey is GET-only with no wrap. Generated modules type client: AuthenticatedClient | Client and _get_kwargs never sets Authorization.
Skip list: CE REST package; POST php/shell as intended admin (CVE-2025-69691 disputed); CE WebGUI leftovers already mailed (QinQ, OpenVPN wizard, CARP VHID, limiter number, IPsec login banner). Those sinks also appear in this schema. I did not re-file them.