第9章 セキュアな実装
[9-1.]
パスワードの取り扱い
ユーザ認証を行うアプリケーションが独自にアカウント情報を管理している場合がある。しかし多くの場合,パスワードは平文で取り扱われ,データベースにも暗号化されずに保存されており,データが事故等で流出した場合に大きな問題となり得る。



 PDF
● ● ●
パスワード
ユーザのパスワードには手厚いセキュリティ対策が必要だ。
 
たとえば,会員サービスのアプリケーションソフトウェアが画面1のように会員情報テーブル内にパスワードをクリアテキスト(そのまま読めるデータ)で保存していたとする。データベースの保守作業で使われたダンプリストが不用意に捨てられたり,バックアップテープが間違って持ち出されるなど,なんらかの事故や盗難などで漏洩した場合,テーブルに書かれているユーザID,パスワードをそのままの形で不正行為者が利用することができ,大変危険である(図1)。
画面1 パスワードが平文で格納されている会員情報テーブルの例
 画面1 パスワードが平文で格納されている会員情報テーブルの例
図1 平文で保存されているパスワードが会員情報とともに漏洩すると大問題である
 図1 平文で保存されているパスワードが会員情報とともに漏洩すると大問題である
オペレーティングシステムのパスワード
マルチユーザのオペレーティングシステム(OS)製品ではパスワード管理の歴史が長い。LinuxやWindowsなどのパスワードがどのように保管されているか見てみよう。
 
リスト1はLinuxのパスワードファイルの例である。実は最初のrootという1つのアカウントにだけパスワードが設定されているのだが,この「$1$UfhlioB0$s6jfxX07Z1cGkGOC1XEbb/」という文字列がパスワードに該当するデータである。
 
画面2はL0phtcrackというツールでWindows 2000のパスワード情報を表示させたものである。「LM Hash」と「NTLM Hash」の2つの欄に表示されているものが2つともパスワードに該当するデータである。
 
実はここに表示されているデータはどれもパスワードそのものではない。これらはパスワードの文字列から計算された「メッセージダイジェスト」あるいは「ハッシュ値」と呼ばれるデータである。
リスト1 Linux システムのパスワードデータの例(/etc/shadow ファイル)
1 root:$1$UfhlioB0$s6jfxX07Z1cGkGOC1XEbb/:11717:0:99999:7:-1:-1:134539252
2 bin:*:11472:0:99999:7:::
3 daemon:*:11472:0:99999:7:::
 ...以下略...
画面2 Windows 2000のパスワードデータの例(L0phtcrackによる表示)
 画面2 Windows 2000のパスワードデータの例(L0phtcrackによる表示)
メッセージダイジェスト
メッセージダイジェストとは専用の特殊なアルゴリズムで計算される特殊な値である。これは与えられたデータから計算された一見ランダムな値であり,元のデータが異なればメッセージダイジェストの値も異なるが,メッセージダイジェストから元のデータを推測することは困難という特徴をもつ(図2)。
 
メッセージダイジェストは「ハッシュ値」と呼ばれることもある。「ハッシュ値」は通常のデータから特定の目的のために生成されるランダムなデータ全般を指す広い言葉だが,本稿ではメッセージダイジェストとほぼ同じ意味としてこの呼び名を使う。
 
最初に述べたように,ユーザのパスワードをクリアテキスト(そのままの文字列)で保存することは安全であるとはいえない。重要なデータを扱うアプリケーションプログラムの場合,各種OSと同様,ハッシュ値の形でパスワードを保管すべきである(図3)。
図2 メッセージ・ダイジェストの概念
 図2 メッセージ・ダイジェストの概念
図3 メッセージダイジェストにしておけば悪用されるまでのあいだ時間が稼げる
 図3 メッセージダイジェストにしておけば悪用されるまでのあいだ時間が稼げる
