web-dev-qa-db-ja.com

リファレンス-パスワード検証

かなり頻繁に、質問(特に regex とタグ付けされたもの)は、パスワードをvalidateする方法を尋ねます。ユーザーは通常、パスワードに特定の文字が含まれていること、特定のパターンに一致すること、および/または最小文字数に従うことから成るパスワード検証方法を求めているようです。この投稿は、セキュリティを大幅に低下させることなく、ユーザーがパスワード検証に適切な方法を見つけられるようにすることを目的としています。

質問は次のとおりです。どのように適切にパスワードを検証する必要がありますか?

30
ctwheels

Dilbert comic strip for Mordac, the preventer of information services

パスワード検証ルールが悪いのはなぜですか?

私たち自身のJeff Atwood( Coding Horror のブロガーであり、Stack OverflowとStack Exchangeの共同設立者)は、2017年3月に Password Rules are Bullshit というタイトルのパスワードルールに関するブログを書きました=。この投稿を読んでいない場合は、この投稿の意図を大きく反映しているので、ぜひ読んでください。

NIST(National Institute of Standards and Technology) について聞いたことがない場合は、プロジェクトに正しいサイバーセキュリティ手法を使用していない可能性があります。その場合は、 デジタルアイデンティティガイドライン をご覧ください。また、サイバーセキュリティのベストプラクティスについて最新の状態に保つ必要がありますNIST Special Publication 800-63B(Revision 3) は、パスワードルールについて次のことに言及しています。

検証者は、記憶されたシークレットに他の構成ルールを課すべきではありません(異なるキャラクタータイプの混合を要求したり、連続して繰り返されるキャラクターを禁止したり)。

フォームデータの検証 のMozillaのドキュメントでさえ、パスワードルールを楽しんでいます( ページアーカイブはこちら ):

「パスワードは8〜30文字で、大文字、記号、数字を1つずつ含む必要があります」(まじで?)

パスワードの構成規則を課すとどうなりますか?あなたは、潜在的なパスワードの数を制限し、ルールに一致しないパスワード順列を削除しています。これにより、ハッカーは攻撃を確実に同じにすることができます! "はい、しかし、四兆(1,000,000,000,000,000または1x1015)パスワードの置換」25-GPUクラスターは、6時間以内にすべての標準Windowsパスワードをクラックします (958 = 6,634,204,312,890,625〜6.6x1015 パスワード)。

xkcd このStackExchange Securityの投稿 は、上記のXKCDコミックを拡張します。

パスワードを検証するにはどうすればよいですか?

1.独自の認証を作成しないでください

パスワードの要求を完全に停止し、Google、Facebook、Twitter、Yahoo、またはその他の有効な形式の インターネット運転免許証)でログインできるようにします あなたが慣れていること。最適なパスワードは 保存する必要のないパスワード です。

ソース: パスワードが短すぎます Jeff Atwood。

2.独自の認証を作成する

あなたが本当にあなた自身の認証方法を作成しなければならない場合、少なくとも実証済みのサイバーセキュリティ方法に従ってください。次の2つのセクション(2.1および2.2)は、 現在のNIST出版物 、セクション 5.1.1.2記憶された秘密検証者 から引用したものです。

2.1。実績のあるサイバーセキュリティ手法に従う

