質問

パスワードの強度を正確に把握できる効果的なアルゴリズムを探していました。

さまざまなWebサイトでさまざまなパスワード強度評価を取得しているため、いくつかのさまざまなWebサイトがいくつかの異なるアルゴリズムを使用していることがわかりました。

役に立ちましたか?

解決

これは、PHP / MySQLでパスワードを操作するためのベストプラクティスの一般的な頭脳ダンプに成長しました。 ここで紹介するアイデアは一般的に私自身のものではありませんが、今までに見つけたものの中で最高のものです。


ユーザー情報を含むすべての操作にSSLを使用していることを確認してください。これらのフォームを含むすべてのページは、HTTPS経由で呼び出されていることを確認し、それ以外の場合は動作を拒否する必要があります。

許可されるログイン失敗回数を制限するだけで、ほとんどの攻撃を排除できます。

比較的弱いパスワードを許可しますが、ユーザーごとのログイン失敗回数を保存し、それを超える場合はメールによるキャプチャまたはパスワードの確認が必要です。最大失敗回数を5に設定します。

ユーザーへのログイン失敗の提示は、攻撃者に情報を提供しないように慎重に検討する必要があります。 存在しないユーザーによるログインの失敗は、不正なパスワードによるログインの失敗と同じメッセージを返す必要があります。異なるメッセージを提供すると、攻撃者は有効なユーザーログインを判断できます。

また、有効なパスワードを使用したログインが多すぎて失敗した場合、およびログインが多すぎてパスワードが間違った場合は、まったく同じメッセージを返すようにしてください。別のメッセージを提供すると、攻撃者は有効なユーザーパスワードを決定できます。かなりの数のユーザーがパスワードのリセットを強制されると、単純に元の状態に戻ります。

残念ながら、IPアドレスごとに許可されるログイン数を制限することは実用的ではありません。 AOLやほとんどの企業などのいくつかのプロバイダーは、Web要求をプロキシします。この制限を課すことで、これらのユーザーを効果的に排除できます。


辞書をクライアントにJavaScriptで送信するか、フィールドの変更ごとにajaxリクエストを送信する必要があるため、送信する前に辞書の単語をチェックするのは非効率的であることがわかりました。私はしばらくこれをやったがうまくいきましたが、それが生成したトラフィックが好きではありませんでした。

本質的に弱いパスワードから辞書の単語を差し引いたものをチェックすることは、いくつかの単純なjavascriptを使用した実用的なクライアント側です。

送信後、辞書にある単語とパスワードを含むユーザー名を確認します。逆もまた同様です。非常に優れた辞書はすぐにダウンロードでき、それらに対するテストは簡単です。ここでの落とし穴の1つは、辞書の単語をテストするために、データベースに対してクエリを送信する必要があることです。データベースには再びパスワードが含まれています。これを回避する方法は、簡単な暗号化と最後に配置されたSALTで辞書を暗号化してから、暗号化されたパスワードをテストすることでした。理想的ではありませんが、プレーンテキストよりも優れており、物理マシンとサブネット上の人々にとっては通信上のみです。

パスワードに満足したら、最初にPHPで暗号化してから保存します。次のパスワード暗号化機能も私の考えではありませんが、多くの問題を解決します。 PHP内で暗号化すると、共有サーバー上のユーザーが暗号化されていないパスワードを傍受するのを防ぎます。変更しないユーザーごとに何かを追加し(これは私のサイトのユーザー名であるため、メールを使用します)、ハッシュ(SALTはサイトごとに変更する短い定数文字列です)を追加すると、攻撃に対する耐性が高まります。 SALTはパスワード内にあり、パスワードは任意の長さにすることができるため、レインボーテーブルでこれを攻撃することはほとんど不可能になります。 または、ユーザーがメールを変更できず、全員のパスワードを無効にせずにSALTを変更できないことも意味します。

編集:ここで独自の機能をロールバックする代わりに、 PhPass を使用することをお勧めします。ユーザーログインを完全に忘れて、代わりに OpenID を使用します。

function password_crypt($email,$toHash) {
  $password = str_split($toHash,(strlen($toHash)/2)+1);
  return hash('sha256', $email.$password[0].SALT.$password[1]); 
}

私のJqueryishクライアント側のパスワードメーター。ターゲットはdivである必要があります。その幅は0から100の間で変化し、背景色はスクリプトで示されたクラスに基づいて変化します。

他のヒント

基本的に、主要な種類の攻撃を防止したい

  • 辞書攻撃
  • ブルートフォース攻撃

