abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-export-key-get
类别: 权限残留 可达性: 远程
pfSense Plus MIM API(Netgate)固定于 b4acd7ca —— 面向 Nexus 多实例管理控制器的公开 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。授权从未在那里添加。
这不是 php,不是 shell,也不是固件 POST。从 G9 示例 TLS 跳过 或 G6 集群令牌 窃取的 JWT 就足以调用这些 GET。在 Plus 上,一个读形态的 MIM JWT 是否足够,就是那个残留问题。我没有运行 Plus。Plus RBAC 未被执行。
| ID | 暂无 CVE |
| 类别 | 权限残留 |
| 可达性 | 远程(对 Nexus 控制器进行已认证 HTTP 访问;实验环境为公开客户端契约) |
| CWE | CWE-200、CWE-862 |
| CVSS | 高危: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。本包为第 4 部分。
文档将 /system 下的 GET 映射到 mim_system_read / mim_read_system。mim_view 被文档描述为不包含机密信息。残留问题在于 GET 上的私钥导出,PKCS12 被文档描述为无保护,以及生成的 _get_kwargs 从不添加 Authorization。
| 方法 | 路径 | 权限 |
|---|---|---|
GET DownloadCAKey | /system/certauth/{refid}/export-key | 侦察(在 mock 上经实验验证): application/octet-stream 响应体包含见证 PEM。在 Plus 上推断: 若 RBAC 允许该 GET,则为 CA 证书签名密钥。 |
GET GetCertKey | /system/certificates/{refid}/export-key | 侦察(在 mock 上经实验验证): 见证 PEM。在 Plus 上推断: 叶子私钥。 |
GET GetCertP12 | /system/certificates/{refid}/export-p12 | 侦察(在 mock 上经实验验证): 相同的见证响应体。在 Plus 上推断: 证书加密钥以 PKCS12 格式导出,无密码保护(OpenAPI 摘要)。 |
生成的 _get_kwargs | 全部三个操作 | 侦察(经实验验证): kwargs 仅为 method 加带引号的 url。没有 headers,没有 Authorization,没有 Bearer。 |
Client(无令牌) | 全部三个操作 | 侦察(经实验验证): 三次 mock 命中,has_authorization=false 且返回见证响应体(client-no-auth=yes、witness-body=yes)。 |
AuthenticatedClient | 全部三个操作 | 侦察(经实验验证): 三次 mock 命中,带有 Authorization: Bearer mock-token(authed-bearer=3)。Bearer 是包装器属性,不是 _get_kwargs。 |
| 从 G9 MITM 窃取的 JWT,或 G6 车队令牌 | 同样的三个 GET,外加 /api/device/pfsense/{device_id}/api(如果车队残留持有该令牌) | 侦察(推断,链式): 为控制器以及令牌能命名的每个已注册实例拉取 CA / 叶子密钥。 |
| 使用窃取的 CA / 叶子密钥 | TLS、VPN、IPsec、WebGUI 证书 | 完整性(推断,未实验验证): 以 CA 身份签发后代证书;冒充 Nexus TLS 名称;解密使用这些证书的隧道。本身并非 Unix root。 |
| 相关的列表/详情 GET | /system/certauth?withprivkey=true、证书 prv / private_key 字段 | 侦察(规范,非本实验): 批量转储相同机密。此处未实际测试。 |
可用性: 无需任何条件。
经实验验证 vs 推断: OpenAPI 三个 GET 路径、PKCS12“无密码保护”措辞、_get_kwargs 不含 Authorization、Client 三次无认证命中并返回见证 PEM、AuthenticatedClient 三次 Bearer 命中,以及 pfapi_openapi.yml 的 pin 克隆均经实验验证。Plus mim_system_read / mim_view 返回 200、签发后代证书、以及全车队密钥拉取均为推断。Plus RBAC 未执行。
所需条件(推断,Plus 未执行): Nexus 登录,加上一个被允许在 /system/certauth 和 /system/certificates 下执行 GET 的组。如果残留属实,则不是 admins / mim_superuser。不是 Diagnostics: Command。到控制器 :8443(或设备代理)的网络路径,并持有 JWT。
| 攻击面 | 原因 |
|---|---|
| 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 | 预期为系统修改 / 超级用户。 |
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 证书管理器路由。三个 GET 导出私钥。GetCertP12 摘要说无密码保护。DownloadCAKey 仅支持 GET,无包装。生成的模块将类型标注为 client: AuthenticatedClient | Client,且 _get_kwargs 从不设置 Authorization。
跳过列表:CE REST 包;以预期管理员身份 POST php/shell(CVE-2025-69691 有争议);CE WebGUI 遗留问题已邮件发送(QinQ、OpenVPN 向导、CARP VHID、limiter 编号、IPsec 登录横幅)。这些接收点也出现在此 schema 中。我没有重新提交它们。
错误方向:将省略的 OAS 安全机制视为未认证的 php/shell(登录仍会返回 JWT;mock 并非无 JWT 返回 200 的服务器证明)。将超级用户导出视为遗留问题(GUI system_certmanager.php 已经导出密钥)。我在公开契约处停止,因为 Plus 是付费且闭源的。
表演:反向 shell。预言机是见证 PEM 加上 plus-rbac=not-executed。
从 pin 引入,与 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 上具有相同的结构。pin 上的 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
或
cd lab
./run.sh
仅回环:127.0.0.1:19141。Compose 项目 pfsense-api-export-key-get。见证 PFSENSE-API-EXPORT-KEY-GET-WITNESS。当 git 可以访问 github.com/Netgate/pfsense-api 时,run.sh 会在固定版本处稀疏检出 pfapi_openapi.yml。Plus 不会被下载。
最后一行:
SUCCESS PFSENSE-API-EXPORT-KEY-GET openapi=3/3 client-no-auth=yes witness-body=yes authed-bearer=3 plus-rbac=not-executed pin=clone PFSENSE-API-EXPORT-KEY-GET-WITNESS
将私钥导出视为仅限超级用户操作。绝不在只读角色上返回 PEM 或 PKCS12。对 PKCS12 进行密码保护。在 OpenAPI 中将这些操作标记为使用生成器无法将其类型化为裸 Client 的安全方案。