
pfSense Plus MIM API toolkit b4acd7ca - 높음 - 원격 - 권한 잔존 - GET export-key 개인 키
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 - 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도, shell도, 펌웨어 POST도 아니다. G9 샘플 TLS skip 또는 G6 플릿 토큰에서 탈취한 JWT만으로도 이 GET들을 호출하기에 충분하다. 읽기 형태의 MIM JWT가 Plus에서 충분한지는 남은 문제다. 나는 Plus를 실행하지 않았다. Plus RBAC는 실행되지 않았다.
| ID | 아직 CVE 없음 |
| Class | Privilege leftover |
| Reach | Remote (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들을 호출할 수 있는 경우) |
| Product | Netgate/pfsense-api (pfSense Plus Nexus MIM 컨트롤러 OpenAPI + 생성된 클라이언트) |
| Affected | pin b4acd7ca21dbca739a530403a1f62a7440f7726f (2026-05-25). OpenAPI 3.0.3 title pfSense API version 1.0. Plus 25.11+. CE REST 패키지가 아님. |
| Auth | 문서화된 Nexus JWT (POST /login, Bearer). 랩은 공개 OpenAPI와 생성된 _get_kwargs 계약. Plus RBAC는 실행되지 않았다. |
| License | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:19141 전용. Plus 이미지 없음. |
나는 github.com/Netgate/pfsense-api b4acd7ca21dbca739a530403a1f62a7440f7726f를 pin했다. 그날 이후의 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을 절대 추가하지 않는다.
| 메서드 | 경로 | 권한 |
|---|---|---|
GET DownloadCAKey | /system/certauth/{refid}/export-key | 정찰(모의 환경에서 실증됨): witness PEM을 포함하는 application/octet-stream 본문. Plus에서 추정: RBAC가 GET을 허용할 경우 CA 인증서 서명 키. |
GET GetCertKey | /system/certificates/{refid}/export-key | 정찰(모의 환경에서 실증됨): witness PEM. Plus에서 추정: 리프 개인 키. |
GET GetCertP12 | /system/certificates/{refid}/export-p12 | 정찰(모의 환경에서 실증됨): 동일한 witness 본문. Plus에서 추정: 인증서와 키를 비밀번호 보호 없이 PKCS12로 제공(OpenAPI 요약). |
생성된 _get_kwargs | 세 작업 모두 | 정찰(실증됨): kwargs는 method와 따옴표로 묶인 url뿐. headers 없음, Authorization 없음, Bearer 없음. |
Client (토큰 없음) | 세 작업 모두 | 정찰(실증됨): has_authorization=false와 witness 본문으로 모의 환경에서 세 번 적중(client-no-auth=yes, witness-body=yes). |
AuthenticatedClient | 세 작업 모두 | 정찰(실증됨): 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 "비밀번호 보호 없이" 문구, Authorization이 없는 _get_kwargs, witness PEM과 함께 Client의 세 무인증 적중, AuthenticatedClient의 세 Bearer 적중, 그리고 pfapi_openapi.yml의 핀 클론은 실험실에서 실증됨. Plus mim_system_read / mim_view 200 응답, 하위 인증서 발급, 플릿 전체 키 추출은 추정. 또한 Plus RBAC는 실행되지 않음.
요구 사항(추정, Plus 미실행): Nexus 로그인과 /system/certauth 및 /system/certificates 아래에서 GET이 허용된 그룹. 잔여물이 실제라면 admins / mim_superuser가 아님. Diagnostics: Command도 아님. JWT를 사용하여 컨트롤러 :8443(또는 디바이스 프록시)로의 네트워크 경로.
| 표면 | 이유 |
|---|---|
| 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을 설정하지 않는다.
Skip list: CE REST 패키지; 의도된 관리자로서의 POST php/shell (CVE-2025-69691 disputed); CE WebGUI 잔여물은 이미 메일로 보고됨 (QinQ, OpenVPN wizard, CARP VHID, limiter number, IPsec login banner). 해당 sink들은 이 스키마에도 나타난다. 나는 그것들을 다시 신고하지 않았다.
잘못된 접근: 누락된 OAS security를 unauth php/shell로 취급한 것 (login은 여전히 JWT를 반환하며, mock은 JWT 없이 200을 반환하는 서버 증명이 아니다). superuser export를 잔여물로 취급한 것 (GUI system_certmanager.php는 이미 키를 export한다). Plus는 유료이며 closed-source이므로 나는 public contract에서 멈췄다.
Theatre: a reverse shell. The oracle is a witness PEM plus plus-rbac=not-executed.
pin에서 vendoring되었으며, 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
또는