前者を防ぐために、一般的な単語を含むパスワードは弱いと考えます。 2番目を防ぐには、適切な長さ(8文字以上が一般的)で、かなり大きな文字セット(文字、数字、特殊文字を含む)のパスワードを推奨します。小文字と大文字を区別すると、文字セットが大幅に増えます。ただし、これにより一部のユーザーコミュニティでユーザビリティの問題が発生するため、その考慮事項のバランスを取る必要があります。

グーグルのクイック検索により、ブルートフォース攻撃(複雑なパスワード)を考慮したソリューションが見つかりましたが、辞書攻撃は考慮されませんでした。 このリストのPHPパスワード強度メーター強度チェッカーのはチェックサーバー側を実行するため、辞書をチェックするように拡張できます。

編集:

ところで...ユーザーごとのログイン試行回数も制限する必要があります。これにより、両方のタイプの攻撃の可能性が低くなります。効果的だがユーザーフレンドリーではないのは、X回の試行が失敗した後にアカウントをロックし、パスワードのリセットを要求することです。よりユーザーフレンドリーですが、より多くの努力は、ログイン試行間の時間を調整することです。最初の数回のログイン試行後に CAPTCHA を要求することもできます(これは、スタックオーバーフローが多くの編集後に必要とするものです) 、または非常に新しいユーザー向け)。

基本的には、おそらく正規表現を使用してパスワードの長さと複雑さを検証する必要があります。

javascriptを使用してこれを行う良い例は、次の場所にあります:

http://marketingtechblog.com/programming/javascript-password-strength/

Daren Schwenkeが指摘したように、セキュリティを自分で管理し、ユーザーの手には渡さない方がよい

しかし、パスワードを取得する最良の方法は依然としてソーシャルエンジニアリングであるため、ユーザーにパスワードの強さのヒントを提供することをお勧めします。

そのため、礼儀的な指標としてユーザーパスワードの強度をリアルタイムでチェックする小さなクライアントサイドスクリプトをハッキングできます。それは何もブロックしませんが、緑に変わるとき彼に良い暖かい感じを与えます:-)

基本的に確認する必要があるのは一般的な意味です。パスワードに文字、数字、アルファベット以外の文字が適切な量で含まれているかどうかを確認してください。

独自のアルゴリズムを非常に簡単にハックできます。10/ 10マークするだけです:

  • 0は長さゼロのパスワードです;
  • パスワードの8文字ごとに+2(15は安全な長さであると想定されます);
  • 文字を使用する場合は+1、2文字を使用する場合は+2;
  • 数字を使用する場合は+1、2つの数字を使用する場合は+2;
  • アルファベット以外の文字を使用する場合は
  • +1、2を使用する場合は+2

神様のパスワードを確認する必要はありません(大文字、特殊文字が配置されている場所など)。ユーザーは銀行/軍事/シークレットサービス/マンスリーpython映画業界に属していませんか?

あなたは、狂ったjavascriptスキルがなくても1時間でコーディングできます。

とにかく、パスワードを有効にして、サーバー側ですべてのセキュリティコードを移動します。認証を委任できる場合(例:オープンID)、さらに良い。

パスワードの強度をチェックする特定のアルゴリズムを考えることはできません。いくつかの基準を定義し、パスワードが基準を尊重する場合、そのスコアに1を追加します。パスワードがしきい値に達すると、パスワードは強力になります。それ以外の場合は弱いです。

しきい値が異なる場合は、さまざまなレベルの強度を定義できます。または、特定の基準に対して異なる値を定義できます。たとえば、パスワードが5文字の場合は1を追加しますが、10文字の場合は2を追加します。

チェックする基準のリストはこちら

長さ(8〜12は問題ありませんが、多ければ多いほど良いです) 小文字を含む 大文字を含む 大文字は最初の文字ではありません。 数字を含む 記号が含まれています 最後の文字は人間のような記号ではありません(例:。または!) 辞書の言葉のように見えません。いくつかの賢明なパスワードクラックには、単語と文字の代替ライブラリが含まれます(Library-> L1br @ ryなど)

助けてください。

ロールアウトしないでください!

暗号の専門家は、独自の暗号化を思いとどまらせる明らかなはずの理由のため。

まったく同じ理由で、パスワードの強度を測定するという問題に対する独自のソリューションを展開しようとすべきではありません。これは非常に暗号化の問題です。

この目的のためにいくつかの大規模な正規表現を作成するというい仕事をしてはいけません。パスワードの全体的な強度に影響するいくつかの要因を考慮に入れない可能性があります。

それは難しい問題です

パスワードの強度を測定する問題に固有のかなりの困難があります。このテーマについてより多くの研究を行うほど、これが「単方向」であることを実感します。問題;つまり、「難易度」を測定することはできません。 (計算コスト)パスワードをクラッキングする効率的。むしろ、複雑さの要件を提供し、その要件を満たすパスワードの能力を測定する方が効率的です。

