MD5による脆弱なパスワードハッシュ

MD5による脆弱なパスワードハッシュ

説明

MD5のように計算が速いハッシュでパスワードを保存すると、データベースの漏えい後に多くの候補を短時間で試される可能性があります。ハッシュを復号するのではなく、候補のハッシュを比較する攻撃です。固有のソルトがなければ、事前計算したハッシュの一覧や利用者間のハッシュ比較も利用されます。

想定される影響

  • 高速なオフライン推測でパスワードが判明するおそれがあります。
  • 判明したパスワードでアカウントに不正アクセスされる可能性があります。

対処方法

  • パスワードの保存にMD5やSHA-1などの高速なハッシュを使わないでください。
  • 保守されているArgon2idやscryptの実装を使ってください。既存のbcryptを維持する場合は、入力長の制限と環境に適した計算コストを確認してください。
  • ライブラリに固有のソルトを生成させ、コストの設定をハッシュとともに保存してください。ソルトは事前計算や同じパスワードのハッシュ比較を難しくしますが、ハッシュ衝突を防ぐものではありません。

例

変更前

javascript
const crypto = require('crypto');

function setUserPassword(user, pwtext) {
  const hash = crypto.createHash('md5').update(pwtext).digest('hex');
  user.setPassword(hash);
}

変更後

javascript
const bcrypt = require('bcrypt');

function setUserPassword(user, pwtext) {
  const saltRounds = 12; // コストの例: サービス環境に合わせて調整
  bcrypt.hash(pwtext, saltRounds, function(err, hash) {
    if (err) throw err;
    user.setPassword(hash);
  });
}

変更前は計算の速いMD5を固有のソルトなしで使うため、多くの候補を低コストで試せます。変更後はbcryptがソルトを生成し、計算コストを設定して推測の負担を増やします。例の12が常に適切とは限りません。環境に合わせて調整し、72バイトの入力制限に対処してください。ハッシュ生成の失敗は、アプリケーションのエラー処理に渡してください。

参考資料