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

こんにちは、サイオステクノロジー武井です。

※本記事の英語版はこちら(Click here to read in English)

今回は、OpenID Connectで利用されるnonceパラメーター(ノンスと読むらしいです、ナンスと呼んで恥かきました(´・ω・`))の目的について、私なりにわかりやすく図を交えながら、ご説明させて頂きたいと思います。

一言で言うならば、nonceパラメーターは、リプレイアタック(不正に傍受した正しいIDトークンを送りつけて、不正アクセスを実現する攻撃)を防ぐためのものです。

OpenID Connectの仕様書には以下のように書かれています。

リプレイアタックを阻止するため、署名のチェックを行なうエージェントは、肯定アサーションの中に含まれるノンス値の履歴を辿り、同一の OP エンドポイント URL について、同じ値を二度以上決して受け入れてはならない。

ニホンゴデハナシテクダサーイ(><)

ということで、私の理解をもとに、わかりやすく説明してみたいと思います。

まずは、nonceパラメータがない場合に、リプレイアタックを仕掛けられた場合の挙動についてご説明します。(リプレイアタックの詳細についても次章で合わせて記載します)

nonceパラメーターがない場合

まず、今回の説明の中で登場する人物やサービスをご紹介致します。

Screen Shot 2019-02-25 at 10.27.50 SNS1・・・Relying Partyです。OpenID Connect Providerによって認証のサービスを受ける側です。
Screen Shot 2019-02-25 at 10.27.56 SNS2・・・OpenID Connect Providerです。つまり認証のサービスを提供する側です。
Screen Shot 2019-02-25 at 10.27.41 Aさん・・・SNS1のサービスの利用者です。
Screen Shot 2019-02-25 at 12.14.47 悪い人・・・リプレイアタックにより、不正アクセスを目論む悪い人です。

 

Aさんは、SNS1にアクセスします。しばらくは、ごくごく一般的なOpenID Connectの認証フローが続きます。

Screen Shot 2019-02-26 at 22.23.37

 

Aさんは、SNS2へのAuthorization Endpointへリダイレクトされます。

Screen Shot 2019-02-26 at 22.29.35

 

SNS2のログイン画面が表示されます。IDとパスワードを入力します。

Screen Shot 2019-02-26 at 22.30.42

 

事前に定義したコールバックURLにリダイレクトされます。そのとき、クエリパラメーターに認可コードが付与されます。

Screen Shot 2019-02-26 at 22.31.35

 

IDトークンを取得するため、認可コードと共に、Token Endpointにアクセスします。

Screen Shot 2019-02-26 at 22.36.27

 

SNS2は、SNS1に対して、IDトークンをトークンを発行します。しかし、悪い人はその通信を傍受し、IDトークンを取得してしまいます。

 

Screen Shot 2019-02-26 at 22.40.37

 

悪い人は、先程傍受したIDトークンをSNS1に送りつけます。すると、SNS1はそのIDトークンを正しいものとして受け入れます。なぜならば、IDトークンはSNS2からSNS1に対して、正規なリクエストに対して発行されたものだからです。iss(IDトークンの発行元)も正しいし、aud(IDトークンの発行先)も正しいので、SNS1はこれが不正なIDトークンかどうかを見分ける手段はありません。

Screen Shot 2019-02-26 at 22.41.17

nonceパラメーターがある場合

では、nonceパラメーターを使った場合、先程の攻撃がどのように防げるかを見てみましょう。

まず、Aさんは、SNS1にアクセスします。

Screen Shot 2019-02-26 at 22.46.51

 

Aさんは、SNS2へのAuthorization Endpointへリダイレクトされます。このとき、SNS1では、衝突の可能性の低い値を生成して、Aさんのセッションに保存、さらにAuthorization Endpointへのクエリパラメータに付与して、AさんをAuthorization Endpointへリダイレクトします。

Screen Shot 2019-02-26 at 22.49.44

 

SNS2のログイン画面が表示されます。IDとパスワードを入力します。

Screen Shot 2019-02-26 at 22.54.15

 

事前に定義したコールバックURLにリダイレクトされます。そのとき、クエリパラメーターに認可コードが付与されます。

Screen Shot 2019-02-26 at 22.55.12

 

IDトークンを取得するため、認可コードと共に、Token Endpointにアクセスします。

Screen Shot 2019-02-26 at 22.56.35

 

SNS2は、SNS1に対して、IDトークンをトークンを発行します。前回と違い、IDトークンの中には、nonceクレームという値があります。これは、Authorization Endopointへのリダイレクト時にクエリパラメーターとして付与したnonceの値と同じです。そして、このIDトークンを受け取ったSNS1は、Aさんのセッションに保存されているnonceの値と、IDトークンの中に含まれているnonceの値を比較し、一致した場合にだけこのIDトークンを受け入れます。そして、悪い人は先程と同様、通信を傍受して、このIDトークンを取得します。

Screen Shot 2019-02-26 at 22.57.33

 

SNS1は、IDトークンの検証が終わったら、Aさんのセッションの中にあるnonceの値を削除します。

Screen Shot 2019-02-26 at 23.02.49

 

悪い人は、先程傍受したIDトークンをSNS1に送りつけます。SNS1は、IDトークンの中にあるnonceクレームの値と、Aさんのセッションの中にあるnonceの値を比較しようとします。しかし、先程、Aさんのセッションの中にあるnonceの値は削除してしまったので、一致しません。よって、SNS1はこのIDトークンを受け入れず、悪い人によるリプレイアタックは成立しません。

Screen Shot 2019-02-26 at 23.04.27

 

つまり、nonceパラメーターは、IDトークンが再利用されないために、IDトークンに付与する一時的な(number used once)値というわけです。

これでリプレイアタックが防げますね。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

21人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です