nginxでDigest認証が正しく動作しているか検証してみる | no news.

nginxでDigest認証が正しく動作しているか検証してみる

はじめに

さて先日の記事でnginxのDigest認証のインストールと設定を行いました。でも果たしてちゃんと動作しているのだろうか?少々気になったので調べてみました。

Digest認証の動作

ここでWikipediaのDigest認証のページより認証動作を確認してみます。

  1. クライアントは認証が必要なページをリクエストする。しかし、通常ここではユーザ名とパスワードを送っていない。なぜならばクライアントはそのページが認証を必要とするか否かを知らないためである。
  2. サーバは401レスポンスコードを返し、認証領域 (realm) や認証方式(Digest)に関する情報をクライアントに返す。このとき、ランダムな文字列(nonce)も返される。
  3. それを受けたクライアントは、認証領域(通常は、アクセスしているサーバやシステムなどの簡単な説明)をユーザに提示して、ユーザ名とパスワードの入力を求める。ユーザはここでキャンセルすることもできる。
  4. ユーザによりユーザ名とパスワードが入力されると、クライアントはnonceとは別のランダムな文字列(cnonce)を生成する。そして、ユーザ名とパスワードとこれら2つのランダムな文字列などを使ってハッシュ文字列(response)を生成する。
  5. クライアントはサーバから送られた認証に関する情報とともに、ユーザ名とresponseをサーバに送信する。
  6. サーバ側では、クライアントから送られてきたランダムな文字列(nonce、cnonce)などとサーバに格納されているハッシュ化されたパスワードから、正解のハッシュを計算する。
  7. この計算値とクライアントから送られてきたresponseとが一致する場合は、認証が成功し、サーバはコンテンツを返す。不一致の場合は再び401レスポンスコードが返され、それによりクライアントは再びユーザにユーザ名とパスワードの入力を求める。

検証

それでは順番に1から見ていきたいと思います。パケットキャプチャにはWiresharkを使いました。

スポンサーリンク
レクタングル大

環境

サーバーIPアドレス:133.242.211.47
クライアントIPアドレス:192.168.89.16

通信の流れ

1. クライアントは認証が必要なページをリクエストする。しかし、通常ここではユーザ名とパスワードを送っていない。なぜならばクライアントはそのページが認証を必要とするか否かを知らないためである。

とあります。キャプチャではクライアントがサーバーにリクエストを行っていることがわかります。この時点では
単純に/auth/へのリクエストを行っているだけです。

01

2. サーバは401レスポンスコードを返し、認証領域 (realm) や認証方式(Digest)に関する情報をクライアントに返す。このとき、ランダムな文字列(nonce)も返される。

ここではサーバーからクライアントへ上記の応答を返されます。内容は脚注のとおりです。

02

3. それを受けたクライアントは、認証領域(通常は、アクセスしているサーバやシステムなどの簡単な説明)をユーザに提示して、ユーザ名とパスワードの入力を求める。ユーザはここでキャンセルすることもできる。

これはブラウザで表示されるダイアログですね。サーバーからのメッセージといてRealm(This is not for you)が表示されています。これは2.でのサーバーからの応答にも含まれていますね。

03

4.ユーザによりユーザ名とパスワードが入力されると、クライアントはnonceとは別のランダムな文字列(cnonce)を生成する。そして、ユーザ名とパスワードとこれら2つのランダムな文字列などを使ってハッシュ文字列(response)を生成する。
5. クライアントはサーバから送られた認証に関する情報とともに、ユーザ名とresponseをサーバに送信する。

クライアントからサーバーへ認証情報を送ります。クライアントが生成したresponseのみならずサーバーから送られたnonce、クライアントが生成したcnonceについても送信されていることがわかります。

04

6. サーバ側では、クライアントから送られてきたランダムな文字列(nonce、cnonce)などとサーバに格納されているハッシュ化されたパスワードから、正解のハッシュを計算する。
7. この計算値とクライアントから送られてきたresponseとが一致する場合は、認証が成功し、サーバはコンテンツを返す。不一致の場合は再び401レスポンスコードが返され、それによりクライアントは再びユーザにユーザ名とパスワードの入力を求める。

パケットからはサーバーがハッシュを計算したかどうかは分かりませんが、クライアントへ304を返していることがわかります。これはキャプチャする前に一回アクセスしちゃったからだと思われます。

05

また、応答にqop、rspauth、ncという見慣れない言葉が出てきています。qop、ncはwikiによると下記の記載があります。

ユーザ名とパスワードの具体的な計算は以下のようになる。なお、ここでは認証アルゴリズムがMD5の時の計算方法を示す。
クライアントが計算するresponseは以下のようにして求められる:
A1 = ユーザ名 “:” realm “:” パスワード
A2 = HTTPのメソッド “:” コンテンツのURI
response = MD5( MD5(A1) “:” nonce “:” nc “:” cnonce “:” qop “:” MD5(A2) )

サーバ側では、MD5(A1) をあらかじめ計算し格納してある。nonce,nc,cnonce,qopとHTTPのメソッド(GETなど)とコンテンツのURIはクライアントから送られてくるので、サーバ側でもresponseの正解を計算できる。

言われてみれば5.のキャプチャを見るとnc=00000001、qop=authというのが見られますね。

rspauthについてはRFC2617の16ページ目に記載があります。

AuthenticationInfo = “Authentication-Info” “:” auth-info
auth-info = 1#(nextnonce | [ message-qop ]
| [ response-auth ] | [ cnonce ]
| [nonce-count] )
nextnonce = “nextnonce” “=” nonce-value
response-auth = “rspauth” “=” response-digest
response-digest = <"> *LHEX <">

The optional response digest in the “response-auth” directive
supports mutual authentication — the server proves that it knows the
user’s secret,

The “response-digest” value is calculated
as for the “request-digest” in the Authorization header, except that
if “qop=auth” or is not specified in the Authorization header for the
request,

このへんからよくわからんようになってきました。おそらくこのrspauthの値を使ってサーバー⇔クライアント間の認証が正しく出来ているということを表しているのでしょう。
まあでも、パスワードが平文で流れていないことが分かったので良しとしたいと思います。

というわけでまたもやモヤモヤした感じで終わりましたが、ご参考になれば幸いです。

スポンサーリンク
レクタングル大

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
レクタングル大