테스트 완료

This commit is contained in:
gyuu04 2025-06-11 15:11:50 +09:00
commit 57625307a7

View file

@ -17,16 +17,16 @@ class RedirectBypassChecker:
""" 우회 페이로드 목록 """
self.bypass_payloads = [
BypassPayload(
name="\@",
name=r"@",
mutate_func=self._mutate_pattern1,
description="브라우저는 \@를 사용자정보(@user)로 해석하지만, 일부 서버는 도메인 전체로 해석 → evil.com으로 우회"
description=r"@ 기호를 이용한 호스트 우회 공격: evil.com@target.com"
),
""" 테스트 후 우회 패턴 추가 예정 """
]
self.session = None
""" 우회 URL 생성 목록 """
# 1. \@
# 1. @
def _mutate_pattern1(self, original: str) -> str:
parsed = urlparse(original)
mutated = f"https://evil.com@{parsed.netloc}{parsed.path}"
@ -75,8 +75,22 @@ class RedirectBypassChecker:
if not redirect_host or not base_host:
return False
# 동일 도메인 또는 하위 도메인인지 확인
return (redirect_host == base_host or redirect_host.endswith(f".{base_host}"))
if "@" in redirect_uri:
if redirect_host != base_host:
print(f"[ALERT] 우회 공격 탐지: {redirect_host} != {base_host}")
return False
at_parts = redirect_uri.split('@')
if len(at_parts) > 1:
before_at = at_parts[0]
if '//' in before_at:
potential_domain = before_at.split('//')[-1]
if '.' in potential_domain and potential_domain != base_host:
print(f"[CRITICAL] @ 우회 공격: {potential_domain}@{base_host}")
return False
is_valid = (redirect_host == base_host or redirect_host.endswith(f".{base_host}"))
return is_valid
except Exception as e:
print(f"[ERROR] 도메인 검증 실패: {e}")
@ -118,9 +132,10 @@ class RedirectBypassChecker:
""" 개별 우회 패턴 테스트 """
async def _test_bypass_pattern(self, original_url, query, parsed_url, original_redirect_uri, payload, headers):
print(f"[SCAN] 우회 패턴 테스트: {payload.name}")
# 우회 URL 생성
bypassed_uri = payload.mutate(original_redirect_uri)
print(f"[DEBUG] 테스트 중인 우회 패턴 ({payload.name}): {bypassed_uri}")
# 새로운 쿼리 파라미터 구성
modified_query = query.copy()
@ -128,48 +143,45 @@ class RedirectBypassChecker:
new_query_string = urlencode(modified_query, doseq=True)
test_url = urlunparse(parsed_url._replace(query=new_query_string))
print(f"[DEBUG] 테스트 URL: {test_url}")
# 요청 전송
response = await self._send_request(test_url, headers)
# 응답 분석
await self._analyze_response(
original_url, test_url, bypassed_uri, response, payload
)
await self._analyze_response(original_url, test_url, bypassed_uri, response, payload)
""" 응답 분석 및 취약점 판단 """
async def _analyze_response(self, original_url, test_url, bypassed_uri, response, payload):
status = response['status']
location = response['location']
print(f"[DEBUG] 응답 상태: {status}, Location: {location}")
# 리다이렉트 응답이 아니면 스킵
if status not in [301, 302, 303, 307, 308]:
print(f"[DEBUG] 리다이렉트가 아닌 응답: {status}")
return
# Location 헤더에서 code 추출
auth_code = self._extract_code_from_location(location)
if auth_code and not self._is_baseline_valid(bypassed_uri, original_url):
# 취약점 발견!
await self._report_vulnerability(
original_url, test_url, bypassed_uri, location, auth_code, payload
)
elif auth_code:
print(f"[DEBUG] 인가 코드 발급되었지만 유효한 도메인: {bypassed_uri}")
else:
print(f"[DEBUG] 인가 코드 발급되지 않음")
# 취약점 발견 시에만 로그
print(f"[🎯 VULNERABILITY] {payload.name} 우회 성공!")
await self._report_vulnerability(original_url, test_url, bypassed_uri, location, auth_code, payload)
""" 취약점 보고서 생성 """
async def _report_vulnerability(self, original_url, test_url, bypassed_uri, location, auth_code, payload):
# payload가 문자열인지 객체인지 확인
if hasattr(payload, 'name'):
pattern_name = payload.name
pattern_description = payload.description
else:
pattern_name = str(payload)
pattern_description = "Unknown bypass pattern"
description = (
f"Redirect URI 우회 취약점 발견!\n\n"
f"-- 상세 정보 --:\n"
f"• 우회 패턴: {payload.name}\n"
f"• 설명: {payload.description}\n"
f"• 우회 패턴: {pattern_name}\n"
f"• 설명: {pattern_description}\n"
f"• 원본 URL: {original_url}\n"
f"• 우회된 redirect_uri: {bypassed_uri}\n"
f"• 테스트 URL: {test_url}\n"
@ -179,10 +191,12 @@ class RedirectBypassChecker:
report_data = [{
"target": target.load(),
"status": "CRITICAL",
"title": "Redirect URI Bypass Vulnerability",
"description": description
"description": description,
"uri": test_url # uri 필드 추가
}]
save_report(report_data)
print(f"[🎯 CRITICAL] Redirect URI 우회 취약점 발견 및 보고 완료!")
print(f"[INFO] 패턴: {payload.name}, 우회 URI: {bypassed_uri}")
print(f"[INFO] 패턴: {pattern_name}, 우회 URI: {bypassed_uri}")