問題を論理的に考えると、「亀裂性指数」思ったほど便利ではありません。計算を駆動する要因は非常に多く、そのほとんどはクラッキングプロセス専用の計算リソースに関連しているため、実用的ではありません。

問題のパスワードに対する John the Ripper (または同様のツール)を想像してください。適切なパスワードを解読するには数日かかり、良いパスワードを解読するには数か月かかり、例外的なパスワードを解読するには太陽が燃え尽きるまで時間がかかる場合があります。これは、パスワードの強度を測定する実用的な手段ではありません。

他の方向から問題にアプローチする方がはるかに管理しやすい:複雑さの要件のセットを提供すれば、パスワードの相対的な強度を非常に迅速に判断することができます。明らかに、提供される複雑さの要件は時間とともに進化する必要がありますが、この方法で問題にアプローチする場合に考慮する変数ははるかに少なくなります。

実行可能なソリューション

passwdqc という名前のOpenwallから入手可能なスタンドアロンユーティリティがあります(おそらく、パスワード品質チェッカーの略)。 Openwallの開発者であるSolar Designerは、真正な暗号化の専門家であるように見えます(彼の作品は自分で語っています)ので、そのようなツールを作成する資格があります。

私の特定のユースケースでは、これはWebの暗い隅に住む、よく考えられていないJavaScriptスニペットを使用するよりもはるかに魅力的なソリューションです。

特定のニーズに合わせてパラメータを設定することが最も難しい部分です。実装は簡単な部分です。

実用例

ジャンプスタートを提供するために、PHPで簡単な実装を提供しています。標準免責事項が適用されます。

この例では、パスワードのリスト全体をPHPスクリプトにフィードすることを想定しています。言うまでもなく、実際のパスワード(パスワードマネージャーからダンプされたパスワードなど)を使用してこれを行う場合は、パスワードの取り扱いに関して細心の注意を払う必要があります。暗号化されていないパスワードダンプをディスクに書き込むだけで、パスワードのセキュリティが危険にさらされます!

passwords.csv

"Title","Password"
"My Test Password","password123"
"Your Test Password","123456!!!"
"A strong password","NFYbCoHC5S7dngitqCD53tvQkAu3dais"

password-check.php

<?php

//A few handy examples from other users:
//http://php.net/manual/en/function.str-getcsv.php#117692

$csv = array_map('str_getcsv', file('passwords.csv'), [',']);

array_walk($csv, function(&$a) use ($csv) {
    $a = array_combine($csv[0], $a);
});

//Remove column header.

array_shift($csv);

//Define report column headers.

$results[] = [
    'Title',
    'Result',
    'Exit Code',
];

$i = 1;

foreach ($csv as $p) {
    $row['title'] = $p['Title'];

    //If the value contains a space, it's considered a passphrase.

    $isPassphrase = stristr($p['Password'], ' ') !== false ? true : false;

    $cmd = 'echo ' . escapeshellarg($p['Password']) . ' | pwqcheck -1 min=32,24,22,20,16 max=128';

    if ($isPassphrase) {
        $cmd .= ' passphrase=3';
    }
    else {
        $cmd .= ' passphrase=0';
    }

    $output = null;
    $exitCode = null;

    $stdOut = exec($cmd, $output, $exitCode);

    //Exit code 0 represents an unacceptable password (not an error).
    //Exit code 1 represents an acceptable password (it meets the criteria).

    if ($exitCode === 0 || $exitCode === 1) {
        $row['result'] = trim($stdOut);
        $row['exitCode'] = $exitCode;
    }
    else {
        $row['result'] = 'An error occurred while calling pwqcheck';
        $row['exitCode'] = null;
    }

    $results[$i] = $row;

    $i++;
}

$reportFile = 'report.csv';

$fp = @fopen($reportFile, 'w');

if ($fp !== false) {
    foreach ($results as $p) {
        fputcsv($fp, $p);
    }

    fclose($fp);
}
else {
    die($reportFile . ' could not be opened for writing (destination is not writable or file is in use)');
}

exit;

結果 report.csv

Title,Result,"Exit Code"
"My Test Password","Bad passphrase (too short)",1
"Your Test Password","Bad passphrase (too short)",1
"A strong password",OK,0

まとめ

ウェブ上でより徹底的な解決策を見つけることはまだありません。言うまでもなく、他の推奨事項も歓迎します。

明らかに、このアプローチは特定のユースケースには理想的ではありません(たとえば、「クライアント側」に実装された「パスワード強度メーター」)。それでも、上記で概説したアプローチを使用して成功/失敗応答を返すサーバー側リソースへのAJAX呼び出しを行うのは簡単ですが、

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top