pfSense Plus MIM API toolkit b4acd7ca - उच्च - रिमोट - फ़ाइल पढ़ें - Snort नियम {file} decode-then-join
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-snort-file-join
Class: File read Reach: Remote
pfSense Plus MIM API (Netgate/pfsense-api b4acd7ca) - Netgate
GET /services/snort/rules/{name}/{file} दो path parameters लेता है, दोनों type: string, कोई pattern नहीं। विवरण: ruleset में एक फ़ाइल का निरीक्षण करें। SnortRuleFileContents.filename "फ़ाइल का path" है। जनरेट किया गया get_snort_ruleset_file._get_kwargs quote(str(...), safe="") करता है, इसलिए वायर पर ../ ..%2F हो जाता है। एक सर्वर जो URL-decode करके ruleset directory में join करता है, वह अभी भी बाहर निकल जाता है।
एक caller जो उस path को GET कर सकता है, साथ में एक fleet JWT, हर enrolled box पर MIM agent के रूप में named ruleset के बाहर की फ़ाइलें पढ़ता है। साथ ही join निष्पादित नहीं हुआ। लैब public path का decode-then-join gadget है।
यह 9 में से बचा हुआ 8 है। Map: pfsense-api-nexus-mim। वही pin leftover: fleet JWT। यह jaredhendrickson/pfsense-api नहीं है।
| ID | अभी तक कोई CVE नहीं |
| Class | File read (Snort {file} decode-then-join) |
| Reach | Remote (authenticated GET; fleet JWT हर device_id पर वही path दोबारा उपयोग करता है) |
| CWE | CWE-22 |
| CVSS | High: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N उस JWT के लिए जो Snort ruleset फ़ाइल GET कर सकता है |
| Product | Netgate/pfsense-api (pfSense Plus Nexus MIM controller OpenAPI + generated client) |
| Affected | main b4acd7ca21dbca739a530403a1f62a7440f7726f (2026-05-25, Add Snort-3 API definitions) |
| Auth | उदाहरण POST /login के बाद controller JWT भेजते हैं। OpenAPI में कोई securitySchemes नहीं है। Unauth सिद्ध नहीं है। |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1:19181। Decode-then-join gadget। साथ ही join निष्पादित नहीं हुआ। |
एक caller चाहिए जो GET /services/snort/rules/{name}/{file} कर सके। आधिकारिक उदाहरण POST /login के बाद Authorization: Bearer का उपयोग करते हैं, फिर उस token को GET /mim/devices से प्राप्त हर id के लिए base_url=.../api/device/pfsense/{device_id}/api के रूप में दोबारा चलाते हैं। जनरेट किए गए ops अभी भी AuthenticatedClient | Client टाइप करते हैं। इस GET पर CSRF काम नहीं आता।
| विधि | सिंक | विशेषाधिकार | लैब बनाम अनुमानित |
|---|---|---|---|
{file}=../../oracle/WITNESS के साथ जनरेटेड-क्लाइंट GET (वायर ..%2F..%2Foracle%2FWITNESS) | unquote(file) को डिकोड करें फिर नामित रूलसेट निर्देशिका से जोड़ें और पढ़ें | रीकॉन: HTTP 200, filename /oracle/WITNESS, बॉडी PFSENSE-API-SNORT-FILE-JOIN-WITNESS। इच्छित उस रूलसेट के अंदर एक .rules फ़ाइल है। | लैब-सिद्ध (गैजेट)। साथ ही जॉइन निष्पादित नहीं हुआ था। |
{file}=../../../etc/passwd के साथ वही GET | वही जॉइन यदि नियंत्रक इसे डिवाइस फ़ाइलसिस्टम पर मैप करता है | रीकॉन: MIM एजेंट के रूप में होस्ट फ़ाइलें पढ़ें (Plus WebGUI/PHP आमतौर पर root होता है)। लैब ने /oracle/WITNESS का उपयोग किया, लाइव /etc/passwd का नहीं। | अनुमानित (वही जॉइन, होस्ट पथ)। |
फ्लीट JWT के बाद वही GET (POST /login एक बार, /api/device/pfsense/{id}/api पर रीप्ले) | उसी अप्रतिबंधित {file} का डिवाइस प्रॉक्सी | रीकॉन: एक हेल्पडेस्क-आकार का नियंत्रक टोकन हर नामांकित बॉक्स पर फ़ाइलें पढ़ता है, न कि केवल उस पर जिसके लिए लॉगिन किया गया था। | अनुमानित (G6 अनुबंध + यह पथ)। साथ ही RBAC निष्पादित नहीं हुआ। |
{name} पर वही बचा हुआ | GET|DELETE /services/snort/rules/{name} और सहोदर address/suppress {name} भी अप्रतिबंधित स्ट्रिंग हैं | रीकॉन / अखंडता: उस रूलसेट का नाम बदलें या हटाएँ जिसका नाम एक पथ है। | स्पेक से अनुमानित। लैब ने केवल {file} चलाया। |
| उसी वायर पथ का सीमित नियंत्रण | डिकोड के बाद relative_to(ruleset_dir.resolve()) | बंद। HTTP 400, कोई विटनेस नहीं। | लैब-सिद्ध |
सौम्य {file}=local.rules | इच्छित रूलसेट रीड | बंद। 200, sid:1, कोई विटनेस नहीं, नैव और नियंत्रण दोनों। | लैब-सिद्ध |
समीपवर्ती बंद: ../ का क्लाइंट प्रतिशत-एन्कोडिंग (encoding=%2F)। डिकोड के बाद नियंत्रण जॉइन (control-confined=yes)। Plus नियंत्रक जॉइन (plus-join-not-executed)। रूलसेट foo के अंदर local.rules का इच्छित रीड। अनप्रमाणित GET (सिद्ध नहीं; उदाहरण Bearer भेजते हैं)। POST /services/snort/rules आर्काइव / प्लांटेड .so (इच्छित IDS व्यवस्थापक, यह बचा हुआ नहीं)। डायग्नोस्टिक्स PHP/शेल। फ़ाइल राइट। होस्ट शेल। यह बचा हुआ RCE नहीं है।
मैंने Netgate/pfsense-api b4acd7ca21dbca739a530403a1f62a7440f7726f को पिन किया क्योंकि 2026-10-14 को HEAD पर कोई टैग नहीं था और नवीनतम कमिट "Add Snort-3 API definitions" है। इसी तरह यह पथ अस्तित्व में है। YAML में कहीं भी शून्य pattern: कुंजियाँ हैं। {name} और {file} अप्रतिबंधित स्ट्रिंग हैं। quote(..., safe="") एक क्लाइंट एन्कोडर है, सर्वर basedir जाँच नहीं।
/services/snort/rules/{name}/{file}:
parameters:
- in: path
name: name
required: true
schema:
type: string
- in: path
name: file
required: true
schema:
type: string
get:
description: Obtain the contents of the specified file in the ruleset. This is intended for inspecting scripts provided by it.
operationId: GetSnortRulesetFile
"url": "/services/snort/rules/{name}/{file}".format(
name=quote(str(name), safe=""),
file=quote(str(file), safe=""),
),
गलत मोड़ पहले से दर्ज: क्लाइंट एन्कोडिंग को क्लोज़िंग ट्रैवर्सल मानना; pfSense Plus की रचना करना; Snort आर्काइव .so को इस अवशेष के रूप में रैंक करना; unauth GET का दावा करना। थिएटर: एक रिवर्स शेल। ओरेकल /oracle/WITNESS का गैजेट 200 और कंट्रोल 400 है।
python3 pfsense-api-snort-file-join-Abraxas-Labs.py
या
cd lab
./run.sh
केवल http://127.0.0.1:19181 को लक्षित करें। प्रोजेक्ट pfsense-api-snort-file-join को कंपोज़ करें। सार्वजनिक पथ का डिकोड-देन-जॉइन गैजेट। साथ ही जॉइन निष्पादित नहीं होता। रन के बाद स्टैक टूट जाता है।
SUCCESS PFSENSE-API-SNORT-FILE-JOIN encoding=%2F decode-then-join=yes control-confined=yes plus-join-not-executed PFSENSE-API-SNORT-FILE-JOIN-WITNESS
../../../etc/passwd का क्लाइंट एन्कोडिंग ..%2F..%2F..%2Fetc%2Fpasswd है। /services/snort/rules/foo/..%2F..%2Foracle%2FWITNESS का सामान्य GET 200 लौटाता है, फ़ाइलनाम /oracle/WITNESS, बॉडी PFSENSE-API-SNORT-FILE-JOIN-WITNESS। नियमसेट रूट के अंतर्गत हल करने वाले एक सीमित नियंत्रण के तहत वही अनुरोध 400 और कोई विटनेस नहीं लौटाता। बिनाइन local.rules foo के अंदर ही रहा।
डिकोड के बाद एक नियमसेट रूट के अंतर्गत हल करें। .. और निरपेक्ष पथों को अस्वीकार करें। पढ़ने से पहले Path.resolve() फिर relative_to(ruleset_dir.resolve()), या समकक्ष। OpenAPI में {file} (और {name}) को एक नियमसेट-सुरक्षित पैटर्न तक सीमित करें ताकि जनरेटर पथ-आकार के स्ट्रिंग भेजना बंद कर दें।