diff --git a/.env b/.env new file mode 100644 index 0000000..cf32153 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +# Google OAuth 설정 +GOOGLE_ID=bot.imnya.ng@gmail.com diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cf32153 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +# Google OAuth 설정 +GOOGLE_ID=bot.imnya.ng@gmail.com diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32a975c..09915cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,10 @@ jobs: - name: Install dependencies run: uv sync + + - name: Set up environment variables + run: | + echo "GOOGLE_ID=bot.imnya.ng@gmail.com" > .env - name: Start application and run proxy test run: | @@ -37,7 +41,12 @@ jobs: sleep 5 # Test proxy functionality - curl -x http://localhost:11080 http://example.com + sudo cp ~/.mitmproxy/mitmproxy-ca-cert.pem /usr/local/share/ca-certificates/mitmproxy-ca-cert.crt + sudo update-ca-certificates + + mkdir data + echo https://github.com > ./data/target.dump + curl -k -x https://localhost:11080 "https://github.com/login/oauth/authorize?client_id=Ov23lixietSCQOHxPvcr&redirect_uri=http://localhost:8787&scope=read:user+user:email&response_type=code&code_challenge=abc123&code_challenge_method=S256" # Clean up kill $APP_PID diff --git a/addon/GoogleLoginHint.py b/addon/GoogleLoginHint.py new file mode 100644 index 0000000..6d80669 --- /dev/null +++ b/addon/GoogleLoginHint.py @@ -0,0 +1,71 @@ +import lib.target as target +from lib.report import save_report +import os +from urllib.parse import urlparse, parse_qs, urlencode, urlunparse +from dotenv import load_dotenv + +# .env 파일 로드 +load_dotenv(override=True) + +class GoogleLoginHint: + def __init__(self): + self.google_id = os.getenv('GOOGLE_ID', '') + if not self.google_id: + print("⚠️ Warning: GOOGLE_ID not found in .env file") + + async def request(self, flow): + """Google OAuth 요청을 가로채서 login_hint를 추가하거나 수정""" + req = flow.request + method = req.method + url = req.pretty_url + + # Google OAuth 인증 URL인지 확인 + if self._is_google_oauth_url(url): + print(f"🔍 Google OAuth URL detected: {url}") + + # URL 파싱 + parsed_url = urlparse(url) + query_params = parse_qs(parsed_url.query) + + # login_hint 추가 또는 수정 + if self.google_id: + query_params['login_hint'] = [self.google_id] + print(f"✅ Added/Updated login_hint: {self.google_id}") + + # 새로운 쿼리 스트링 생성 + new_query = urlencode(query_params, doseq=True) + + # 새로운 URL 생성 + new_url = urlunparse(( + parsed_url.scheme, + parsed_url.netloc, + parsed_url.path, + parsed_url.params, + new_query, + parsed_url.fragment + )) + + # 요청 URL 수정 + flow.request.pretty_url = new_url + print(f"🔄 Modified URL: {new_url}") + + + def _is_google_oauth_url(self, url): + """Google OAuth URL인지 확인""" + google_oauth_domains = [ + 'accounts.google.com', + 'oauth2.googleapis.com' + ] + + parsed_url = urlparse(url) + domain = parsed_url.netloc.lower() + + # Google OAuth 도메인 확인 + for google_domain in google_oauth_domains: + if google_domain in domain: + # OAuth 관련 경로 확인 + path = parsed_url.path.lower() + if any(oauth_path in path for oauth_path in ['/oauth2', '/auth', '/login']): + return True + + return False \ No newline at end of file diff --git a/addon/init.py b/addon/init.py index 78e616a..c54a7fc 100644 --- a/addon/init.py +++ b/addon/init.py @@ -6,6 +6,11 @@ from csrf_check import CsrfChecker from nonce_check import NonceChecker from redirect_uri_check import RedirectBypassChecker from access_token import AccessTokenScanner +from GoogleLoginHint import GoogleLoginHint +import os +from dotenv import load_dotenv + +load_dotenv(override=True) class PKCEAddon: def __init__(self): @@ -87,4 +92,19 @@ class RedirectBypassAddon: except Exception as e: print(f"[ERROR] RedirectBypass Addon failed: {e}") -addons = [PKCEAddon(), ScopeAddon(), CsrfAddon(), NonceAddon(), AccessTokenAddon(), RedirectBypassAddon()] +class GoogleLoginHintAddon(): + def __init__(self) -> None: + if os.getenv('GOOGLE_ID'): + self.checker = GoogleLoginHint() + else: + self.checker = None + + async def request(self, flow: http.HTTPFlow): + if self.checker is None: + return + try: + await self.checker.request(flow) + except Exception as e: + print(f"[ERROR] GoogleLoginHint Addon failed: {e}") + +addons = [PKCEAddon(), ScopeAddon(), CsrfAddon(), NonceAddon(), AccessTokenAddon(), RedirectBypassAddon(), GoogleLoginHintAddon()]