
पालो ऑल्टो नेटवर्क्स PAN-OS में GlobalProtect पोर्टल और गेटवे में खामियों के कारण एक प्रमाणीकरण बाईपास है, जो हमलावरों को अनधिकृत VPN कनेक्शन स्थापित करने देता है, शोषण के लिए पोर्टल या गेटवे तक नेटवर्क पहुंच की आवश्यकता होती है।
यह एक्सप्लॉइट पालो ऑल्टो GlobalProtect गेटवे/पोर्टल में अप्रमाणित VPN पहुँच प्राप्त करता है, केवल सर्वर के सार्वजनिक रूप से उपलब्ध TLS प्रमाणपत्र का उपयोग करके एक प्रमाणीकरण कुकी बनाकर।
GlobalProtect एक पूर्व-प्रमाणीकरण कुकी (portal-userauthcookie) का उपयोग करता है ताकि क्लाइंट प्रमाणित हो सकें। यहाँ घातक दोष है:
सामान्य प्रवाह:
1. क्लाइंट प्रमाणित होता है (उपयोगकर्ता नाम + पासवर्ड)
2. सर्वर एक कुकी उत्पन्न करता है → इसे सर्वर की RSA सार्वजनिक कुंजी से एन्क्रिप्ट करता है
3. क्लाइंट एन्क्रिप्टेड कुकी संग्रहीत करता है
4. पुनः कनेक्शन पर, क्लाइंट कुकी भेजता है → सर्वर निजी कुंजी से डिक्रिप्ट करता है → उस पर भरोसा करता है
बग:
सर्वर केवल यह जाँचता है कि क्या कुकी अपनी निजी कुंजी से सफलतापूर्वक डिक्रिप्ट होती है।
यह सत्यापित नहीं करता कि कुकी को किसने एन्क्रिप्ट किया या क्या प्लेनटेक्स्ट सामग्री वैध है।
चूँकि RSA सार्वजनिक कुंजी सर्वर के TLS प्रमाणपत्र में एम्बेडेड है (जो किसी भी कनेक्ट होने वाले के लिए सार्वजनिक रूप से सुलभ है), कोई भी हमलावर:
यह एक पाठ्यपुस्तकीय टूटा हुआ प्रमाणीकरण दोष है — एन्क्रिप्शन का उपयोग वहाँ किया गया जहाँ डिजिटल हस्ताक्षर या HMAC की आवश्यकता थी।
flowchart TD
A["चरण 1: रॉ TCP कनेक्ट"] --> B["चरण 2: निर्मित TLS ClientHello भेजें"]
B --> C["चरण 3: ServerHello पार्स करें → DER प्रमाणपत्र निकालें"]
C --> D["चरण 4: ASN.1 चलें → RSA सार्वजनिक कुंजी निकालें"]
D --> E["चरण 5: PKCS#1 v1.5 एन्क्रिप्टेड कुकी बनाएँ"]
E --> F["चरण 6: /ssl-vpn/login.esp पर POST करें"]
F --> G{"सर्वर कुकी डिक्रिप्ट करता है"}
G -->|"वैध प्लेनटेक्स्ट"| H["प्रमाणीकरण बाइपास — VPN पहुँच प्रदान"]
G -->|"अमान्य"| I["अस्वीकृत"]
रॉ क्यों? हमें सर्वर का प्रमाणपत्र DER (रॉ बाइनरी) प्रारूप में चाहिए। Python का
sslमॉड्यूल आंतरिक रूप से पूरा TLS हैंडशेक पूरा करता है और रॉ प्रमाणपत्र बाइट्स उसी तरह प्रदर्शित नहीं करता। रॉ TCP कनेक्शन करके और हाथ से बनाया गया ClientHello भेजकर, हम सर्वर की प्रतिक्रिया को बाइट स्तर पर इंटरसेप्ट कर सकते हैं।
TLS रिकॉर्ड इस तरह दिखता है:
┌──────────────────────────────────────────────────┐
│ TLS रिकॉर्ड हेडर (5 बाइट्स) │
│ ┌──────┬──────────┬────────────┐ │
│ │ प्रकार│ संस्करण │ लंबाई │ │
│ │ 0x16 │ 0x03 01 │ 2 बाइट्स │ │
│ │(हैंडशेक)│(TLS 1.0)│ │ │
│ └──────┴──────────┴────────────┘ │
│ │
│ हैंडशेक संदेश │
│ ┌──────┬────────────┬─────────────────────────┐ │
│ │ प्रकार│ लंबाई │ बॉडी │ │
│ │ 0x01 │ 3 बाइट्स │ (ClientHello) │ │
│ │(CHlo)│ │ │ │
│ └──────┴────────────┴─────────────────────────┘ │
└──────────────────────────────────────────────────┘
ClientHello बॉडी में शामिल है:
| क्षेत्र | मान | उद्देश्य |
|---|---|---|
| संस्करण | 0x03 0x03 (TLS 1.2) | सर्वर को बताएँ हम TLS 1.2 बोलते हैं |
| रैंडम | 4-बाइट टाइमस्टैम्प + 28 रैंडम बाइट्स | हैंडशेक के लिए नॉन्स |
| सत्र ID | 0x00 (खाली) | कोई सत्र पुनरारंभ नहीं |
| सिफर सूट | 9 सूट जिनमें TLS_RSA_WITH_AES_128_CBC_SHA शामिल | मुख्य: हम RSA-केवल सिफर शामिल करते हैं ताकि सर्वर को अपने RSA प्रमाणपत्र का उपयोग करने के लिए मजबूर किया जा सके |
| संपीड़न | 0x00 (कोई नहीं) | आवश्यक |
शामिल एक्सटेंशन:
| एक्सटेंशन | ID | उद्देश्य |
|---|---|---|
| SNI (सर्वर नाम संकेत) | 0x0000 | सर्वर को बताएँ हम किस होस्टनाम से जुड़ रहे हैं |
| हस्ताक्षर एल्गोरिदम | 0x000D | बताएँ हम किन हस्ताक्षर एल्गोरिदम का समर्थन करते हैं |
| समर्थित समूह | 0x000A | हम किन EC वक्रों का समर्थन करते हैं (P-256, P-384, P-521) |
| EC बिंदु प्रारूप | 0x000B | असम्पीडित EC बिंदु |
[!NOTE] सिफर सूट्स में जानबूझकर RSA कुंजी विनिमय सिफर (
0x002F=TLS_RSA_WITH_AES_128_CBC_SHA) शामिल हैं। यह सर्वर को ECDSA प्रमाणपत्र के बजाय अपना RSA प्रमाणपत्र भेजने के लिए प्रेरित करता है — जो महत्वपूर्ण है क्योंकि एक्सप्लॉइट केवल RSA के साथ काम करता है।
ClientHello भेजने के बाद, सर्वर कई TLS रिकॉर्ड वापस भेजता है:
सर्वर प्रतिक्रिया:
┌─────────────────┐
│ ServerHello │ (हैंडशेक प्रकार 2)
├─────────────────┤
│ प्रमाणपत्र │ (हैंडशेक प्रकार 11) ← हमें यह चाहिए
├─────────────────┤
│ ServerKeyExchange│ (हैंडशेक प्रकार 12, वैकल्पिक)
├─────────────────┤
│ ServerHelloDone │ (हैंडशेक प्रकार 14) ← रुकने का संकेत
└─────────────────┘
चरण 1 — TLS रिकॉर्ड हेडर हटाएँ:
प्रत्येक TLS रिकॉर्ड में 5-बाइट हेडर होता है: [प्रकार(1)] [संस्करण(2)] [लंबाई(2)]। कोड सभी रिकॉर्ड्स को स्कैन करता है, और type == 22 (हैंडशेक) वाले रिकॉर्ड के पेलोड को जोड़ता है:
while i + 5 <= len(data):
t = data[i] # सामग्री प्रकार
rl = (data[i + 3] << 8) | data[i + 4] # रिकॉर्ड लंबाई
if t == 22: # हैंडशेक
hs.extend(data[i + 5: i + 5 + rl]) # पेलोड लें
i += 5 + rl # अगला रिकॉर्ड
चरण 2 — प्रमाणपत्र संदेश (प्रकार 11) खोजें:
हैंडशेक स्ट्रीम के अंदर, प्रत्येक संदेश का 4-बाइट हेडर होता है: [प्रकार(1)] [लंबाई(3)]। हम type == 11 की खोज करते हैं:
while j + 4 <= len(hs):
ht = hs[j] # हैंडशेक प्रकार
hl = (hs[j+1] << 16) | (hs[j+2] << 8) | hs[j+3] # 3-बाइट लंबाई
if ht == 11: # प्रमाणपत्र!
# अंदर प्रमाणपत्र सूची पार्स करें
चरण 3 — अलग-अलग DER प्रमाणपत्र निकालें:
प्रमाणपत्र संदेश में प्रमाणपत्रों की एक सूची होती है, प्रत्येक के पहले 3-बाइट लंबाई होती है:
प्रमाणपत्र संदेश बॉडी:
┌───────────────────────────────────┐
│ कुल प्रमाणपत्रों की लंबाई (3 बाइट्स) │
├───────────────────────────────────┤
│ प्रमाणपत्र 1 की लंबाई (3 बाइट्स) │
│ प्रमाणपत्र 1 का DER डेटा (चर) │
├───────────────────────────────────┤
│ प्रमाणपत्र 2 की लंबाई (3 बाइट्स) │
│ प्रमाणपत्र 2 का DER डेटा (चर) │
├───────────────────────────────────┤
│ ... │
└───────────────────────────────────┘
हमारे परीक्षण रन में, हमें 3 प्रमाणपत्र मिले (लीफ प्रमाणपत्र, मध्यवर्ती CA, रूट CA)।
यह फ़ंक्शन ServerHelloDone (हैंडशेक प्रकार 14) को स्कैन करता है, जो हमें बताता है कि सर्वर भेजना समाप्त कर चुका है और हम पढ़ना बंद कर सकते हैं।
X.509 प्रमाणपत्र DER (विशिष्ट एन्कोडिंग नियम) में एन्कोडेड होते हैं, जो ASN.1 (अमूर्त सिंटैक्स नोटेशन वन) पर आधारित एक बाइनरी प्रारूप है।
DER में प्रत्येक तत्व है:
┌─────┬────────┬───────────────────┐
│ टैग │ लंबाई │ मान (पेलोड) │
│ 1B │ 1-5B │ चर │
└─────┴────────┴───────────────────┘
लंबाई एन्कोडिंग:
0x80 है: लंबाई सीधे वह बाइट है (लघु रूप)0x80 है: निचले 7 बिट = लंबाई को एन्कोड करने वाले निम्नलिखित बाइट्स की संख्या (दीर्घ रूप)# उदाहरण: लंबाई बाइट = 0x82 → 2 और बाइट्स अनुसरण करती हैं
# अगले 2 बाइट्स: 0x06 0x4F → लंबाई = 0x064F = 1615 बाइट्स