From 7d378fa91fc79005d372322a3e76502c73f735c3 Mon Sep 17 00:00:00 2001 From: gyuu04 Date: Thu, 17 Jul 2025 13:59:05 +0900 Subject: [PATCH] Update open_redirect_check.py --- addon/open_redirect_check.py | 39 ++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/addon/open_redirect_check.py b/addon/open_redirect_check.py index 94f20f0..f3d0c93 100644 --- a/addon/open_redirect_check.py +++ b/addon/open_redirect_check.py @@ -1058,7 +1058,7 @@ class OpenRedirectChecker: self.session = None """ 우회된 URL에 GET 요청을 보내고, 서버 응답 정보 반환 """ - async def _send_request(self, url, headers=None): + async def _send_request(self, url, headers=None, record_to_limiter=True): try: session = await self._get_session() # 세션 준비 request_headers = headers or {} # 요청 헤더 설정 - headers가 주어지지 않았다면 빈 딕셔너리 사용 @@ -1072,10 +1072,11 @@ class OpenRedirectChecker: } # 성공/실패 기록 (rate limiter용) - if response.status in [200, 301, 302, 303, 307, 308]: - redirect_limiter.record_success() - else: - redirect_limiter.record_failure(f"HTTP {response.status}") + if record_to_limiter: + if response.status in [200, 301, 302, 303, 307, 308]: + redirect_limiter.record_success() + else: + redirect_limiter.record_failure(f"HTTP {response.status}") return result @@ -1116,6 +1117,9 @@ class OpenRedirectChecker: '/oauth/callback', '/auth/callback', '/login/callback', '/oauth/redirect', '/auth/return', '/sso/callback', '/signup', '/register', + '/api/auth/v3/social/callback', # velog.io + '/social/callback', # 일반화 + '/auth/social/callback', # 변형 ] path = parsed.path.lower() @@ -1134,7 +1138,11 @@ class OpenRedirectChecker: import re # 패턴 1: 간단한 소셜 식별자 - simple_patterns = ['from=fb', 'from=facebook', 'from=google', 'from=github'] + simple_patterns = [ + 'from=fb', 'from=facebook', 'from=google', 'from=github', + 'provider=google', 'provider=facebook', + 'callback/google', 'callback/github', 'callback/facebook' # ← URL 경로 패턴 + ] has_simple = any(pattern in query_string.lower() for pattern in simple_patterns) # 패턴 2: URL 형태 @@ -1151,7 +1159,7 @@ class OpenRedirectChecker: 'next', 'return_to', 'continue', 'redirect_uri', 'redirect_url', 'destination', 'success_url', 'callback_url', 'goto', 'forward_to', 'redirectUrl', 'redirectURL', 'redirect_to', 'returnUrl', 'returnURL', - 'from', 'target', 'targetUrl', 'targetURL' # 일반적인 변형들 추가 + 'from', 'target', 'targetUrl', 'targetURL', ] has_redirect_param = any(param in query for param in client_redirect_params) @@ -1203,7 +1211,11 @@ class OpenRedirectChecker: '/oauth2/v1/authorize', '/authorize', # 일반적인 authorize 추가 '/auth/realms', # Keycloak 패턴 - '/connect/authorize' # IdentityServer 패턴 + '/connect/authorize', # IdentityServer 패턴 + '/idp/', # ← Identity Provider 패턴 + '/signin', # ← Sign-in 패턴 + '/auth/signin', # ← Auth Sign-in 패턴 + '/identity/', # ← Identity 패턴 ] path = parsed.path.lower() @@ -1263,6 +1275,9 @@ class OpenRedirectChecker: if 'state' in query: await self._test_state_parameter_manipulation(url, parsed, query) + # 일반 리다이렉트 파라미터 테스트를 위해 Rate Limiter 리셋 + redirect_limiter.reset_for_new_target() + # 2. 테스트할 파라미터들 찾기 test_params = [] @@ -1289,8 +1304,7 @@ class OpenRedirectChecker: print(f"[OAUTH] 📍 발견된 파라미터들: {test_params}") print(f"[OPEN_REDIRECT] 총 우회 패턴: {len(self.bypass_payloads)}") print("-" * 50) - - redirect_limiter.reset_for_new_target() + success_count = 0 # 3. 각 파라미터별로 모든 우회 패턴 테스트 @@ -1368,7 +1382,7 @@ class OpenRedirectChecker: test_url = urlunparse(parsed._replace(query=new_query_string)) # 요청 전송 - response = await self._send_request(test_url) + response = await self._send_request(test_url, record_to_limiter=False) # State 전용 취약점 분석 if await self._analyze_state_vulnerability(url, test_url, malicious_state, response, attack_name): @@ -1377,8 +1391,7 @@ class OpenRedirectChecker: else: print(f"[STATE_TEST] ✓ {attack_name}") - # 레이트 리미팅 - await redirect_limiter.wait_if_needed(f"state_{attack_name}") + await asyncio.sleep(1) # 1초 대기 print(f"[STATE_TEST] ✅ State 테스트 완료: {success_count}/{len(state_attacks)} 취약점 발견")