環境
Ubuntu20.4
Postgresql12
はじめに
PostgreSQL10より、ロールにつけるパスワードの暗号化方式で、従来のmd5に加え、scram-sha-256を指定することができるようになりました。
md5にはいくつかの脆弱性が指摘されています。md5は強い意志をもった攻撃に対して安全でないとされています。md5では攻撃者がサーバからパスワードハッシュを盗むことに対して防ぐ手立てがありません。
scram-sha-256が、現在実装されている認証方式の中で、最も安全なアルゴリズムと言われています。セキュリティを強化させるために、md5のデフォルトの設定のままにしている場合は、scram-sha-256に変更した方がいいでしょう。
事前作業
設定ファイルを変更する前に、デフォルトの設定を残しておくために、バックアップを取っておいた方がいいでしょう。
sudo cp /etc/postgresql/12/main/postgresql.conf /etc/postgresql/12/main/postgresql.conf_bkup
sudo cp /etc/postgresql/12/main/pg_hba.conf /etc/postgresql/12/main/pg_hba.conf_bkup
暗号化のアルゴリズムを変更
パスワードの暗号化方式は、デフォルトではmd5になっています。
postgresql.confをみると、デフォルトではコメントになっています。コメントになっていれば、デフォルト値のmd5が有効になっています。
#password_encryption = md5 # md5 or scram-sha-256
コメントを外して設定を変更します。
password_encryption = scram-sha-256 # md5 or scram-sha-256
コメントには、md5またはscram-sha-256を設定するように記載されています。古いバージョンのPostgreSQLでは、passwordという値が設定できるようになっていました。passwordではパスワードは暗号化されずに、平文で保存されていました。現バージョンではpasswordを設定することはできません。あまりにもセキュリティ的に問題があるので外した模様です。
設定した内容を反映させるには、PostgreSQLのサービスを再起動させる必要があります。
$service postgresql restart
設定の確認
PostgreSQLにログインします。因みに、ここでのログインはmd5認証ではなくpeer認証によるログインです。
$sudo su - postgres
$psql
postgresql.confのpassword_encryptionで変更した値が、PostgreSQLに反映されていることを確認するには、つぎのコマンドで確認することができます。
postgres=#show password_encryption;
password_encryption
---------------------
scram-sha-256
(1 row)
動作確認(その1)
ここで問題です。
postgresql.confで、認証のアルゴリズムをmd5からscram-sha-256に変更しました。そして、pg_hba.confで認証タイプはつぎのように、md5のままになっています。
host all all 127.0.0.1/32 md5
この状態で、host接続はできるでしょうか?
答えは「できます。」
ロールのパスワードはmd5でハッシュ化されたままの状態です。pg_hba.confの設定がmd5であれば、md5を使ってチャレンジパスワードがハッシュ化されるからです。
scram-sha-256の設定は、次にロールのパスワードを生成したときから有効になります。scram-sha-256に設定を変更しても、ロールのパスワードを再生成しない限り、md5でハッシュ化されたままの状態になっています。
動作確認(その2)
もうひとつ問題です。
pg_hba.confをmd5からscram-sha-256に変更して、サービスを再起動させて設定を反映させました。
host all all 127.0.0.1/32 scram-sha-256
この状態で、host接続はできるでしょうか?
答えは「できません。」
チャレンジパスワードを入力するとつぎのエラーが表示されます。
$psql -U hoge -d hoge_db -h localhost
Password for user hoge:
psql: error: connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL: password authentication failed for user "hoge"
connection to server at "localhost" (127.0.0.1), port 5432 failed: FATAL: password authentication failed for user "hoge"
ロールのパスワードはmd5でハッシュ化されたままの状態です。host接続しようとすると、チャレンジパスワードはscram-sha-256でハッシュ化されます。md5でハッシュ化したものと、scram-sha-256でハッシュ化したものを比較して認証作業をするので、認証は失敗します。
因みにですが、local接続でpeer認証で接続する場合は、認証が行われないため、postgresql.confの設定がmd5であろうと、scram-sha-256であろうと、関係なく接続できます。
パスワードを作り直す
postgresql.confの設定をmd5からscram-sha-256に変更して、pg_hba.confの認証タイプもmd5からscram-sha-256に変更しました。次にやることは、md5でハッシュ化されているロールを、すべて、scram-sha-256でハッシュ化させて作り直すことです。
PostgreSQLにログインします。
$sudo su - postgres
$psql
pg_authidのデータカタログで、パスワードが設定されているロールの一覧を確認することができます。ハッシュ化されたパスワードはrolpasswordカラムに更新されています。
postgres=#select * from pg_authid; # すべてのカラムを表示
postgres=#select rolname, rolpassword from pg_authid; # ロール名とパスワードを表示
すべてのロールに対して、scram-sha-256でハッシュ化させたパスワードに変更します。
postgres=#ALTER ROLE hoge_user1 WITH PASSWORD 'hoge_user1_password';
同じ長さのパスワードをmd5とscram-sha-256でそれぞれハッシュ化させた結果です。見ての通りハッシュの長さがこれだけ違います。やはりscram-sha-256の方がmd5と比べて圧倒的に強力です。
md5でハッシュ化した結果
hoge | md5ce5f2d27bc6276a03b0328878c1dc0e2
scram-sha-256でハッシュ化した結果
hoge | SCRAM-SHA-256$4096:855fLdHvpeSqPT/MaeoMGQ==$Mv4RTDu+WYy83hs48Zwr1cBtoobIU9EkFaPVaQK+QCg=:GrVQoMdFdaSGtsx7WF7M30Jm9npheaDYuIBNm7fabiA=
scram-sha-256でロールのパスワードを作り直した後、host接続をすると、今度はちゃんと認証に成功します。
動作確認(その3)
もうひとつ変なことをします。
postgresql.confでmd5ではなくscram-sha-256に設定されています。ロールのパスワードをscram-sha-256でハッシュ化して再設定をしました。そして、pg_hba.confで認証タイプを、scram-sha-256ではなくmd5で設定しました。
host all all 127.0.0.1/32 md5
この状態でhost接続はできるでしょうか。
pg_hba.confで認証タイプをmd5にしているということは、チャレンジパスワードはmd5でハッシュ化されます。そして、scram-sha-256でハッシュ化されたパスワードと比較されるため、認証は成功するはずがない思われるでしょう。
しかし、この設定でもhost接続はできてしまいます。
なぜか?
ロールのパスワードがscram-sha-256でハッシュ化されていた場合、pg_hba.confの設定がmd5になっていても、実は、チャレンジパスワードは、md5ではなく、scram-sha-256でハッシュ化して認証するといった仕様になっているからです。
えーっ!、うそーっ!と思われるかも分かりませんが、現に公式ドキュメントにそのように書かれています。こちらのリンクがその証拠です。自分も実際に試してみて、その通りに動作しました。
このような仕様になっているからといって、pg_hba.confの設定をmd5のままにしておくのではなく、明示的にscram-sha-256で設定してしておいた方が、後々、管理の面において混乱を起こさないことになるのでいいかとは思います。