こんにちは、サイオステクノロジー武井です。
※本記事の英語版はこちら(Click here to read in English)
今回は、OpenID Connectで利用されるnonceパラメーター(ノンスと読むらしいです、ナンスと呼んで恥かきました(´・ω・`))の目的について、私なりにわかりやすく図を交えながら、ご説明させて頂きたいと思います。
一言で言うならば、nonceパラメーターは、リプレイアタック(不正に傍受した正しいIDトークンを送りつけて、不正アクセスを実現する攻撃)を防ぐためのものです。
OpenID Connectの仕様書には以下のように書かれています。
リプレイアタックを阻止するため、署名のチェックを行なうエージェントは、肯定アサーションの中に含まれるノンス値の履歴を辿り、同一の OP エンドポイント URL について、同じ値を二度以上決して受け入れてはならない。
ニホンゴデハナシテクダサーイ(><)
ということで、私の理解をもとに、わかりやすく説明してみたいと思います。
まずは、nonceパラメータがない場合に、リプレイアタックを仕掛けられた場合の挙動についてご説明します。(リプレイアタックの詳細についても次章で合わせて記載します)
nonceパラメーターがない場合
まず、今回の説明の中で登場する人物やサービスをご紹介致します。
SNS1・・・Relying Partyです。OpenID Connect Providerによって認証のサービスを受ける側です。 | |
SNS2・・・OpenID Connect Providerです。つまり認証のサービスを提供する側です。 | |
Aさん・・・SNS1のサービスの利用者です。 | |
悪い人・・・リプレイアタックにより、不正アクセスを目論む悪い人です。 |
Aさんは、SNS1にアクセスします。しばらくは、ごくごく一般的なOpenID Connectの認証フローが続きます。
Aさんは、SNS2へのAuthorization Endpointへリダイレクトされます。
SNS2のログイン画面が表示されます。IDとパスワードを入力します。
事前に定義したコールバックURLにリダイレクトされます。そのとき、クエリパラメーターに認可コードが付与されます。
IDトークンを取得するため、認可コードと共に、Token Endpointにアクセスします。
SNS2は、SNS1に対して、IDトークンをトークンを発行します。しかし、悪い人はその通信を傍受し、IDトークンを取得してしまいます。
悪い人は、先程傍受したIDトークンをSNS1に送りつけます。すると、SNS1はそのIDトークンを正しいものとして受け入れます。なぜならば、IDトークンはSNS2からSNS1に対して、正規なリクエストに対して発行されたものだからです。iss(IDトークンの発行元)も正しいし、aud(IDトークンの発行先)も正しいので、SNS1はこれが不正なIDトークンかどうかを見分ける手段はありません。
nonceパラメーターがある場合
では、nonceパラメーターを使った場合、先程の攻撃がどのように防げるかを見てみましょう。
まず、Aさんは、SNS1にアクセスします。
Aさんは、SNS2へのAuthorization Endpointへリダイレクトされます。このとき、SNS1では、衝突の可能性の低い値を生成して、Aさんのセッションに保存、さらにAuthorization Endpointへのクエリパラメータに付与して、AさんをAuthorization Endpointへリダイレクトします。
SNS2のログイン画面が表示されます。IDとパスワードを入力します。
事前に定義したコールバックURLにリダイレクトされます。そのとき、クエリパラメーターに認可コードが付与されます。
IDトークンを取得するため、認可コードと共に、Token Endpointにアクセスします。
SNS2は、SNS1に対して、IDトークンをトークンを発行します。前回と違い、IDトークンの中には、nonceクレームという値があります。これは、Authorization Endopointへのリダイレクト時にクエリパラメーターとして付与したnonceの値と同じです。そして、このIDトークンを受け取ったSNS1は、Aさんのセッションに保存されているnonceの値と、IDトークンの中に含まれているnonceの値を比較し、一致した場合にだけこのIDトークンを受け入れます。そして、悪い人は先程と同様、通信を傍受して、このIDトークンを取得します。
SNS1は、IDトークンの検証が終わったら、Aさんのセッションの中にあるnonceの値を削除します。
悪い人は、先程傍受したIDトークンをSNS1に送りつけます。SNS1は、IDトークンの中にあるnonceクレームの値と、Aさんのセッションの中にあるnonceの値を比較しようとします。しかし、先程、Aさんのセッションの中にあるnonceの値は削除してしまったので、一致しません。よって、SNS1はこのIDトークンを受け入れず、悪い人によるリプレイアタックは成立しません。
つまり、nonceパラメーターは、IDトークンが再利用されないために、IDトークンに付与する一時的な(number used once)値というわけです。
これでリプレイアタックが防げますね。