OAuthやOpenID Connectで使われるstateパラメーターについて

こんにちは、サイオステクノロジー技術部 武井です。今回は、OAuthやOpenID Connectで使われるstateパラメーターについて書いてみました。どうして、stateパラメータが必要なのか、stateパラメーターがないとどんな悪いことが起こるのか整理しました。

stateパラメーターとは?

stateパラメーターは、CSRF(クロスサイトリクエストフォージェリ)対策で付与します。CSRFとはユーザー本人がいとしないリクエストを、悪意のある第三者によって強制する攻撃のことです。だいぶ昔には、mixiの「はまちちゃん」で有名になりましたが、OAuthやOpenID Connectにも同様のリスクがあります。その対策がstateパラメーターになります。ただ、stateパラメーターで対策するのは、「なりすまされ」というのであって、ここが今までのCSRF対策とイマイチ違いがわかりにくい点になります。(少なくとも私は理解に苦しみました^^;)

stateパラメーターの説明

stateパラメーターのない世界と、ある世界ではどのように違うのかを説明することで、stateパラメーターの有効性を説明します。とあるシステムを例に上げることとします。そのシステムの登場人物は以下のとおりとなります。

Screen Shot 2018-04-08 at 21.36.55 ストレージサービス・・・クラウド上のオンラインストレージサービスです。ユーザーは自分の領域に任意のファイルを格納することが出来ます。
Screen Shot 2018-04-08 at 21.41.48 サービスA・・・ストレージサービスを利用するサービスです。OAuth認証を用いて、ユーザーにストレージサービスを利用させます。
Screen Shot 2018-04-08 at 21.50.09 Aさん・・・サービスAの正規な利用者です。
Screen Shot 2018-04-08 at 21.51.43 悪い人・・・ユーザーAさんに対してCSRF攻撃を行おうとする攻撃者です。

stateパラメーターのない世界

stateパラメーターのない世界では、どのような悪いことが起こるのかを説明します。

 

まず、以下のようなシステムを想定します。ストレージサービスは外部にAPIを公開しており、そのAPIでファイルをアップロードできます。そしてAPIの認証はOAuthで行います。サービスAはOAuth認証を用いて、ユーザーがサービスAにアップロードした画像をストレージサービスにもアップロードします。悪い人は、まず、サービスAにアクセスして、OAuth連携を開始します。

Screen Shot 2018-04-08 at 22.02.10

 

悪い人は、ストレージサービスの認可画面にリダイレクトされます。「はい」をクリックします。

Screen Shot 2018-04-08 at 22.04.45

 

すると、認可コードをクエリパラメーターに付与した、サービスAへのリダイレクトが発生します。しかし、悪い人は、ここで、リダイレクト先のURLだけ取得をし、サービスAにリダイレクトさせないようにします。この実現方法は色々ありますが、独自のHTTPクライアントのプログラムを開発して、Locationヘッダからリダイレクト先のURLだけを抜き取り、実際のリダイレクトはさせないようにすればよいと思います。

Screen Shot 2018-04-08 at 22.06.01

 

悪い人は、先程取得したURLをメールなどの手段でAさんに送付して、AさんにそのURLにアクセスさせます。すると、アクセストークンを取得する主体は、悪い人からAさんに移り、悪い人のアクセストークンを取得するプロセスは、今後、Aさんのセッションで行われることとなります。ここがキモです。

Screen Shot 2018-04-08 at 22.09.17

 

サービスAは、認可コードをストレージサービスに渡して、アクセストークンを要求します。

Screen Shot 2018-04-08 at 22.13.38

 

ストレージサービスは、悪い人のストレージにアクセスするためのアクセストークンをサービスAに返します。なぜそうなるかというと、アクセストークンを取得するために発行された認可コードは、悪い人によって発行されたものだからです。

そして、そのアクセストークンは、ユーザーAのデータベースに格納されます。なぜそうなるかというと、認可コードをサービスAに渡したのは、他ならぬAさんだからです。

Screen Shot 2018-04-08 at 22.12.18

 

つまり、Aさんは、悪い人のアクセストークンを取得し、悪い人のストレージに自由にアクセスできるようになりました。他人のストレージを自由にアクセスできるわけですから、あまり害はないように思えますが、ここで一番まずのは、Aさんが知らない間にこのような状況に陥ってしまったことです。これは、「乗っ取り」ではなくて「乗っ取られ」といわれるもので、例えば、他の人に漏らしたくないような情報を自分のフォルダにアップロードしたつもりが、実は悪い人のフォルダに知らない間にアップロードしていることになり、悪い人はAさんのプライベートを見ることが出来てしまうわけです。

Screen Shot 2018-04-10 at 8.55.36

stateパラメーターのある世界

stateパラメーターがあると、先程のような被害を防ぐことが出来ます。先程のケースで、stateパラメーターを付与した場合にどの様になるかを説明してみます。

 

悪い人は、まず、サービスAにアクセスして、OAuth連携を開始します。ここまでは、先程と一緒です。

Screen Shot 2018-04-08 at 23.36.12

 

悪い人は、ストレージサービスの認可画面にリダイレクトされます。先ほどと違うのは、サービスAがリダイレクト先のURLのパラメーターにstate=xyzという値を付与していることです。さらに、このとき、サービスAは、このstateの値を悪い人のセッションに紐づけます(Javaでいえば、request.getSession().setAttribute(“state”,”xyz”)とします)。

Screen Shot 2018-04-08 at 23.42.28

 

すると、認可コードをクエリパラメーターに付与した、サービスAへのリダイレクトが発生します。しかし、悪い人は、ここで、リダイレクト先のURLだけ取得をし、サービスAにリダイレクトさせないようにします。先ほどと違うのは、ストレージサービスは、1つ前のプロセスで渡されたstateパラメーターをそのまま同じように、リダイレクト先のURLに付与しているところです。

Screen Shot 2018-04-08 at 23.47.50

 

先程と同様に、悪い人は、先程取得したURLをメールなどの手段でAさんに送付して、AさんにそのURLにアクセスさせます。

Screen Shot 2018-04-08 at 23.50.31

 

「stateパラメーターのない世界」と決定的に違うのがこのプロセスです。サービスAは、URLに付与されているstateパラメーターと、アクセスしてきたユーザーのセッションに格納されているstateパラメーターを比較して、一致していなければ不正なアクセスとして、処理を中断します。認可コードを取得したのは悪い人なので、stateパラメーターは悪い人のセッションの中に格納されていますが、認可コードをもとにアクセストークンを要求したのはAさんです。もちろん、Aさんのセッションの中には、stateパラメーターの値が入っていないので、下記のように不一致となります。このような理路により、CSRF攻撃を防御することが可能です。

Screen Shot 2018-04-08 at 23.55.47

最後に

いかがでしたでしょうか?OAuthやOpenID Connectには、このようにセキュリティを考慮した仕組みがいくつかありますので、今後も、ご紹介していきたいと思います。

Be the first to comment

コメント投稿

Your email address will not be published.


*