passwordcheck
笠原 辰仁
はじめに
本エントリは、PostgreSQL Advent Calendar 2012の12月4日分です。
昨今のwebサービスやOSのユーザ作成時には、推測されやすい弱いパスワードを弾く機能が標準で備わっています。これらの検査は一般的にはアプリケーションで実施されることが多いでしょう。しかし、DBのホスティングサービスやDaaS(Database as a Service)に代表されるように、PostgreSQLなどDBMSそのものを提供するサービス機構では、DBMSでのユーザ登録時に弱いパスワードを弾く機能が求められることもあります。しかし、PostgreSQL本体にはパスワードの強度を検査する仕組みはありません。
passwordcheckは、PostgreSQLのユーザやロールに指定するパスワードに対して検査を行い、推測されやすい弱い文字列を弾く仕組みを提供するcontribモジュールです。このモジュールはPostgreSQL9.0から追加されています。passwordcheckモジュールを使うことで、DBMSでのユーザ作成時のパスワード検査が可能となります。本記事では、passwordcheckモジュールの概要と使い方、およびその拡張について解説していきます。
passwordcheckの概要と提供する検査機能
passwordcheckモジュールは、PostgreSQLの内部Hookを利用しており、CREATE USER/ROLEやALTER USER/ROLE時のパスワード指定時に自動で検査します。そのためユーザからは透過的に使用できます。検査時に弱いと判断された場合は、ERRORメッセージを出力しパスワード指定を弾きます。passwordcheckはパスワードに対して以下の3つの検査を行います。
- 「8文字以上」かどうか
- 8文字未満のパスワードは弾かれます。8文字はハードコーディングされていて、コードを書き換えないと変更できません。
- 「アルファベット」と「それ以外の文字」の双方を使用しているかどうか
- アルファベットだけ、あるいはアルファベット以外の文字だけを使っているパスワードは弾かれます。内部的にはisalpha()関数でアルファベットかどうかを確認しています。数字や記号、マルチバイト文字は「アルファベット以外」と見なされます。
- ユーザ名/ロール名が含まれていないかどうか
- ユーザ名/ロール名と同じ文字列が含まれているパスワードは弾かれます。
では、具体的な挙動を使い方を通して見ていきます。
passwordcheckの使い方
passwordcheckの導入
passwordcheckを使用するには、通常のcontribモジュールの様にビルドするか、contribモジュールを含むrpmやdpkgパッケージをインストールします。下記はソースからビルドする場合の手順です。
★ $PGSRC はPostgreSQLのソースコードのトップディレクトリです。 $ cd $PGSRC/contrib/passwordcheck/ $ make USE_PGXS=1 $ make USE_PGXS=1 install
ビルドが終われば、あとはpostgresql.confのshared_preload_librariesパラメータに'passwordcheck'と指定し、PostgreSQLサーバを起動or再起動すれば有効になります。passwordcheckモジュールは、特にDBに対して関数やビューなどを登録することはないため、CREATE EXTENSION を実行する必要はありません。
passwordcheckを試す
以下は実際にCREATE ROLEで各種パスワード指定を試した結果です。上記で説明した検査で簡単なパスワードは弾かれていることが分かります。
-- 8文字に満たないパスワード =# CREATE ROLE test1 PASSWORD 'test'; ERROR: password is too short -- アルファベットしか使っていないパスワード =# CREATE ROLE test1 PASSWORD 'testtest'; ERROR: password must contain both letters and nonletters -- ROLE名を含むパスワード =# CREATE ROLE test1 PASSWORD 'test1test1'; ERROR: password must not contain user name -- 検査を通るパスワード =# CREATE ROLE test1 PASSWORD 'mypass9!'; CREATE ROLE
CrackLibを活用する
マニュアルにもある通り、passwordcheckはCrackLibを使うことで、辞書ベースのパスワード検査を行うこともできます。CrackLibはLinuxやMacOSをはじめ、様々な認証モジュールなどに採用されているパスワード検査用のライブラリです。辞書を元に、入力文字列の検査を高速に行うことができます。ただし、passwordcheckとCrackLibを組み合わせるには、passwordcheckモジュールの再ビルドとCrackLibのインストールが必要になります。以下、CrackLibの導入とpasswordcheckの再ビルドの方法、および簡単な使い方を解説していきます。
CrackLibの導入
では、CrackLibの導入を行っていきましょう。今回は執筆時点(2012年12月)で最新となるcracklibのバージョン2.8.19を使っています。 なお、構築や試行については筆者の環境であるMacOS 10.7で行っていますが、基本的な手順は一般的なLinux環境であれば同じです。
まず、CrackLibのソースコードを入手し、展開します。次に、configureを行います。その際、"--with-default-dict=/usr/lib/cracklib_dict"オプションを指定します。これはCrackLibの辞書が置かれるデフォルト位置を決めるオプションです。"/usr/lib/cracklib_dict"と指定すると、次節の辞書作成コマンド後、"/usr/lib/"配下に"cracklib_dict.pwdなど3種のファイルが生成されます。"もし"/usr/lib"配下に置きたくない場合は別途の場所を指定しても構いません。その場合、passwordcheckモジュールのMakefileの編集時に、指定した場所と同様の記述を行う必要があります。prefixなどのその他オプションについては特に制約はありません。以下はconfigure実行例です。
# cd # ./configure --with-default-dict=/usr/lib/cracklib_dict
configureが終われば、あとはmake && make install をして導入は終わりです。
辞書の作成
次に、CrackLibの辞書を作成します。辞書の作成は、デフォルトでは"/usr/local/sbin/"にインストールされる"create-cracklib-dict"コマンドを使用します。引数には辞書の元となる、単語が羅列されたファイルのパスを指定します。このコマンドは簡単なシェルになっていて、内部で"/usr/local/sbin/"にある他のCrackLibの実行ファイルを呼び出しています。そのため、環境変数のPATHに"/usr/local/sbin"を通しておくと良いです。
では、CrackLibに付随している単語帳を使って辞書を作成してみましょう。単語帳は"/usr/local/share/cracklib/cracklib-small"にあります。cracklib-small を見るとわかりますが、単語帳は1行1単語のシンプルなテキストファイルです。これに独自の単語を追加していくことで、強固な検査が可能な辞書にすることができます。基本的にはこの単語帳とパスワードのマッチングで検査がされます。単語帳にキーワードを追加してみましょう。vi等でファイルを開き、先ほど通したパスワード"mypass9!"を追加します。下記は追加例です。追加位置は末尾でも構いません。
# vi /usr/local/share/cracklib/cracklib-small (省略) myopia myopic myosin mypass9! <--この行を追加 myra myriad (省略)
次に、以下のコマンドを実行すると、configureの"--with-default-dict"で指定した場所に辞書が生成されます。
# /usr/local/sbin/create-cracklib-dict /usr/local/share/cracklib/cracklib-small 49641 49641 # ls /usr/lib/cracklib_dict.* /usr/lib/cracklib_dict.hwm /usr/lib/cracklib_dict.pwd /usr/lib/cracklib_dict.pwi
これでCrakLib側の準備は終わりです。
passwordcheckの再ビルド
では、passwordcheckの再ビルドを行います。$PGSRC/contrib/passwordcheckに移動し、Makefileの編集を行います。以下のPG_CPPFLAGSとSHLIB_LINKの行のコメントアウトを取り払い、有効にします。(幅の制約で改行しています)
(省略) # uncomment the following two lines to enable cracklib support PG_CPPFLAGS = -DUSE_CRACKLIB \ '-DCRACKLIB_DICTPATH="/usr/lib/cracklib_dict"' SHLIB_LINK = -lcrack (省略)
ご覧のとおり、-DCRACKLIB_DICTPATには、CrackLibのconfigureで指定した辞書の配置位置を記述しています。もしCrackLibのconfigureオプションで"/usr/lib/cracklib_dict"以外の場所を指定した場合は、Makefileでの辞書の配置位置を変更する必要があります。
次に、(もし以前にmakeしていればmake cleanをしてから)make && make install を行います。あとはpostgresql.confのshared_preload_librariesパラメータに'passwordcheck'と指定されていることを確認し、PostgreSQLサーバを起動or再起動すればCrackLibが有効になったpasswordcheckが機能します。
CrackLibを試す
では、先ほど通した"mypass9!"を試してみます。すると、以下の様にパスワード指定が弾かれました。
=# CREATE ROLE crack_test PASSWORD 'mypass9!'; ERROR: password is easily cracked
また、CrackLibは辞書ベースの検査の他、単純な数値や文字列の並びや組み合わせを持つものも弾くようになっています。そのため、辞書にはない文字列であっても弾かれることがあります。
なお、CrackLibの辞書に単語を追加した場合は、辞書の再作成とPostgreSQLの再起動を行えば即座に有効になります。
おわりに
いかがでしたでしょうか?passwordcheck自体はシンプルなCのコードなので、ユーザが独自に拡張することも比較的容易です。素の状態でもそれなりのパスワードポリシーを適用できますので、もしDBMSとして弱いパスワードを弾く機能が必要となった場合には利用してみて下さい。