OAuth를 통한 계정 탈취
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
기본 정보
OAuth는 여러 버전이 있으며, 기초적인 내용은 OAuth 2.0 documentation에서 확인할 수 있습니다. 이 논의는 주로 널리 사용되는 OAuth 2.0 authorization code grant type에 초점을 맞추며, 이는 한 애플리케이션이 다른 애플리케이션(authorization server)에서 사용자의 계정에 접근하거나 행위를 수행할 수 있게 하는 authorization framework를 제공합니다.
가상의 웹사이트인 _https://example.com_을 예로 들어보면, 이 사이트는 모든 소셜미디어 게시물(비공개 포함)을 보여주기 위해 설계되어 있고, 이를 위해 OAuth 2.0을 사용합니다. _https://example.com_은 당신의 소셜미디어 게시물에 접근 권한을 요청할 것입니다. 그 결과, 권한 동의 화면이 _https://socialmedia.com_에서 나타나며, 여기에는 요청되는 권한과 요청을 하는 개발자가 표시됩니다. 당신이 승인하면, _https://example.com_은 당신을 대신해 게시물에 접근할 수 있는 권한을 얻게 됩니다.
OAuth 2.0 프레임워크 내에서 다음 구성 요소들을 이해하는 것이 중요합니다:
- resource owner: 당신, 즉 사용자/엔티티로서 소셜미디어 계정 게시물 같은 리소스에 대한 접근을 승인합니다.
- resource server:
access token을 획득한 후 애플리케이션의 인증된 요청을 처리하는 서버, 예: https://socialmedia.com. - client application:
resource owner로부터 권한을 얻으려는 애플리케이션, 예: https://example.com. - authorization server:
resource owner의 인증과 권한 부여가 완료된 후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:
resource owner를 대신해 클라이언트 애플리케이션이 API 요청에 사용하는 토큰. - refresh_token: 사용자를 다시 프롬프트하지 않고 새로운
access_token을 얻을 수 있게 하는 토큰.
흐름
실제 OAuth 흐름은 다음과 같이 진행됩니다:
- 당신은 https://example.com에 접속하여 “Integrate with Social Media” 버튼을 클릭합니다.
- 사이트는 https://socialmedia.com으로 요청을 보내 https://example.com의 애플리케이션이 당신의 게시물에 접근할 수 있도록 권한을 요청합니다. 요청은 다음과 같은 구조입니다:
https://socialmedia.com/auth
?response_type=code
&client_id=example_clientId
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=readPosts
&state=randomString123
- 그런 다음 동의 페이지가 표시됩니다.
- 승인하면 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을 사용해 소셜 미디어에 API 호출을 하여 접근하기 위해 종료됩니다
취약점
Open redirect_uri
Per RFC 6749 §3.1.2, authorization server는 브라우저를 사전 등록된, 정확한 redirect URIs로만 리디렉트해야 합니다. 여기의 취약점은 공격자가 피해자를 악성 authorization URL로 유도해 IdP가 피해자의 code (및 state)를 공격자 엔드포인트로 그대로 전달하게 만들고, 공격자는 이를 교환하여 토큰을 수집하게 할 수 있습니다.
일반적인 공격 흐름:
https://idp.example/auth?...&redirect_uri=https://attacker.tld/callback을 만들어 피해자에게 보냅니다.- 피해자가 인증하고 스코프를 승인합니다.
- IdP가
attacker.tld/callback?code=<victim-code>&state=...로 리디렉트하면 공격자는 요청을 기록하고 즉시code를 교환합니다.
검사해야 할 일반적인 검증 버그:
- No validation – any absolute URL is accepted, resulting in instant
codetheft. - 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/user-content 엔드포인트로 지정하면 chained redirects, Referer headers, 또는 injected JavaScript를 통해 leaks the code. - Directory constraints without normalization –
/oauth/*같은 패턴은/oauth/../anything으로 우회될 수 있습니다. - Wildcard subdomains –
*.example.com을 허용하면 어떤 takeover (dangling DNS, S3 bucket, etc.)라도 즉시 유효한 콜백을 제공합니다. - Non-HTTPS callbacks –
http://URI를 허용하면 네트워크 공격자(Wi-Fi, corporate proxy 등)가 전송 중에code를 탈취할 기회를 갖게 됩니다.
또한 보조적인 redirect 형태의 파라미터들(client_uri, policy_uri, tos_uri, initiate_login_uri 등)과 OpenID discovery 문서(/.well-known/openid-configuration)도 검토하여 동일한 검증 버그를 물려받을 수 있는 추가 엔드포인트가 있는지 확인하세요.
XSS in redirect implementation
As mentioned in this bug bounty report https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html it might be possible that the redirect URL is being reflected in the response of the server after the user authenticates, being vulnerable to XSS. Possible payload to test:
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
CSRF - state parameter의 부적절한 처리
state 파라미터는 Authorization Code 흐름의 CSRF 토큰입니다: 클라이언트는 브라우저 인스턴스별로 암호학적으로 랜덤한 값을 생성하고, 해당 브라우저만 읽을 수 있는 곳(쿠키, 로컬 스토리지 등)에 저장한 뒤 인가 요청에 포함시키고, 동일한 값을 반환하지 않는 응답은 거부해야 합니다. 값이 고정되어 있거나 예측 가능하거나 선택적이거나 사용자 세션과 연동되지 않으면, 공격자는 자신의 OAuth 흐름을 완료한 뒤 최종 ?code= 요청을 캡처(전송하지 않음)하고 나중에 피해자 브라우저로 해당 요청을 재생하게 하여 피해자 계정이 공격자의 identity provider 프로필에 연결되도록 할 수 있습니다.
재생(replay) 패턴은 항상 동일합니다:
- 공격자는 자신의 계정으로 IdP에 인증한 후
code(및state)가 포함된 마지막 리다이렉트를 가로챕니다. - 그 요청을 버리고 URL을 보관한 뒤, 링크/iframe/자동 제출 폼 같은 CSRF 프리미티브를 이용해 피해자 브라우저가 그 URL을 로드하도록 강제합니다.
- 클라이언트가
state를 강제하지 않으면, 애플리케이션은 공격자의 인가 결과를 수용하여 공격자를 피해자 앱 계정에 로그인시킵니다.
테스트 중 state 처리에 대한 실무 체크리스트:
state가 전혀 없음 – 파라미터가 전혀 나타나지 않으면 전체 로그인 흐름이 CSRF에 취약합니다.state가 필수 아님 – 초기 요청에서 제거해 보십시오; IdP가 여전히 코드를 발급하고 클라이언트가 이를 수용하면 방어는 옵트인 방식입니다.- 반환된
state가 검증되지 않음 – 응답에서 값을 변조해 보십시오(Burp, MITM proxy). 불일치 값을 수용하면 저장된 토큰을 비교하지 않는 것입니다. - 예측 가능하거나 순수 데이터 기반의
state– 많은 앱이 리디렉트 경로나 JSON 블랍을 randomness 없이state에 넣어 공격자가 유효 값을 추측하고 흐름을 재생할 수 있게 합니다. 데이터를 인코딩하기 전에 항상 강력한 엔트로피를 prepend/append 하세요. state고정(state fixation) – 앱이 사용자가state값을 제공하도록 허용(e.g., 조작된 authorization URL을 통해)하고 흐름 전반에 걸쳐 재사용하면, 공격자는 알려진 값을 고정해 여러 피해자에게 재사용할 수 있습니다.
PKCE는 authorization code를 code verifier에 바인딩함으로써(especially for public clients) state를 보완할 수 있지만, 웹 클라이언트는 여전히 cross-user CSRF/계정 링크 버그를 방지하기 위해 state를 추적해야 합니다.
Pre Account Takeover
- 계정 생성 시 이메일 검증이 없는 경우: 공격자는 피해자 이메일로 미리 계정을 생성할 수 있습니다. 피해자가 이후 서드파티 서비스를 통해 로그인하면, 애플리케이션이 의도치 않게 이 서드파티 계정을 공격자가 미리 만든 계정에 연결하여 무단 접근이 발생할 수 있습니다.
- 느슨한 OAuth 이메일 검증 악용: 공격자는 이메일을 검증하지 않는 OAuth 서비스를 악용해 계정을 등록한 뒤 계정 이메일을 피해자의 것으로 변경할 수 있습니다. 이 방법도 위 시나리오와 유사하게 무단 계정 접근 위험을 초래합니다.
Disclosure of Secrets
client_id는 의도적으로 공개되지만, client_secret은 절대 최종 사용자에게 회수 가능해서는 안 됩니다. Authorization Code 배포에서 비밀을 mobile APKs, desktop clients, 또는 single-page apps에 내장하면 해당 패키지를 다운로드할 수 있는 누구에게나 자격증명을 넘겨주는 셈입니다. 공개 클라이언트를 항상 다음과 같이 검사하세요:
- APK/IPA, 데스크탑 인스톨러 또는 Electron 앱을 언패킹하고
client_secret, Base64 블랍(디코드 시 JSON), 또는 하드코딩된 OAuth 엔드포인트를 grep하세요. - 번들된 설정 파일(plist, JSON, XML)이나 디컴파일된 문자열을 검토해 클라이언트 자격증명을 찾으세요.
공격자가 시크릿을 추출하면, 약한 redirect_uri, 로그 등으로 피해자의 인가 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 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 leaking Code + State
클라이언트가 code and state를 가지고 있고, 사용자가 다른 페이지로 이동할 때 그 값들이 reflected inside the Referer header에 남는다면 취약합니다.
Access Token Stored in Browser History
Authorization Code grant의 핵심 보증은 access tokens가 절대 resource owner’s browser에 도달하지 않는다는 것입니다. 구현체가 토큰을 client-side로 leak하면, 어떤 사소한 버그(XSS, Referer leak, proxy logging)도 즉시 계정 탈취로 이어집니다. 항상 다음을 확인하세요:
- Tokens in URLs –
access_token이 쿼리/프래그먼트에 나타나면 브라우저 기록, 서버 로그, 분석, 그리고 제3자에게 전송되는 Referer headers에 남습니다. - Tokens transiting untrusted middleboxes – 토큰을 HTTP로 반환하거나 디버깅/회사 프록시를 통해 전송하면 네트워크 관찰자가 이를 직접 캡처할 수 있습니다.
- Tokens stored in JavaScript state – React/Vue stores, 전역 변수, 또는 직렬화된 JSON blob은 origin의 모든 스크립트(여기에는 XSS 페이로드나 악성 확장도 포함)에 토큰을 노출합니다.
- Tokens persisted in Web Storage –
localStorage/sessionStorage는 공유 기기에서 로그아웃 후에도 토큰을 장기간 보관하며 스크립트로 접근 가능합니다.
이러한 발견 중 어느 것 하나라도 보통 별것 아닌 “low” 버그(예: CSP bypass 또는 DOM XSS)를 전체 API 탈취로 격상시킵니다. 공격자는 단순히 leaked bearer token을 읽어 재사용할 수 있기 때문입니다.
Everlasting Authorization Code
Authorization codes는 **짧은 수명(short-lived), 일회용(single-use), 및 재사용 방지(replay-aware)**여야 합니다. 흐름을 평가할 때 code를 캡처하고:
- Test the lifetime – RFC 6749는 분 단위를 권장합니다(시간 단위 아님). 5–10분 후에 코드를 redeem해 보세요. 여전히 작동하면 해당 코드의 노출 창이 과도합니다.
- Test sequential reuse – 동일한
code를 두 번 전송하세요. 두 번째 요청에서 또 다른 토큰이 발급되면 공격자는 세션을 무기한 복제할 수 있습니다. - Test concurrent redemption/race conditions – 토큰 요청을 병렬로 두 번 발사하세요(Burp intruder, turbo intruder). 취약한 발급자는 둘 다 허용하기도 합니다.
- Observe replay handling – 재사용 시도는 단순히 실패해야 하는 것에 그치지 않고, 해당 코드에서 이미 발급된 토큰들을 취소(revoke)해야 합니다. 그렇지 않으면 재사용이 감지되어도 공격자의 첫 토큰은 활성 상태로 남습니다.
replay-friendly한 code를 어떤 redirect_uri나 로깅 버그와 결합하면, 피해자가 정상 로그인 절차를 마친 이후에도 지속적인 계정 접근이 가능합니다.
Authorization/Refresh Token not bound to client
만약 authorization code를 얻어 다른 client와 함께 사용할 수 있다면 다른 계정들을 탈취할 수 있습니다.
Happy Paths, XSS, Iframes & Post Messages to leak code & state values
AWS Cognito
In this bug bounty report: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/에서 볼 수 있듯, token을 AWS Cognito가 사용자에게 반환할 때 사용자 데이터를 덮어쓸 수 있을 만큼의 권한을 가질 수 있습니다. 따라서 다른 사용자 이메일로 사용자의 이메일을 변경할 수 있다면, 다른 계정들을 탈취할 수 있을지도 모릅니다.
# 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
As mentioned in this writeup, OAuth flows that expect to receive the token (and not a code) could be vulnerable if they not check that the token belongs to the app.
이는 mentioned in this writeup에 따르면, token(코드가 아닌)을 받도록 설계된 OAuth 흐름은 해당 token이 특정 app에 귀속되는지 확인하지 않으면 취약할 수 있기 때문입니다.
This is because an attacker could create an application supporting OAuth and login with Facebook (for example) in his own application. Then, once a victim logins with Facebook in the attackers application, the attacker could get the OAuth token of the user given to his application, and use it to login in the victim OAuth application using the victims user token.
이는 attacker가 자신의 애플리케이션에 OAuth를 지원하고 Facebook으로 로그인하는 application(예: Facebook)을 만들 수 있기 때문입니다. 그러면 victim이 attacker의 application에서 Facebook으로 로그인하면, attacker는 그 application에 발급된 사용자의 OAuth token을 얻어 victim OAuth application에서 victim의 user token으로 로그인하는 데 사용할 수 있습니다.
Caution
Therefore, if the attacker manages to get the user access his own OAuth application, he will be able to take over the victims account in applications that are expecting a token and aren’t checking if the token was granted to their app ID.
Caution
따라서 attacker가 사용자가 자신의 OAuth application에 접근하도록 만들면, token을 기대하고 그 token이 자신의 app ID에 부여된 것인지 확인하지 않는 application에서 victim의 계정을 탈취할 수 있습니다.
Two links & cookie
According to this writeup, it was possible to make a victim open a page with a returnUrl pointing to the attackers host. This info would be stored in a cookie (RU) and in a later step the prompt will ask the user if he wants to give access to that attackers host.
this writeup에 따르면, victim이 returnUrl이 attacker 호스트를 가리키는 페이지를 열도록 만들 수 있었습니다. 이 정보는 **쿠키(RU)**에 저장되고 이후 단계에서 prompt가 사용자에게 해당 attacker 호스트에 접근 권한을 부여할지 묻게 됩니다.
To bypass this prompt, it was possible to open a tab to initiate the Oauth flow that would set this RU cookie using the returnUrl, close the tab before the prompt is shown, and open a new tab without that value. Then, the prompt won’t inform about the attackers host, but the cookie would be set to it, so the token will be sent to the attackers host in the redirection.
이 prompt를 우회하려면, returnUrl을 사용해 RU 쿠키를 설정하는 Oauth flow를 시작하는 탭을 열고 prompt가 뜨기 전에 해당 탭을 닫은 뒤 그 값이 없는 새 탭을 열 수 있었습니다. 그러면 prompt는 attacker 호스트에 대해 알리지 않지만, 쿠키에는 attacker가 설정되어 있어 리디렉션 시 token이 attacker 호스트로 전송됩니다.
Prompt Interaction Bypass
As explained in this video, some OAuth implementations allows to indicate the prompt GET parameter as None (&prompt=none) to prevent users being asked to confirm the given access in a prompt in the web if they are already logged in the platform.
이 this video에 설명된 바와 같이, 일부 OAuth 구현은 prompt GET 파라미터를 None(&prompt=none)으로 지정하여 사용자가 이미 플랫폼에 로그인되어 있는 경우 웹에서 접근 권한 확인을 묻는 prompt를 표시하지 않도록 할 수 있습니다.
response_mode
As explained in this video, it might be possible to indicate the parameter response_mode to indicate where do you want the code to be provided in the final URL:
이 explained in this video에서 설명한 것처럼, 최종 URL에서 code가 어디에 제공될지 지정하기 위해 response_mode 파라미터를 설정할 수 있습니다:
response_mode=query-> The code is provided inside a GET parameter:?code=2397rf3gu93f
코드는 GET 파라미터 안에 제공됩니다:?code=2397rf3gu93fresponse_mode=fragment-> The code is provided inside the URL fragment parameter#code=2397rf3gu93f
코드는 URL fragment 파라미터 안에 제공됩니다:#code=2397rf3gu93fresponse_mode=form_post-> The code is provided inside a POST form with an input calledcodeand the value
코드는code라는 이름의 input을 가진 POST form 내부에서 제공됩니다.response_mode=web_message-> The code is send in a post message:window.opener.postMessage({"code": "asdasdasd...
코드는 post message로 전송됩니다:window.opener.postMessage({"code": "asdasdasd...
Clickjacking OAuth consent dialogs
OAuth consent/login dialogs are ideal clickjacking targets: if they can be framed, an attacker can overlay custom graphics, hide the real buttons, and trick users into approving dangerous scopes or linking accounts. Build PoCs that:
OAuth consent/login dialog는 clickjacking의 이상적인 대상입니다. 프레임으로 감쌀 수 있다면 attacker는 커스텀 그래픽으로 오버레이하고 실제 버튼을 숨겨 사용자를 속여 위험한 scope를 승인하거나 계정을 연결하게 할 수 있습니다. 다음과 같은 PoC를 만드세요:
- Load the IdP authorization URL inside an
<iframe sandbox="allow-forms allow-scripts allow-same-origin">.
IdP authorization URL을<iframe sandbox="allow-forms allow-scripts allow-same-origin">안에 로드합니다. - Use absolute positioning/opacity tricks to align fake buttons with the hidden Allow/Approve controls.
절대 위치/투명도 트릭을 사용해 가짜 버튼을 숨겨진 Allow/Approve 컨트롤과 정렬합니다. - Optionally pre-fill parameters (scopes, redirect URI) so the stolen approval immediately benefits the attacker.
선택적으로 파라미터(scopes, redirect URI)를 미리 채워 도난된 승인으로 attacker가 즉시 이득을 보게 합니다.
During testing verify that IdP pages emit either X-Frame-Options: DENY/SAMEORIGIN or a restrictive Content-Security-Policy: frame-ancestors 'none'. If neither is present, demonstrate the risk with tooling like NCC Group’s clickjacking PoC generator and record how easily a victim authorizes the attacker’s app. For additional payload ideas see Clickjacking.
테스트 시 IdP 페이지가 X-Frame-Options: DENY/SAMEORIGIN 또는 제한적인 Content-Security-Policy: frame-ancestors 'none'를 내보내는지 확인하세요. 둘 다 없으면 NCC Group’s clickjacking PoC generator 같은 도구로 위험을 시연하고 피해자가 attacker의 앱을 얼마나 쉽게 승인하는지 기록하세요. 추가 페이로드 아이디어는 Clickjacking를 참조하세요.
OAuth ROPC flow - 2 FA bypass
According to this blog post, this is an OAuth flow that allows to login in OAuth via username and password. If during this simple flow a token with access to all the actions the user can perform is returned then it’s possible to bypass 2FA using that token.
이 this blog post에 따르면, 이것은 username과 password로 OAuth에 로그인할 수 있게 하는 OAuth 흐름입니다. 이 간단한 흐름에서 사용자가 수행할 수 있는 모든 동작에 접근 가능한 token이 반환된다면, 해당 token을 사용해 2FA를 우회할 수 있습니다.
ATO on web page redirecting based on open redirect to referrer
This blogpost comments how it was possible to abuse an open redirect to the value from the referrer to abuse OAuth to ATO. The attack was:
이 blogpost는 referrer의 값에 대한 open redirect를 악용해 OAuth로 ATO를 유발하는 방법을 설명합니다. 공격 흐름은 다음과 같았습니다:
- Victim access the attackers web page
Victim이 attacker의 웹페이지에 접근합니다. - The victim opens the malicious link and an opener starts the Google OAuth flow with
response_type=id_token,code&prompt=noneas additional parameters using as referrer the attackers website.
Victim이 악성 링크를 열면 opener가 추가 파라미터로response_type=id_token,code&prompt=none을 사용해 Google OAuth 흐름을 시작하고 referrer로 attacker의 웹사이트를 사용합니다. - In the opener, after the provider authorizes the victim, it sends them back to the value of the
redirect_uriparameter (victim web) with 30X code which still keeps the attackers website in the referer.
Opener에서 provider가 victim을 승인한 후,redirect_uri파라미터의 값(즉 victim 웹)으로 30X 코드와 함께 리디렉션합니다. 이때 referer에는 여전히 attacker의 웹사이트가 남아 있습니다. - The victim website trigger the open redirect based on the referrer redirecting the victim user to the attackers website, as the
respose_typewasid_token,code, the code will be sent back to the attacker in the fragment of the URL allowing him to tacke over the account of the user via Google in the victims site.
Victim 웹사이트는 referrer를 기반으로 open redirect를 트리거하여 victim을 attacker 웹사이트로 리디렉트합니다.respose_type이id_token,code였기 때문에 code는 URL의 fragment로 attacker에게 전송되어 attacker가 victim 사이트에서 Google을 통해 사용자 계정을 탈취할 수 있게 됩니다.
SSRFs parameters
Check this research For further details of this technique.
Check this research. 이 기법의 자세한 내용은 위 연구를 참조하세요.
Dynamic Client Registration in OAuth serves as a less obvious but critical vector for security vulnerabilities, specifically for Server-Side Request Forgery (SSRF) attacks. This endpoint allows OAuth servers to receive details about client applications, including sensitive URLs that could be exploited.
OAuth의 Dynamic Client Registration은 덜 명백하지만 중요한 보안 취약점 벡터로, 특히 Server-Side Request Forgery (SSRF) 공격에 관련됩니다. 이 엔드포인트는 OAuth 서버가 클라이언트 애플리케이션에 대한 세부 정보를 수신할 수 있게 하며, 여기에는 악용될 수 있는 민감한 URL들이 포함될 수 있습니다.
Key Points:
-
Dynamic Client Registration is often mapped to
/registerand accepts details likeclient_name,client_secret,redirect_uris, and URLs for logos or JSON Web Key Sets (JWKs) via POST requests.
Dynamic Client Registration은 종종/register에 매핑되며client_name,client_secret,redirect_uris, 로고 또는 JSON Web Key Sets(JWKs)용 URL과 같은 세부 정보를 POST 요청으로 수락합니다. -
This feature adheres to specifications laid out in RFC7591 and OpenID Connect Registration 1.0, which include parameters potentially vulnerable to SSRF.
이 기능은 RFC7591 및 OpenID Connect Registration 1.0에 명시된 사양을 따르며, 이들 사양에는 SSRF에 취약할 수 있는 파라미터들이 포함됩니다. -
The registration process can inadvertently expose servers to SSRF in several ways:
등록 과정은 여러 방식으로 서버를 SSRF에 노출시킬 수 있습니다: -
logo_uri: A URL for the client application’s logo that might be fetched by the server, triggering SSRF or leading to XSS if the URL is mishandled.logo_uri: 서버가 가져올 수 있는 클라이언트 애플리케이션 로고의 URL로, 서버가 이를 요청하면 SSRF를 유발하거나 URL을 잘못 처리할 경우 XSS로 이어질 수 있습니다. -
jwks_uri: A URL to the client’s JWK document, which if maliciously crafted, can cause the server to make outbound requests to an attacker-controlled server.jwks_uri: 클라이언트의 JWK 문서 URL로, 악의적으로 조작된 경우 서버가 공격자가 제어하는 서버로 아웃바운드 요청을 하게 만들 수 있습니다. -
sector_identifier_uri: References a JSON array ofredirect_uris, which the server might fetch, creating an SSRF opportunity.sector_identifier_uri:redirect_uris의 JSON 배열을 참조하는 URL로, 서버가 이를 가져올 경우 SSRF 기회를 만들 수 있습니다. -
request_uris: Lists allowed request URIs for the client, which can be exploited if the server fetches these URIs at the start of the authorization process.request_uris: 클라이언트의 허용 request URI 목록으로, 서버가 인가 과정 시작 시 이들을 가져오면 악용될 수 있습니다.
Exploitation Strategy:
- SSRF can be triggered by registering a new client with malicious URLs in parameters like
logo_uri,jwks_uri, orsector_identifier_uri.
악용 전략:logo_uri,jwks_uri,sector_identifier_uri같은 파라미터에 악의적인 URL을 넣어 새 클라이언트를 등록하면 SSRF를 유발할 수 있습니다. - While direct exploitation via
request_urismay be mitigated by whitelist controls, supplying a pre-registered, attacker-controlledrequest_urican facilitate SSRF during the authorization phase.request_uris를 통한 직접적인 악용은 화이트리스트 제어로 완화될 수 있지만, 미리 등록된 attacker가 제어하는request_uri를 제공하면 인가 단계에서 SSRF를 용이하게 할 수 있습니다.
OAuth providers Race Conditions
If the platform you are testing is an OAuth provider read this to test for possible Race Conditions.
테스트 중인 플랫폼이 OAuth provider라면 read this to test for possible Race Conditions를 참고하세요.
Mutable Claims Attack
In OAuth, the sub field uniquely identifies a user, but its format varies by Authorization Server. To standardize user identification, some clients use emails or user handles. However, this is risky because:
- Some Authorization Servers do not ensure that these properties (like email) remain immutable.
- In certain implementations—such as “Login with Microsoft”—the client relies on the email field, which is user-controlled by the user in Entra ID and not verified.
- An attacker can exploit this by creating their own Azure AD organization (e.g., doyensectestorg) and using it to perform a Microsoft login.
- Even though the Object ID (stored in sub) is immutable and secure, the reliance on a mutable email field can enable an account takeover (for example, hijacking an account like victim@gmail.com).
OAuth에서 sub 필드는 사용자를 고유하게 식별하지만 그 형식은 Authorization Server마다 다릅니다. 일부 클라이언트는 사용자 식별을 표준화하기 위해 이메일이나 사용자 핸들을 사용합니다. 그러나 이는 위험합니다:
- 일부 Authorization Server는 이러한 속성(예: email)이 불변임을 보장하지 않습니다.
- 특정 구현(예: “Login with Microsoft”)에서는 클라이언트가 email 필드에 의존하는데, 이 필드는 Entra ID에서 사용자가 제어하며 검증되지 않습니다.
- 공격자는 자신만의 Azure AD 조직(예: doyensectestorg)을 만들어 이를 통해 Microsoft 로그인을 수행함으로써 이를 악용할 수 있습니다.
- Object ID(sub에 저장됨)는 불변이고 안전하지만, 변경 가능한 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.
Client Confusion Attack에서는 OAuth Implicit Flow를 사용하는 애플리케이션이 최종 access token이 자신들의 Client ID를 위해 생성되었는지 검증하지 못합니다. attacker는 Google의 OAuth Implicit Flow를 사용하는 공개 웹사이트를 만들어 수천 명의 사용자를 속여 로그인하게 하고 attacker 사이트용으로 발급된 access token을 수집할 수 있습니다. 만약 이 사용자들이 token의 Client ID를 검증하지 않는 다른 취약한 웹사이트의 계정을 가지고 있다면, attacker는 수집한 토큰을 재사용해 피해자를 사칭하고 계정을 탈취할 수 있습니다.
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.
Authorization Code Grant 타입은 사용자 데이터를 전송하기 위해 안전한 서버간 통신을 포함합니다. 그러나 Authorization Server가 Access Token Request의 scope 파라미터(종종 RFC에 정의되지 않은)를 암묵적으로 신뢰하면, 악의적 애플리케이션이 더 높은 scope를 요청해 authorization code의 권한을 상승시킬 수 있습니다. Access Token이 생성된 후 Resource Server는 이를 검증해야 합니다: JWT 토큰의 경우 JWT 서명을 확인하고 client_id, scope 등의 데이터를 추출해야 하며, 무작위 문자열 토큰의 경우 서버는 Authorization Server에 쿼리해 토큰의 세부 정보를 조회해야 합니다.
Redirect Scheme Hijacking
In mobile OAuth implementations, apps use custom URI schemes to receive redirects with Authorization Codes. However, because multiple apps can register the same scheme on a device, the assumption that only the legitimate client controls the redirect URI is violated. On Android, for instance, an Intent URI like com.example.app:// oauth is caught based on the scheme and optional filters defined in an app’s intent-filter. Since Android’s intent resolution can be broad—especially if only the scheme is specified—an attacker can register a malicious app with a carefully crafted intent filter to hijack the authorization code. This can enable an account takeover either through user interaction (when multiple apps are eligible to handle the intent) or via bypass techniques that exploit overly specific filters, as detailed by Ostorlab’s assessment flowchart.
모바일 OAuth 구현에서는 Authorization Code를 받기 위해 custom URI schemes를 사용합니다. 그러나 하나의 디바이스에서 동일한 스킴을 여러 앱이 등록할 수 있기 때문에 정당한 클라이언트만이 리디렉션 URI를 제어한다는 가정이 깨집니다. 예를 들어 Android에서는 com.example.app:// 같은 Intent URI가 스킴과 앱의 intent-filter에 정의된 선택적 필터를 기반으로 처리됩니다. Android의 intent 해석은 특히 스킴만 지정된 경우 광범위할 수 있으므로, attacker는 정교하게 설계한 intent filter로 악성 앱을 등록해 authorization code를 가로챌 수 있습니다. 이는 (여러 앱이 intent를 처리할 수 있는 경우) 사용자 상호작용을 통해 또는 Ostorlab의 평가 플로차트에 설명된 과도하게 특정한 필터를 악용하는 우회 기법을 통해 **계정 탈취(ATO)**를 가능하게 합니다.
References
- 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
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks

