認証の安全性
この章では、認証(ログイン)そのものの安全性を担保する方法について見ていきます。
パスワードの保存
ウェブの認証で最も広く使われているのは、ID とパスワードの組み合わせです。サーバーは「入力されたパスワードが、登録されているものと一致するか」を見る必要があります。
ここでパスワードをそのまま(平文で)保存してはいけません。データベースが漏えいした瞬間に、すべてのアカウントが乗っ取られます。可逆な暗号化も、暗号鍵が同じシステム上にあれば、鍵ごと持っていかれたときに同じ結末になります。
そこで使うのが ハッシュ です。一方向の変換なので、保存値から元のパスワードを復元できません。ログイン時は、入力されたパスワードを同じ手順でハッシュし、保存値と一致するかを見ます。
ただし、計算が速いハッシュだと、攻撃者は漏えいしたハッシュに対して大量の候補を試せます。また、同じパスワードは同じハッシュになるため、「よく使われるパスワードの対応表」(レインボーテーブル)で一括解読されてしまいます。
これを防ぐのが salt・pepper・stretching と呼ばれる各手法です。現代のシステムではこれらをすべて用いるのが一般的です。
salt(ソルト)
ユーザーごとに異なるランダムな値を、ハッシュの入力に混ぜます。同じパスワードでも人によってハッシュが変わるため、レインボーテーブルが使えなくなります。
salt は秘密である必要はなく、ハッシュと一緒にデータベースへ保存します。これが問題ないのは、salt の目的が「全員に同じテーブルを使わせない」ことだからです。
pepper(ペッパー)
pepper はサーバーだけが知る秘密の値です。salt と違い、データベースには置きません。
データベースだけが漏えいしても、pepper が無ければハッシュを再現できません。
stretching(ストレッチング)
平文をハッシュ値に変換するときに、ハッシュ関数を1回だけ通すのではなく、何回も繰り返しハッシュ関数に通します(ハッシュのハッシュのハッシュ... を計算します。)。
これにより、ハッシュ値を求めるために必要な計算量が増えるため、攻撃者が解読するための計算量を増やすことができます。
| 仕組み | 防ぐこと |
|---|---|
| salt | 同一パスワードが同一ハッシュになること、レインボーテーブル |
| pepper | DB を盗まれたときにハッシュを再現できること |
| stretching | 1 回の推測を安く試せること |
Nogiku のパスワード保存
Nogiku Auth は、ユーザーごとの salt にサーバー側の秘密(pepper)を組み合わせ、反復回数をかけたハッシュとしてパスワードを保存しています。
漏洩パスワード(HIBP)
ハッシュを強化していても、ユーザーが「別のサービスで漏れたパスワードを使いまわしている」ような状況では無意味です。
Have I Been Pwned(HIBP)は、過去の漏えいデータにそのパスワードが含まれているかを調べられる仕組みです。パスワード登録時や変更時に HIBP への問い合わせを行うことで、使い回された既知のパスワードをブロックすることができます。
HIBP では、パスワードを SHA-1 ハッシュした結果の先頭数文字のみを HIBP サーバーに送信することで、実際のパスワードを送信することに漏えい状況を確認できる「k-Anonymity」という仕組みが採用されています。
Nogiku での漏洩パスワード検査
Nogiku Auth は本番環境で、Have I Been Pwned を使った漏洩パスワードの検査を行います。
二段階認証(2FA)
認証防御では、複数要素を組み合わせることで安全性を飛躍的に向上させることができます。
二段階認証(2FA, Two-Factor Authentication)では、パスワードに加えて別のカテゴリの要素(所持しているものなど)を要求します。
TOTP
よく使われるのが TOTP(Time-based One-Time Password)です。サーバーと認証アプリが同じ秘密鍵を共有し、現在時刻から短い数字のコードを生成します。サインイン時にこのコードを入力します。
フィッシング
TOTP はパスワードの漏えいに対する防御策にはなりますが、根本的にフィッシングに弱いという点は共通です。
フィッシング では、正規のログイン画面に似せた偽サイトへユーザーを誘導し、そこで認証情報を入力させようとします。被害者が偽サイトにパスワードと TOTP コードの両方を入力すると、攻撃者はその場で正規の IdP に転送してログインできます。コードは数十秒で変わるため、リアルタイムで中継すれば間に合います。
この問題は、TOTP が「今この画面が本物か」を検証できていないことに起因しています。
パスキー(WebAuthn)
パスキー は、フィッシングに耐えるための認証方式です。内部では WebAuthn という公開鍵暗号の規格が使われています。
登録時、端末(またはパスワードマネージャ)が鍵ペアを作り、公開鍵だけを IdP に渡します。秘密鍵は端末側に残り、サーバーには送られません。サインイン時、IdP は挑戦値(challenge)を送り、端末が秘密鍵で署名して返します。
重要なのは、この署名が そのサイトの origin(ドメイン)に紐づく ことです。偽サイトは正規の origin ではないため、秘密鍵は署名しません。パスワードや TOTP のように「画面の入力欄に打ち込む」情報ではないので、偽サイトへ転送する攻撃が成立しにくくなります。
また、誤解されやすい点ですが、指紋や顔は多くの場合「端末上の秘密鍵を使うためのロック解除」であり、生体情報が IdP に送られるわけではありません。
Nogiku の認証手段
Nogiku Auth はパスワードに加え、TOTP による二段階認証とパスキーを提供しています。