Flatt Secuurity サマーインターン応募課題 課題晒し
Flatt Secuurity サマーインターン応募課題
はじめに
こんにちは、hatomatoです。
この記事は、Flatt Security サマーインターン2024 に参加した際の応募課題です。
またこの内容は選考結果が送られてきた6月上旬に書いています。
課題晒しなので文体・内容は変えていません。(見やすいようにセクション分けはするかも)
また応募課題の作成に当たり、2023年度サマーインターン生であるかろっくさんの課題晒し記事を参考にさせていただきました。
興味がある技術 脆弱性調査
サマーインターン2025に応募される際はぜひ参考にしてみてください。
さらに2023,2024の参加記もたくさんあるのでぜひ見てください。
- 2023年
- 2024年
興味のある技術
Webセキュリティに関連する技術で、今あなたが興味を持っているものがあれば、それについて自由に説明してください。少しでもWebセキュリティとの関連性がある技術であれば、ハードウェア領域に近いものでも、ソフトウェア領域に近いものでも構いません。
// ここに回答を自由なフォーマットで記入してください。
OAuth
-
OAuthとは
- 私が現在興味を持っている技術はOAuthです。OAuthはインターネット上でユーザーが自分のアカウントパスワードを共有することなく、第三者のアプリケーションに自分の情報へのアクセスを許可するための仕組みです。
たまに見かけるOAuth2.0はRFC6749で標準化されたフレームワークです。
身近な例を挙げるとTwitterをほかのアプリと連携させるときに「〇〇(アプリ名)にアカウントへのアクセスを許可しますか?」という文字列が表示されます。これがOAuthによるアクセス権の受け渡しです。
最近Twitter側のAPI料金変更の影響によりなくなってしまいましたが、PlayStationやNintendoSwitchに存在したスクリーンショットや動画のTwitter投稿機能もOAuthを使ってAPI通信の機密性を担保していたと考えられます。
- 私が現在興味を持っている技術はOAuthです。OAuthはインターネット上でユーザーが自分のアカウントパスワードを共有することなく、第三者のアプリケーションに自分の情報へのアクセスを許可するための仕組みです。
-
なぜOAuthを使うのか
-
OAuthは主にアプリケーション間の連携を安全性を担保しながら円滑に行うために用いられます。
他のサービスと連携するだけならIDとパスワードをそのまま渡せばいいのですが、それを行うのセキュリティ上問題があります。
クライアントサービスAがリソースサービスBのIDパスワードを持っていた場合、サービスAの情報が流出したとき一緒にサービスBのIDパスワードも流出してしまいます。
またIDパスワードを教えるということはサービスAに全権限を与えることになってしまうので連携に必要のない情報を見られたり、情報を改ざんさせられたりするかもしれません。
そこでOAuthを利用することで安全に必要最低限のアクセス権を与えることができます。 -
現在、webサービスのユーザーデータの受け渡しには主にAPIが使用されます。
APIがあればリソースサーバーに対し要求を送るだけで別の媒体から様々な情報にアクセスできるようになるので非常に便利です。
しかしAPIのみでは第三者にAPIへのアクセス場所がバレた時に簡単に使用されてしまいます。
他人にAPIを使われるとそれを元に攻撃者のアプリケーションなどに連携され、自身の重要な情報を窃取される可能性があります。
そこでアクセストークンを使用します。 -
アクセストークンは要求と一緒にAPIに対して送ります。そこでリソースサーバーは要求とともに来たアクセストークンを検証し、それが正規のものであれば要求を許可し、ユーザーの情報を送ります。
ではアクセストークンはどこから発生するのでしょうか。
そこで認可サーバーを使用します。 -
認可サーバーはクライアントサービスの要求に応じてアクセストークンを生成し、発行します。
認可サーバーはユーザーにアクセストークン受け渡しの確認を取るので認可サーバーに勝手にアクセスされてアクセストークンを盗まれることはありません。
多くのwebサービスはこの認可サーバーとクライアントサービスのやり取りの部分をOAuthという仕組みを使って行っています。
-
-
フロー
-
前提:クライアント側のサービスAでリソース側のサービスBの情報を使いたいとします。A,B,そしてアクセストークンを発行する認可サーバーがあるとします。
- まずユーザーはAに対しBの情報を使っていいよ、と許可を出します。
- その許可を得たAは認可サーバーに対し、アクセストークンを要求します。
- 認可サーバーからユーザーに対し、本当に許可を出していいか聞かれます。
- 3で許可を得た場合、認可サーバーはAに対しアクセストークンを送ります。
- アクセストークンを得たAはリソースサーバーBのAPIに対し要求とともにアクセストークンを送ります。
- Bは送られてきたアクセストークンがユーザーのデータを利用する権限を持っているか確認します。
- 6で権限があればAにユーザーの情報を送ります。
-
この2~4のフローで用いられるのがOAuthです。
https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be
-
-
OAuthに対しての観点とその概要
-
OAuthを使っていれば完璧に安全かと言われればそんなことはありません。
実装に不備があればそこが容易にセキュリティホールになります。
OAuthはユーザーのがサービスの特性や利用方法によって柔軟に設定することができるのでオプションによって大きく作用が変わります。
必要なのはクライアントID、エンドポインド、リダイレクトURI、スコープなどです。
特にOAuth認証では脆弱性が発生しやすいです。 -
OAuth認証というものが存在します。
元々OAuthは権限を確認する"認可"のためのものであり、その人物を"認証"するものではありません。
OAuthはアクセストークンを発行しますが、どこに向けて送っているかは確認していません。
アクセストークンは特定の人物の情報を見れる権限でしかありません。
よって被害者が罠サイトでOAuthによって連携しようとした場合、攻撃者は被害者のアクセストークンを得ることで「被害者の情報を見れる権限」を得ることができます。
リソースサーバーは誰が要求しているかの確認はしないので攻撃者に対して被害者の情報を送ってしまいます。
OAuthは認証しないことでAPIをより安全に使えるようにするものです。
認証をしたい場合はIDトークンも一緒に確認するOpenIDConnect(OIDC)を使うべきです。
参考
https://zenn.dev/uma002/articles/152fcef798730b
https://portswigger.net/web-security/oauth#how-do-oauth-authentication-vulnerabilities-arise
https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html- OAuthのサービス
- 自身でOAuthの設定をすることがセキュリティホールを生む原因となるので、提供されているOAuthサービスを使うのが安全です。
例えばAmazonはAmazon Cognitoというサービスを提供しています。
Amazon CognitoはWebアプリ・モバイルアプリの認証・認可機能を簡単に実装できるサービスです。
CognitoはOAuthのほかOIDCにも対応しており、認証も可能です。- OIDC(OpenIDConnect)
- OAuthの機能を拡張して認証に使えるようにしたもの。
OTPなどで本人確認を行うことと、アクセストークンとともにIDトークンも発行し、アプリケーションでIDトークンの検証を行うことがOAuthからの主な変更点です。
外部サービスを利用することでお金はかかりますが、認証・認可の際に自分で1から設定するよりもセキュリティを強固にできます。
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/federation-endpoints-oauth-grants.html
https://zenn.dev/mai_mizz/articles/cce2d2c764e9fc -
脆弱性の調査
JVN https://jvndb.jvn.jp/index.html / NVD https://nvd.nist.gov/vuln やプロダクトのリリース情報等で公開されている脆弱性情報を調査して、あなたが面白いと感じた脆弱性を1つ選択してください。そして、選択した脆弱性について、以下の項目に沿って記述してください。
- 選んだ脆弱性に関する概要
- 関連記事や報告されている脆弱性内容に関するリンク(JVN/NVD)を交えつつ回答してください。
- 攻撃手法の詳細や脆弱性に対する対策など調査したこと
- 他に感じたこと・気がついたこと(例: 調査した結果から「こういう対策をした方が良かったのでは」というアイデアや「こういうことにも活かせそう」という考えなど)
// 上記の項目の指示に従いつつ、ここに回答を自由なフォーマットで記入してください。
-
OAuthにおけるCSRF攻撃
- 概要
- 私が興味のある脆弱性はOAuthにおけるCSRF攻撃です。
OAuthにおけるCSRF攻撃とは、攻撃の標的となったユーザに攻撃者のリソースを処理させる権限を与えることです。
一般的にCSRFというと何らかの方法で攻撃者が被害者に対してリンクを踏ませて被害者になりすました後、ログイン状態であるサイト上での買い物や設定変更などを強制的に実行させる攻撃です。
しかしOAuthにおけるCSRF攻撃は被害者の行動が攻撃者に対して処理されるようになります。
例えば被害者がSNSと攻撃者のストレージサービスを連携されるCSRF攻撃を既に受けた状態でSNSに投稿しようとした場合、SNSだけでなく攻撃者のストレージサービスにも投稿されるようになります。
これにより被害者の発信した情報が攻撃者のストレージに保存され、情報漏洩が起こることが考えられます。
- 用語
- State
- RFC6749でCSRF攻撃対策として定められているパラメータです。
- 認可サーバーに問い合わせる際にクライアントサービス側が生成します。
- リダイレクトURLに生成したStateを付与してアクセストークンを受け取る際に同一ユーザーか確認をします。
-
なぜ起きるのか
結論から言うとOAuthにおけるCSRF攻撃はStateパラメータの不足、またはStateパラメータの検証の不備によって起こります。
認可サーバーからはStateパラメータなしでOAuth認証を始めたユーザーとアクセストークンを渡そうとしているユーザーが同じかの判別がつかないため、リダイレクトURLさえあっていればアクセストークンを渡してしまいます。
そこでStateパラメータでユーザーの検証を行います。 -
事例
- OAuth Connection CSRF Leading to Account Takeover(https://inside.pixiv.blog/kobo/5962)
- Weiboのみ[~/login.php?username=hoge&password=fuga]のようなGETのクエリパラメータにIDとパスワードを渡してログインできる機能があった
- 被害者が1のような攻撃者のIDとパスワードの入ったログインURLを踏ませられる
- 被害者は2によって攻撃者のWeiboでログインした状態でpixivのOAuth連携のURLを踏ませられる
- 3により攻撃者のWeiboアカウントと被害者のpixivアカウントが連携され、攻撃者が自身のWeiboを使って被害者のpixivにログインできるようになる
- 発生原因
- OAuth連携する先のサイトでログインしているアカウントが連携しようとしているユーザー本人のものであるかの確認を怠ったことによる
- 対策
- Stateパラメータによる連携者の確認
- Login CSRF using Twitter OAuth(https://hackerone.com/reports/2228)
- これはOAuth1.0Aの脆弱性ですが一応紹介
- 攻撃者がPhabricatorでTwitterとOAuth連携をしようとする
- 攻撃者がPhabricatorアプリへのアクセスを許可する
- 攻撃者はPhabricatorへのリダイレクトURLを保持し、自身は連携を行わない
- 3で保持したリダイレクトURLを元に[/auth/login/twitter:twitter.com/?oauth_token={attacker_token}&oauth_verifier={attacker_verifier}]に誘導する。
- 発生原因
- OAuth連携する先のサイトでログインしているアカウントが連携しようとしているユーザー本人のものであるかの確認を怠ったことによる
- 対策
- Stateパラメータによる連携者の確認
- OAuth Connection CSRF Leading to Account Takeover(https://inside.pixiv.blog/kobo/5962)
-
攻撃手法の詳細や脆弱性に対する対策
- フロー
-
前提:webサービスAとストレージサービスBがあるとする。攻撃者は被害者が入力した情報がストレージサービスBに蓄積するようにしたい。
- 攻撃者が攻撃者自身のアカウントでサービスAに対しサービスBと連携するよう申請する
- サービスBにリダイレクトし、サービスAと連携して良いか聞かれるので許可する
- サービスBからサービスAに戻るための認可コード付きのリダイレクトが発生するがここでリダイレクトはせず、リダイレクト先のURLを持っておく(認可コードはURLクエリに付く)
- 何らかの方法で被害者に送り付けて3でとっておいたリダイレクト先のURLを踏ませる
- 攻撃者のリダイレクトURLを踏まされた被害者は、被害者のサービスAアカウントでサービスBに対し攻撃者の認可コードを送って攻撃者のストレージサービスBと連携しようとしてしまう
- 認可コード自体は間違っていないのでサービスBは最初に申請してきた人物と今連携しようとしている人物が同じかを確かめることなくこれを承認し、被害者に対しアクセストークンを送る
- これにより、被害者のサービスAと攻撃者のサービスBは連携される
- 被害者が自身のサービスAアカウントで投稿した情報が、攻撃者のストレージサービスBへ一緒にアップロードされることが想定されます。
- さらにサービスBでサービスAにログインできる機能が実装されていた場合、攻撃者が被害者のサービスAアカウントにログイン可能になります。これによりなりすまし、アカウントの乗っ取りが起こりえます。(サービスAの例:Qiita サービスBの例:GitHub 被害者のQiitaと攻撃者のGitHubが連携した場合、QiitaはGitHubでログインできるので攻撃者にQiitaにログインされる)
- 対策
- Stateパラメータをつける
- Stateパラメータを検証することでOAuth連携を始めたユーザーとアクセストークンを受け取るユーザーが同一人物かどうかを判定する必要があります。
- 仕様による不備ではないのでしっかりとユーザー確認をすることでOAuthにおけるCSRF攻撃を対策できます。
- 遷移先をRefererヘッダを用いて確認する
- 攻撃者のアカウントでログインする際のstateパラメータも含むURLを被害者にアクセスさせることでCSRFが可能になります。
- 遷移先をRefererヘッダを用いて確認することによって、ログイン処理の前後のリクエストを確認できます。
- これによって被害者が外部のURLに直接アクセスする可能性を減らすことが可能だと考えられます。
-
実際の脅威
- 被害者のアカウントの情報が取得できることによる情報漏洩が主に考えられます。
- さらに、2-1でも解説しましたが連携した攻撃者のアカウントによって被害者のアカウントにログインできる仕様になっていた場合、なりすまし、被害者のアカウントの操作、最悪の場合アカウントが乗っ取られることが考えられます。
-
まとめ
- Stateパラメータの不備によるものなのでとりあえずStateパラメータをつける仕様にすることが大切
- Stateの実装は大変ではないので単純なミスか大丈夫だろうという思い込み(pixivの件など)によって引き起こされる
- 何かしらの方法で被害者にURLを踏ませる必要があるので攻撃難易度は高いが被害は大きいので実装時に必ず、OAuthの最初と最後にユーザーが同一かの確認をしているかをチェックしなければならない
参考
Discussion