Digest認証はどのような脆弱性対策をしているか

最近CTFをやってみたのをきっかけに、Digest認証のRFCRFC2617)を読みました。今どきDigest認証を使うことはあまりなさそうですが、RFCにはセキュリティ面で考慮したことが色々書かれていて勉強になりました。古典大事。というわけで、いくつかの攻撃手法について、Digest認証はどのように対策しているか、理解したことをまとめてみます。

f:id:ks888:20160509210742p:plain:w400

通信の覗き見

これはBasic認証と比較したときのDigest認証のメリットとしてよく挙がります。例えば公衆WiFiとかにつないでいて、暗号化されていない通信を覗き見された場合、Basic認証だとパスワードが丸見えになっていまいます。

Digest認証では、パスワード自体は通信せず、パスワードを含む文字列のMD5ハッシュ値を通信しています。なので、通信を覗き見されてパスワードが丸見えになる、ということは起きません。一方でパスワード以外は、暗号化もハッシュ化もしていないので丸見えです。

ちなみにMD5SSL/TLSだと非推奨とされていて、MD5=脆弱なイメージがあります。ただ個人的には、MD5は衝突攻撃に対しては脆弱で、改ざん防止には使えないけど、Digest認証のようなパスワードをハッシュ化する用途では、致命的な問題は見つかっていない、と理解しています。

リプレイアタック

リプレイアタックは、覗き見した認証情報を利用し、正規ユーザのふりをして認証をパスする攻撃です。Digest認証だと、HTTPリクエストのAuthorizationヘッダーが認証情報にあたります。

Digest認証の場合、そもそも攻撃者がリプレイアタックをする動機が少し弱くなっています。というのも、覗き見した認証情報は、覗き見したURIでしか使えないからです。例えば、/index.htmlというURIにクライアントがアクセスしたときの認証情報は、他のURI/faq.htmlとか)では使えません。とはいえ、POSTリクエストの再発行とかはできるので、リプレイアタックされる可能性は十分あります。

対策としては、nonceとnonce-countという仕組みがあります。nonceはワンタイムトークンのことです。サーバが401 Unauthorizedレスポンスを返すたびに、nonceを新しく発行してクライアントに送ります。クライアントはnonceやパスワード等を元にハッシュ値を計算し、サーバに送ります。このnonceですが、ワンタイムといいつつ、認証が成功した場合(つまり200 OKレスポンスを返す場合)にnonceを再発行するかは決められていません。Apacheの場合はnonceを使い回しているようです。これでは簡単にリプレイアタックされてしまいそうですが、そこでnonce-countの出番です。

nonce-countは、あるnonceを利用したリクエストの送信数を示す値です。サーバは、受け取ったnonce-countの値が以前と同じだったら、不正なリクエストとみなします。そのため、使いまわされているnonceをのぞき見して、リプレイアタックをしても失敗するようになっています。

選択平文攻撃

選択平文攻撃は、攻撃者の選択した平文とその暗号文のペアを集め、暗号鍵を推測する攻撃です。RFC内には記述を見つけられなかったのですが、Digest認証の場合は、攻撃者がnonceを選択し、パスワードを推測する攻撃だと思います。攻撃者が(中間者攻撃等の方法で)サーバの生成するnonceを書き換え可能であることが前提の攻撃となります。

対策として、cnonce (client nonce)という仕組みがあります。nonceはサーバが生成するトークンなのに対し、cnonceはクライアントが毎回生成するトークンです。クライアントが生成するので、nonceを書き換えられるような状況でもcnonceは書き換えられません。このcnonceをハッシュ値の計算に使うことで、ハッシュへの入力の制御が難しくなり、選択平文攻撃が難しくなります。

ちなみにcnonceは、事前計算辞書攻撃への対策でもあります。事前計算辞書攻撃は、パスワードとハッシュ値の辞書を前もって作っておいて、実際にやり取りされるハッシュ値を辞書に照らし合わせてパスワードを推測する攻撃です。通常はnonceによって事前計算コストを大幅に上げられますが、中間者攻撃等でnonceを固定されてしまうと、効果がありません。そのような場合でもcnonceがあると、cnonceごとに事前計算が必要になるため、ある程度の対策になります。

中間者攻撃

中間者攻撃は、攻撃者の制御下にあるノードに通信を中継させることで、通信内容を盗聴したり改ざんしたりする攻撃です。RFCにはっきり書いてありますが、Digest認証は中間者攻撃に対して脆弱です。中間者攻撃が成功すると、弱い認証方法にダウングレードされたり、勝手にBasic認証に変更されたりして、パスワードを盗みやすい状態にされてしまいます。

一応RFCには対策が書かれています。ただ、クライアントがサーバごとに過去の認証方法を覚えておいて、過去の認証方法より弱い方法を要求されたらユーザに警告する、みたいな方法なので、対策としては厳しいものがあります。

まとめ

いくつかの攻撃手法をピックアップして、Digest認証のRFCで述べられている対策について理解していることを整理してみました。実際のRFCにはセキュリティ面で考慮したことが他にも書かれているので、興味があれば読んでみてください。