パート I: ログイン方法
認証のためにサーバー側のスクリプトに値を POST する、ログインとパスワードの HTML フォームを作成する方法を既に知っていると仮定します。以下のセクションでは、健全で実用的な認証のパターンと、最も一般的なセキュリティの落とし穴を回避する方法について説明します。
HTTPS にするか、HTTPS にしないか?
接続がすでに保護されていない限り (つまり、SSL/TLS を使用して HTTPS を介してトンネリングされていない場合)、ログイン フォームの値はクリアテキストで送信されます。これにより、ブラウザーと Web サーバーの間の回線を盗聴した人は、通過するログインを読み取ることができます。終えた。この種の盗聴は政府によって日常的に行われていますが、一般的には、「所有されている」ワイヤについては、「HTTPS を使用してください」と言う以外には対処しません。
本質的に、ログイン中の盗聴/パケット スニッフィングから保護する唯一の実用的な方法は、HTTPS または別の証明書ベースの暗号化スキーム (たとえば、TLS )、または実証済みでテスト済みのチャレンジ/レスポンス スキーム (たとえば、Diffie-Hellmanベースの SRP)。他の方法は、盗聴攻撃者によって簡単に回避できます。
もちろん、少し非現実的になりたい場合は、何らかの形式の 2 要素認証スキームを採用することもできます (たとえば、Google Authenticator アプリ、物理的な「冷戦スタイル」のコードブック、または RSA キー ジェネレーター ドングル)。正しく適用されれば、セキュリティで保護されていない接続でも機能する可能性がありますが、開発者が SSL ではなく 2 要素認証を喜んで実装するとは想像しがたいです。
(しないでください) 独自の JavaScript 暗号化/ハッシュ化
Web サイトに SSL 証明書を設定するコストと技術的な難しさを考えると (現在は回避可能ですが)、一部の開発者は、セキュリティで保護されていないワイヤを介してクリアテキスト ログインを渡すことを回避するために、独自のブラウザー内ハッシュまたは暗号化スキームを展開するように誘惑されます。
これは高尚な考えですが、上記のいずれか、つまり、強力な暗号化で回線を保護するか、実証済みのチャレンジ/レスポンスを使用することのいずれかと組み合わせない限り、本質的に役に立ちません (また、セキュリティ上の欠陥になる可能性があります)。 (それが何であるかわからない場合は、証明するのが最も難しく、設計が最も難しく、デジタル セキュリティの概念を実装するのが最も難しいものの 1 つであることを知っておいてください)。
パスワードのハッシュ化がパスワードの開示に対して効果的であることは事実ですが、リプレイ攻撃、中間者攻撃/ハイジャックに対して脆弱です (攻撃者がセキュリティで保護されていない HTML ページに到達する前に数バイトを挿入できる場合)。 JavaScript のハッシュをコメント アウトするだけです)、またはブルート フォース攻撃 (攻撃者にユーザー名、salt、およびハッシュ化されたパスワードの両方を渡しているため)。
人道に対するCAPTCHAS
CAPTCHAは、特定のカテゴリの攻撃を阻止することを目的としています。それは、人間のオペレーターがいない、自動化された辞書/ブルート フォースの試行錯誤です。これが本当の脅威であることは間違いありませんが、CAPTCHA を必要とせずにシームレスに対処する方法、特に適切に設計されたサーバー側のログイン スロットリング スキームがあります。これらについては後で説明します。
CAPTCHA の実装は同じようには作成されないことに注意してください。多くの場合、人間が解決することはできず、実際にはほとんどがボットに対して効果がなく、すべてが安価な第三世界の労働力に対して効果がありません ( OWASPによると、現在のスウェットショップ率は 500 テストあたり 12 ドルです)。一部の国では技術的に違法です ( OWASP Authentication Cheat Sheetを参照)。CAPTCHA を使用する必要がある場合は、Google のreCAPTCHAを使用してください。これは、定義上 OCR が難しく (既に OCR で誤って分類された書籍のスキャンを使用しているため)、ユーザーフレンドリーになるように非常に努力しているためです。
個人的には、私は CAPTCHAS が煩わしいと感じる傾向があり、ユーザーが何度もログインに失敗し、スロットリングの遅延が限界に達した場合の最後の手段としてのみ使用します。これは、許容できるほどめったに発生せず、システム全体を強化します。
パスワードの保存 / ログインの確認
これは、ここ数年で大々的に報道されたハッキングやユーザー データの漏えいにより、ようやく一般に知られるようになったかもしれませんが、データベースにパスワードを平文で保存しないでください。ユーザー データベースは、SQL インジェクションによって日常的にハッキング、リーク、または収集されます。未加工の平文のパスワードを保存している場合、ログイン セキュリティは即座にゲーム オーバーになります。
パスワードを保存できない場合、ログイン フォームから POST されたログインとパスワードの組み合わせが正しいことを確認するにはどうすればよいでしょうか。答えは、キー派生関数を使用したハッシュです。新しいユーザーが作成されるか、パスワードが変更されるたびに、パスワードを取得し、Argon2、bcrypt、scrypt、または PBKDF2 などの KDF を介して実行し、クリアテキストのパスワード (「correcthorsebatterystaple」) を長いランダムに見える文字列に変換します。これは、データベースに保存する方がはるかに安全です。ログインを確認するには、入力したパスワードに対して同じハッシュ関数を実行します。今回はソルトを渡し、結果のハッシュ文字列をデータベースに保存されている値と比較します。Argon2、bcrypt、および scrypt は、ハッシュとともにソルトを保存します。詳細については、sec.stackexchange に関するこの記事を参照してください。
ソルトが使用される理由は、ハッシュ自体が十分でないためです。レインボー テーブルからハッシュを保護するために、いわゆる「ソルト」を追加する必要があります。ソルトは、正確に一致する 2 つのパスワードが同じハッシュ値として保存されるのを効果的に防ぎ、攻撃者がパスワード推測攻撃を実行している場合にデータベース全体が 1 回の実行でスキャンされるのを防ぎます。
ユーザーが選択したパスワードは十分な強度がなく (つまり、通常、十分なエントロピーが含まれていない)、パスワード推測攻撃は、ハッシュにアクセスできる攻撃者によって比較的短時間で完了する可能性があるため、暗号化ハッシュをパスワード ストレージに使用しないでください。これが KDF が使用される理由です。これらは効果的に「キーをストレッチ」します。つまり、攻撃者がパスワードを推測するたびに、ハッシュ アルゴリズムが複数回 (たとえば 10,000 回) 繰り返され、攻撃者がパスワードを推測する速度が 10,000 倍遅くなります。
セッション データ - 「Spiderman69 としてログインしています」
サーバーがユーザー データベースに対してログインとパスワードを検証し、一致するものを見つけたら、システムにはブラウザーが認証されたことを記憶する方法が必要です。この事実は、サーバー側のセッション データにのみ保存する必要があります。
セッション データに慣れていない場合は、次のように動作します。ランダムに生成された単一の文字列が期限切れの Cookie に格納され、サーバーに格納されているデータのコレクション (セッション データ) を参照するために使用されます。MVC フレームワークを使用している場合、これは間違いなく既に処理されています。
可能な限り、セッション Cookie がブラウザーに送信されるときに、セキュアおよび HTTP のみのフラグが設定されていることを確認してください。HttpOnly フラグは、XSS 攻撃によって読み取られる Cookie に対する保護を提供します。secure フラグは、Cookie が HTTPS 経由でのみ送り返されることを保証するため、ネットワーク スニッフィング攻撃から保護します。Cookie の値は予測可能であってはなりません。存在しないセッションを参照する Cookie が提示された場合、セッションの固定化を防ぐために、その値をすぐに置き換える必要があります。
セッション状態は、クライアント側でも維持できます。これは、JWT (JSON Web Token) などの手法を使用して実現されます。
パート II: ログイン状態を維持する方法 - 悪名高い "Remember Me" チェックボックス
永続的なログイン Cookie (「記憶」機能) は危険ゾーンです。一方では、ユーザーがそれらの処理方法を理解していれば、従来のログインとまったく同じくらい安全です。その一方で、不注意なユーザーが公共のコンピューターで使用してログアウトするのを忘れたり、ブラウザーの Cookie とは何か、またはそれらを削除する方法を知らない可能性があるため、これらは非常に大きなセキュリティ リスクとなります。
個人的には、定期的にアクセスする Web サイトへの永続的なログインが好きですが、それらを安全に処理する方法を知っています。ユーザーが同じことを知っていると確信している場合は、良心的に永続的なログインを使用できます。そうでない場合は、ログイン資格情報を不注意に使用しているユーザーがハッキングされた場合に自分自身でそれをもたらしたという哲学に同意することができます. ユーザーの家に行って、モニターの端に並べられたパスワード付きの手のひらを誘発する付箋をすべて破るわけでもありません。
もちろん、システムによっては、アカウントをハッキングする余裕がないものもあります。そのようなシステムでは、永続的なログインを正当化する方法はありません。
永続的なログイン Cookie を実装することに決めた場合は、次のようにします。
まず、このテーマに関するParagon Initiative の記事を読んでください。一連の要素を正しく理解する必要がありますが、この記事ではそれぞれの要素をうまく説明しています。
最も一般的な落とし穴の 1 つを繰り返しますが、永続的なログイン Cookie (トークン) をデータベースに保存しないでください。ハッシュのみを保存してください。ログイン トークンはパスワードと同等であるため、攻撃者がデータベースを手に入れた場合、平文のログイン パスワードの組み合わせであるかのように、トークンを使用して任意のアカウントにログインできます。したがって、永続的なログイン トークンを保存する場合は、ハッシュを使用します ( https://security.stackexchange.com/a/63438/5002によると、この目的には弱いハッシュでも問題ありません)。
パート III: 秘密の質問の使用
「秘密の質問」を実装しないでください。「秘密の質問」機能は、セキュリティのアンチパターンです。MUST-READ リストのリンク番号 4 から論文を読んでください。彼女の Yahoo! 彼女の秘密の質問への答えが「ワシラ高校」だったため、以前の大統領選挙中にメールアカウントがハッキングされました!
ユーザー指定の質問であっても、ほとんどのユーザーは次のいずれかを選択する可能性が非常に高くなります。
母親の旧姓や好きなペットなどの「標準的な」秘密の質問
誰でも自分のブログや LinkedIn のプロフィールなどから取り上げることができる簡単なトリビア
パスワードを推測するよりも答えやすい質問。まともなパスワードの場合、どれが想像できるすべての質問です
結論として、セキュリティの質問は、事実上すべての形式とバリエーションで本質的に安全ではないため、何らかの理由で認証方式に使用するべきではありません。
セキュリティに関する質問が広まっている本当の理由は、電子メールにアクセスできないユーザーからの数回のサポート コールのコストを便利に節約できるためです。これは、セキュリティとサラ ペイリンの評判を犠牲にして行われました。価値がある?おそらくそうではありません。
パート IV: パスワードを忘れた場合の機能
忘れた/紛失したユーザーパスワードを処理するためにセキュリティの質問を使用してはならない理由については、既に説明しました。言うまでもなく、ユーザーに実際のパスワードを電子メールで送信してはいけません。この分野で避けるべき、あまりにも一般的な落とし穴が少なくともあと 2 つあります。
忘れたパスワードを自動生成された強力なパスワードにリセットしないでください。このようなパスワードは覚えにくいことで有名です。つまり、ユーザーはパスワードを変更するか、モニターの端にある明るい黄色のポストイットなどに書き留めておく必要があります。新しいパスワードを設定する代わりに、ユーザーがすぐに新しいパスワードを選択できるようにします。これはとにかくやりたいことです。(これに対する例外は、ユーザーが一般的にパスワード マネージャーを使用して、通常は書き留めないと覚えられないパスワードを保存/管理している場合です)。
データベース内の失われたパスワード コード/トークンを常にハッシュします。繰り返しますが、このコードは同等のパスワードの別の例であるため、攻撃者がデータベースを手に入れた場合に備えてハッシュする必要があります。紛失したパスワード コードが要求されたら、平文のコードをユーザーのメール アドレスに送信し、それをハッシュして、ハッシュをデータベースに保存し、元の を破棄します。パスワードや永続的なログイン トークンと同様です。
最後の注意: 「失われたパスワード コード」を入力するためのインターフェイスが、少なくともログイン フォーム自体と同じくらい安全であることを常に確認してください。非常に長い「失われたパスワード コード」 (たとえば、大文字と小文字を区別する 16 文字の英数字) を生成することを確認することは良い出発点ですが、ログイン フォーム自体に対して行うのと同じスロットリング スキームを追加することを検討してください。
パート V: パスワード強度の確認
まず、現実を確認するために、次の小さな記事をお読みください: The 500 most common passwords
さて、このリストは、どこのシステムでも最も一般的なパスワードの標準的なリストではないかもしれませんが、強制的なポリシーがない場合、人々がパスワードをどれだけうまく選択しないかを示す良い指標です. さらに、最近盗まれたパスワードの一般公開されている分析と比較すると、リストは驚くほど身近に見えます。
したがって、パスワード強度の最小要件がないため、ユーザーの 2% が最も一般的な上位 20 個のパスワードのいずれかを使用しています。つまり、攻撃者が 20 回試行しただけで、Web サイトの 50 分の 1 のアカウントがクラック可能になります。
これを阻止するには、パスワードのエントロピーを計算してから、しきい値を適用する必要があります。米国国立標準技術研究所 (NIST)のSpecial Publication 800-63には、一連の非常に優れた提案があります。これを辞書とキーボード レイアウトの分析 (たとえば、「qwertyuiop」は不適切なパスワード) と組み合わせると、不適切に選択されたすべてのパスワードの 99%を 18 ビットのエントロピーのレベルで拒否できます。パスワードの強度を計算し、視覚強度メーターをユーザーに表示するだけでも十分ですが、不十分です。強制されない限り、多くのユーザーはそれを無視するでしょう。
また、エントロピーの高いパスワードの使いやすさを一新するために、Randall Munroe のPassword Strength xkcdを強くお勧めします。
Troy Hunt のHave I Been Pwned APIを利用して、ユーザーのパスワードと公開データ侵害で侵害されたパスワードを照合します。
パート VI: その他 - または: 連射ログイン試行の防止
まず、数値を見てみましょう:パスワード回復速度 - パスワードが有効になる時間
そのリンクの表を確認する時間がない場合は、次のリストを参照してください。
そろばんで解読しても、脆弱なパスワードを解読するのにほとんど時間はかかりません
大文字と小文字が区別されない場合、英数字 9 文字のパスワードを解読するのにほとんど時間がかかりません
複雑な記号と文字と数字の大文字と小文字のパスワードを8 文字未満で解読するのに、ほとんど時間はかかりません(デスクトップ PC は、問題で最大 7 文字までのキースペース全体を検索できます)。数日または数時間)
ただし、 1 秒間に 1 回の試行に制限されていると、6 文字のパスワードを解読するのに非常に長い時間がかかります。
では、これらの数字から何を学べるでしょうか。まあ、たくさんありますが、最も重要な部分に焦点を当てることができます: 大量の連続した連射ログイン試行 (ブルート フォース攻撃) を防ぐことはそれほど難しくないという事実です。しかし、それを正しく防ぐことは、思ったほど簡単ではありません。
一般的に言えば、ブルート フォース攻撃(および辞書攻撃ですが、既に強力なパスワード ポリシーを採用しているため、これらは問題にはなりません)に対してすべて効果的な 3 つの選択肢があります。
N 回失敗した後にCAPTCHAを表示します (非常に面倒で、効果がないことが多いですが、ここで繰り返します)。
アカウントをロックし、N 回失敗した後に電子メールの確認を要求する (これは発生するのを待っているDoS攻撃です)
そして最後に、ログインスロットリング: つまり、N 回失敗した後の試行間に時間遅延を設定します (はい、DoS 攻撃は依然として可能ですが、少なくとも可能性ははるかに低く、実行するのははるかに複雑です)。
ベスト プラクティス #1: 次のように、失敗した試行の数に応じて増加する短い時間の遅延:
- 1 回失敗 = 遅延なし
- 2 回失敗 = 2 秒の遅延
- 3 回失敗 = 4 秒の遅延
- 4 回失敗 = 8 秒の遅延
- 5 回失敗 = 16 秒の遅延
- 等
結果として生じるロックアウト時間は、以前のロックアウト時間の合計よりもわずかに長くなるため、このスキームを攻撃する DoS は非常に非現実的です。
明確にするために: 遅延は、ブラウザーに応答を返す前の遅延ではありません。これは、特定のアカウントまたは特定の IP アドレスからのログイン試行がまったく受け入れられない、またはまったく評価されない、タイムアウトまたは不応期のようなものです。つまり、ログインが成功しても正しい資格情報は返されず、誤った資格情報によって遅延が増加することはありません。
ベスト プラクティス #2: 次のように、N 回の試行が失敗した後に有効になる中程度の長さの遅延時間:
- 1 ~ 4 回の失敗 = 遅延なし
- 試行に 5 回失敗 = 15 ~ 30 分の遅延
このスキームを攻撃する DoS は非常に非現実的ですが、確実に実行可能です。また、このような長い遅延は、正当なユーザーにとって非常に迷惑になる可能性があることに注意してください。忘れっぽいユーザーはあなたを嫌うでしょう。
ベスト プラクティス #3: 2 つのアプローチを組み合わせます。
- 1 ~ 4 回の失敗 = 遅延なし
- 5 回以上試行に失敗 = 20 秒の遅延
または、次のように、上限が固定された遅延の増加:
- 1 回失敗 = 5 秒の遅延
- 2 回失敗 = 15 秒の遅延
- 3 回以上の失敗 = 45 秒の遅延
この最終的なスキームは、OWASP のベスト プラクティスの提案 (MUST-READ リストのリンク 1) から取られたものであり、制限的な側面が認められたとしても、ベスト プラクティスと見なされるべきです。
ただし、経験則として、パスワード ポリシーが強力であればあるほど、遅延でユーザーを悩ませる必要が少なくなります。強力な (大文字と小文字を区別する英数字 + 必要な数字と記号) 9 文字以上のパスワードが必要な場合は、スロットリングを有効にする前に、遅延のないパスワードの試行をユーザーに 2 ~ 4 回与えることができます。
この最終的なログイン スロットリング スキームを攻撃する DoS 攻撃は、非常に現実的ではありません。そして最後の仕上げとして、永続的な (Cookie) ログイン (および/または CAPTCHA で検証されたログイン フォーム) の通過を常に許可することで、正当なユーザーが攻撃の進行中に遅延することさえありません。そうすれば、非常に非現実的な DoS 攻撃が、非常に非現実的な攻撃になります。
さらに、管理者アカウントは最も魅力的なエントリ ポイントであるため、管理者アカウントに対してより積極的な調整を行うことは理にかなっています。
パート VII: 分散型ブルート フォース攻撃
余談ですが、より高度な攻撃者は、「活動を広げる」ことでログイン スロットリングを回避しようとします。
ボットネットで試行を分散して IP アドレスのフラグ付けを防止する
1 人のユーザーを選んで 50.000 の最も一般的なパスワードを試すのではなく (私たちのスロットリングのためにそれはできません)、彼らは最も一般的なパスワードを選び、代わりに 50.000 のユーザーに対して試します。そうすれば、CAPTCHA やログイン スロットリングなどの最大試行回数対策を回避できるだけでなく、成功の可能性も高まります。
ユーザー アカウントごとにログイン リクエストを間隔をあけて (たとえば 30 秒間隔で) レーダーの下に忍び込ませる
ここでのベスト プラクティスは、システム全体で失敗したログインの数をログに記録し、すべてのユーザーに課す上限の基礎としてサイトの不正ログイン頻度の移動平均を使用することです。
抽象的すぎる?言い換えてみましょう:
あなたのサイトでは、過去 3 か月間、1 日あたり平均 120 回の不正なログインがあったとします。それ(移動平均)を使用すると、システムはグローバル制限をその3倍に設定する可能性があります。24 時間で 360 回の失敗。次に、すべてのアカウントで失敗した試行の合計数が 1 日以内にその数を超えた場合 (または、加速率を監視し、計算されたしきい値でトリガーした場合)、システム全体のログイン スロットリングがアクティブになります。つまり、すべてのユーザーに対して短い遅延が発生します。 (ただし、Cookie ログインおよび/またはバックアップ CAPTCHA ログインを除く)。
また、分散型ブルート フォース攻撃をかわす際のトリッキーな落とし穴を回避する方法について、より詳細な質問と非常に良い議論を投稿しました。
パート VIII: 二要素認証と認証プロバイダー
エクスプロイト、パスワードの書き留めや紛失、鍵付きのラップトップの盗難、ユーザーによるフィッシング サイトへのログインなどによって、資格情報が侵害される可能性があります。ログインは、通話、SMS メッセージ、アプリ、またはドングルから受信した使い捨てコードなどの帯域外要素を使用する 2 要素認証でさらに保護できます。複数のプロバイダーが 2 要素認証サービスを提供しています。
認証は、別のプロバイダーが資格情報の収集を処理するシングル サインオン サービスに完全に委任できます。これにより、信頼できるサードパーティに問題がプッシュされます。Google と Twitter はどちらも標準ベースの SSO サービスを提供していますが、Facebook は同様の独自ソリューションを提供しています。
必読のリンク Web 認証について
- 認証の OWASP ガイド/ OWASP 認証チート シート
- Web でのクライアント認証のすべきこととすべきでないこと (非常に読みやすい MIT の研究論文)
- ウィキペディア: HTTP クッキー
- フォールバック認証のための個人的な知識の質問: Facebook の時代におけるセキュリティの質問 (非常に読みやすいバークレーの研究論文)