メッセージダイジェストの種類
何通りかのメッセージダイジェストのアルゴリズムが公開されている。メッセージダイジェストのアルゴリズムを自作することはあまりお奨めできない。ランダムなデータを作ったつもりでも案外規則性が出てしまうものである。むしろ次のような公開されているアルゴリズムを利用したほうがよい。
  • MD4 RFC 1320で公開されているアルゴリズムである。
  • MD5 MD4の改良版であり,RFC 1321で公開されている。
  • SHA1 米国政府の標準として採用されているアルゴリズムである。
  • RIPE MD-160 160bitのハッシュ値を生成するハッシュ関数であり,RIPE MD(およびMD4,MD5)を置き換える目的で開発されたアルゴリズムである。
MD5を実装したライブラリが比較的多く提供されている。Windows系アプリケーションなら,ASP(Active Server Pages)やVisual BasicなどからBabaq氏のBASP21.DLLを用いることでMD5アルゴリズムを用いることができる。Perlや他のいくつかの言語についてもモジュールが提供されている。適当なライブラリが見つからない場合は,RFC 1321にC言語のソースコードと検証用データが掲載されているのでポーティングする方法もある。
メッセージダイジェストを使った認証
パスワードをメッセージダイジェストとして保存している場合は,ユーザが入力してきたパスワード文字列と直接比較検証はできないが,ユーザの入力文字列からもう一度ハッシュ値を作ってその値どうしを比較することができる。クライアント・サーバ型のアプリケーションシステムの場合,メッセージダイジェストを使った認証は次のような手順になる(図4)。
  1. ユーザがクライアントプログラムにユーザIDとパスワードを入力する。
  2. クライアントプログラムはユーザIDとパスワードをサーバプログラムへ送信する
  3. サーバプログラムは,受け取ったパスワードのハッシュ値を計算する。
  4. サーバプログラムは,受け取ったユーザIDをキーとして会員情報にアクセスし,パスワードのハッシュ値を取り出す。
  5. サーバプログラムは 3. で得られた値と 4. で得られた値とを比較する。
図4 メッセージダイジェストで保管されているパスワードの照合
 図4 メッセージダイジェストで保管されているパスワードの照合
メッセージダイジェストの流出
万一メッセージダイジェストの形のパスワード情報が流出した場合,パスワードそのものが流出したときほど深刻ではないが,それでも事後対策は早めに行う方がよい。
 
ハッシュ値から元のパスワードを復元することはできないものの,パスワードの綴りをいくつも試して目的のハッシュ値が生成されるかどうかを調べる総当たり攻撃は可能である。パスワードのハッシュ値を盗み出した直後にパスワードを盗用することは無理だが,高性能なコンピュータを使った総当たり攻撃でパスワードを見つけだされることは十分あり得る。
 
パスワード情報が漏洩してしまったら,直ちに全ユーザのパスワードを付け替えるといった対応を行うべきである。
パスワードを忘れたユーザへのフォロー
インターネットで多くの会員にサービスを提供するWebアプリケーションの場合,ユーザがパスワードを忘れてしまった場合のサポートも大切だろう。
 
パスワードを元の形で保管していれば,あらかじめ登録されているユーザが保有していることが確実なメールアドレスなどに「あなたのパスワードは××××です」という内容のメールを送付できる。ハッシュ値のみでパスワードの情報を保管している場合,このようなサービスができないデメリットがある。
 
もちろん,取り扱う情報の重要性とユーザの利便性のバランスを考慮した設計が求められることは確かである。しかし,ある程度重要な情報を取り扱うアプリケーションの場合,ユーザへの再通知を可能とするためにパスワードを平文で保管しておくことは避けるべきである。パスワードを忘れたユーザに対しては,アプリケーションの側でパスワードを再発行して通知するなどの手順を取ることが望ましい。パスワードをユーザに通知する際には,ユーザが通常アプリケーションを利用するときとは異なる通信方法(暗号化メール,書留郵便など)を用いることも大切だ。
チャレンジ/レスポンス方式
パスワードをメッセージダイジェストとしてサーバに保管していても,クライアント・サーバ間のネットワーク通信が傍受されれば,ユーザの入力したパスワード文字列が盗まれてしまう(図5)。
図5 保存されているパスワードが安全な形式でも,ユーザ入力を伝送する過程で盗聴される
 図5 保存されているパスワードが安全な形式でも,ユーザ入力を伝送する過程で盗聴される
