説明
パスワードを平文で保存すると、保存先の侵害時にそのまま漏えいします。MD5、SHA-1、単純なSHA-256などの高速なハッシュでは、攻撃者が流出したハッシュに対して多数のパスワード候補を短時間で試せます。
想定される影響
許可されていないアクセス
復元されたパスワードを使われると、アカウントへの侵入、データの漏えい、なりすまし、不正取引などにつながるおそれがあります。
パスワードの使い回し
同じパスワードを他のサービスでも使っている場合、それらのアカウントも侵害される可能性があります。
法令や規制への不適合
パスワードの保護が不十分だと、適用されるデータ保護要件に反し、サービスへの信頼を損なう場合があります。
対処方法
- パスワード専用のハッシュ方式を使用してください。 平文では保存せず、新しいシステムではArgon2idを優先してください。既存のbcryptやPBKDF2にも十分な処理コストを設定し、サーバー性能に合わせて調整してください。
- パスワードごとに新しいランダムなソルトを使用してください。 計算済みの結果を複数のハッシュに使い回すことを防ぎます。ソルトはハッシュと一緒に保存できますが、パスワードの推測そのものは防げません。
- 必要な場合はFIPS-140要件を満たしてください。 検証済みの暗号モジュールでPBKDF2-HMAC-SHA256を使用し、600,000回以上を基準に処理コストを設定してください。アルゴリズム名だけで実装が認証されるわけではありません。
例
変更前
Spring Security 5.8形式のJDBC認証設定の抜粋です。クエリがユーザー名、パスワードハッシュ、有効状態を必要な順序で返すスキーマを前提とします。
java
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT * FROM users WHERE username = ?")
.passwordEncoder(new StandardPasswordEncoder()); // パスワード保存には弱いハッシュ
}
変更後
java
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT * FROM users WHERE username = ?")
.passwordEncoder(new BCryptPasswordEncoder()); // 計算コストを調整できるbcryptを使用
}
解説:
- 変更前: 旧方式の
StandardPasswordEncoderはSHA-256を1,024回繰り返します。ソルトがあっても、パスワード保存に十分な計算コストにはなりません。 - 変更後: bcryptの処理コストを調整して推測を難しくします。パスワードの長さ制限と性能を確認し、既存のハッシュはログイン時の再ハッシュやパスワード再設定で移行してください。エンコーダーの交換だけでは、保存済みハッシュは変換されません。
参考資料
- CWE-256 — パスワードの平文保存
- CWE-916 — パスワードハッシュの計算コスト不足
- OWASP Password Storage Cheat Sheet
- Spring Security BCryptPasswordEncoder ドキュメント
- Spring Security 5.8.16
StandardPasswordEncoder