NISTでは、[〜#〜] should [〜#〜]

  • 加入者が選択した記憶シークレットには、少なくとも8文字の長さが必要です。
    • ジェフアトウッドは、パスワードは通常のユーザーの場合は最低10文字、より高い権限を持つユーザー(管理者とモデレーター)の場合は最低15文字にすることを提案しています。
  • 加入者が選択した最大64文字以上の暗記を許可します。
    • 理想的には、これに上限を設けるべきではありません。
  • すべての印刷を許可ASCII(スペース文字を含む)およびUnicode。
    • 長さの要件のために、各Unicodeコードポイントは単一の文字としてカウントされる必要があります。
  • 一般的に使用される、予想される、または危殆化されることが知られている値を含むリストに対して、予想される秘密を比較します。例えば:
    • 以前の侵害コーパスから取得したパスワード。
    • 辞書の言葉。
    • 繰り返しまたは連続した文字(例:aaaaaa1234abcd
    • サービスの名前、ユーザー名、およびその派生語など、コンテキスト固有の単語。
  • パスワード強度メーターなどのガイダンスを加入者に提供します。
  • サブスクライバーのアカウントで実行できる認証試行の失敗回数を効果的に制限するレート制限メカニズムを実装します( レート制限(スロットル) を参照)。
  • オーセンティケータの侵害の証拠がある場合、変更を強制します。
  • 記憶されたシークレットを入力するときに、要求者がpaste機能を使用することを許可します(通常、ユーザーがより強力な記憶されたシークレットを選択する可能性を高めるパスワードマネージャーの使用を促進します)。

2.2。このセクションの方法を使用しないでください!

同じ出版物はまた、あなたがSHOULD NOTと述べています:

  • 秘密を切り捨てます。
  • サブスクライバーに、認証されていない要求者がアクセスできるhintを保存することを許可します。
  • 記憶された秘密を選択するときに、特定の種類の情報(「最初のペットの名前は何ですか?」など)を使用するようにサブスクライバーに促します。
  • 記憶されたシークレットに他の構成ルールを課します(異なるキャラクタータイプの混合を要求したり、連続して繰り返されるキャラクターを禁止したりする)。
  • 記憶されたシークレットを任意に(たとえば定期的に)変更する必要があります。

「適切な」パスワード検証フォームの作成方法を説明するWebサイトが多数あります。これらの多くは古く、使用すべきではありません。

3.パスワードエントロピーの使用

このセクションを読み続ける前に、このセクションの目的は、独自のセキュリティスキームを展開するために必要なツールを提供することではないことに注意してくださいhow現在のセキュリティメソッドvalidateパスワードに関する情報を提供します。独自のセキュリティスキームの作成を検討している場合は、実際に3回考えて、StackExchangeのセキュリティコミュニティの この記事 を読んでください。

3.1。パスワードエントロピーの概要

最も基本的なレベルでは、パスワードエントロピーは次の式を使用して計算できます。

E = log2(R^L)

上記の式で:

  • E パスワードエントロピーを表します
  • R 一意の文字のpoolの文字数
  • L パスワードの文字数です

この意味は R^L 可能なパスワードの数を表します。または、エントロピーの観点から、すべての可能性を使い果たすために必要な試行回数。

残念ながら、この式が考慮しないのは次のようなものです。

  • 汎用パスワード:Password1admin
  • 名前:JohnMary
  • 一般的に使用される単語:つまり、英語のtheI
  • 単語の反転/反転:drowssap(パスワードの逆)
  • 文字置換(別名リート):すなわちP@$$w0rd

これらの追加の考慮事項にロジックを追加することは、大きな課題です。プロジェクトに追加できる既存のパッケージについては、3.2を参照してください。

3.2。既存のパスワードエントロピープロジェクト

これを書いている時点で、パスワードの強度を推定するための最もよく知られている既存のライブラリは Dropboxによるzxcvbn (GitHubのオープンソースプロジェクト)です。 。netangularjscc#c ++goJavajavascriptobjective-cocamlphppythonrestRubyRustscala


間違った方法でやる

しかし、私は、誰もが異なる要件を持ち、時々人々が間違ったやり方でやりたいと思うことを理解しています。この基準に適合する人(または選択肢がなく、このセクションの上にあるものすべてを上司に提示しているが、メソッドの更新を拒否している人)は、少なくともUnicode文字を許可します。パスワード文字を特定の文字セットに制限する瞬間(つまり、小文字のASCII文字が存在することを確認するa-zを入力するか、ユーザーが!@#$%^&*())、あなたは単にトラブルを求めています!

PS非常に簡単に無効にできるため、クライアント側の検証を信頼しないでください。つまり、 javascript[〜#〜] stop [〜#〜]を使用してパスワードを検証しようとしているユーザーにとっては意味があります。詳細については、 JavaScript:クライアント側とサーバー側の検証 を参照してください。

次の正規表現パターンは、すべてのプログラミング言語で機能するわけではありませんが、多くの主要なプログラミング言語で機能します( Java。netphp - PerlRuby )。次の正規表現はご使用の言語(または言語バージョン)でも機能しない場合があり、代替手段を使用する必要がある場合があることに注意してください(ie python :参照 nicodeプロパティに一致するPython正規表現 ) 。一部のプログラミング言語には、車輪を再発明する代わりに、この種のことをチェックするより良い方法さえあります(つまり、 Password Validation Plugin for mysql を使用します)。 node.js を使用すると、 XRegExp addon または Javascript + Unicode regexes で説明されているUnicodeクラス用の他の変換ツールを使用する場合、以下が有効です。

制御文字が入力されないようにする必要がある場合、パターン[^\P{C}\s]を使用して、正規表現の一致が発生したときにユーザーにプロンプ​​トを出すことができます。これは、空白文字でもない制御文字(つまり、水平タブ、改行、垂直タブ)のみに一致します。

次の正規表現は、8文字以上のパスワードに少なくとも1つの小文字、大文字、数字、および記号が存在することを保証します。

^(?=\P{Ll}*\p{Ll})(?=\P{Lu}*\p{Lu})(?=\P{N}*\p{N})(?=[\p{L}\p{N}]*[^\p{L}\p{N}])[\s\S]{8,}$
  • ^行の先頭の位置をアサートします。
  • (?=\P{Ll}*\p{Ll})(スクリプト内に)少なくとも1つの小文字が存在することを確認します。
  • (?=\P{Lu}*\p{Lu})(スクリプト内に)少なくとも1つの大文字が存在することを確認してください。
  • (?=\P{N}*\p{N})(スクリプト内に)少なくとも1つの数字が存在することを確認してください。
  • (?=[\p{L}\p{N}]*[^\p{L}\p{N}])文字または数字以外の文字(スクリプト内)の少なくとも1つが存在することを確認します。
  • [\s\S]{8,} 8文字以上の任意の文字に一致します。
  • $行末の位置をアサートします。

上記の正規表現をご自身の判断で使用してください。警告されました!

58
ctwheels