盗聴に対してはクライアントとサーバの間の通信経路をSSLなどで暗号化するという対策もあるが,クライアントソフトウェア側にある程度インテリジェントな機能を持たせ,パスワードそのものではなく毎回異なる特殊なデータをやりとりすることによってユーザ認証を行う,チャレンジ/レスポンス方式というやりかたもある。
 
チャレンジ/レスポンス方式のユーザ認証は次のような手順になる(図6)。
  1. サーバプログラムは「チャレンジ」と呼ばれるランダムな事前予測困難な値を生成して,クライアントプログラムへ送る。この「チャレンジ」はサーバプログラム自身も保持しておく。
  2. ユーザは,クライアントプログラムに対してユーザIDとパスワードを入力する。
  3. クライアントプログラムは入力されたパスワードのメッセージダイジェストを計算する。
  4. クライアントプログラムは,3. で計算したメッセージダイジェストと 1. で与えられた「チャレンジ」を合わせたものを元のデータとしてもう一度メッセージダイジェストを計算する。これは「レスポンス」と呼ばれる(注1)。
  5. クライアントプログラムは,ユーザIDと 4. で生成した「レスポンス」をサーバへ送る。
  6. サーバプログラムは,受け取ったユーザIDをキーとして会員情報にアクセスし,メッセージダイジェストの形のパスワード情報を取り出す。
  7. サーバプログラムは,6. で取り出したパスワードのメッセージダイジェストと 1. で保持していた「チャレンジ」を合わせたものを元のデータとしてもう一度メッセージダイジェストを計算する。これは「レスポンス照合データ」となる。
  8. サーバプログラムは,クライアントプログラムから送られた「レスポンス」と, 7. で自身が生成した「レスポンス照合データ」とを比較する。
チャレンジ/レスポンス方式の場合,「チャレンジ」および「レスポンス」が盗難された場合でも,これらは毎回変化する値であるために,ユーザのパスワードを推測するのは困難である(図7)。
(注1・「レスポンス」を作る際のメッセージダイジェスト生成アルゴリズムは,ユーザのパスワードのメッセージダイジェストを生成したものとは異なるアルゴリズムであることが望ましい。)
図6 チャレンジ/レスポンス認証の手順
 図6 チャレンジ/レスポンス認証の手順
図7 チャレンジとレスポンス
 図7 チャレンジとレスポンス
パスワードの代わりに毎回異なるデータがネットワークを流れる。
 
クライアントプログラムとしてWWWブラウザを利用するWebアプリケーションでも,JavaScriptでメッセージダイジェスト生成アルゴリズムを実装することにより,チャレンジ/レスポンス方式の認証処理を行うことができる。クライアントマシンの性能にもよるが,実際にJavaScriptによるMD5の実装が存在し,十分実用になる速度で稼動している。
まとめ
パスワードをそのままの形で保存するのは危険だ。重要な情報を扱うシステムではメッセージダイジェストのみを保管するなどの対策をとるべきである。ただし,メッセージダイジェストといえども解読されうるので万一データが流出した際の事後対策も欠かせない。伝送されるパスワードの盗聴対策にはチャレンジ/レスポンス方式を用いる方法もある。
参考文献
「WindowsNT World」1998年5月号〜7月号『管理者が実践できるNTセキュリティ・テクニック』
“第13回 パスワードの保護”,“第14回 パスワードの保護 続編”,“第15回 NT同士の認証の問題点”
『Perlの小技』
『BASP21』
『RFC1321 日本語訳』(「MD5」)
『The hash function RIPEMD-160』(英文)
『RFC1321 (The MD5 Message-Digest Algorithm)』(英文)
『RFC1320 (The MD4 Message-Digest Algorithm)』(英文)
『FIPS 180-1 SECURE HASH STANDARD (SHA-1)』(英文)