2011-07-05 11 views
33

私は小さなコミュニティのウェブサイトを持っており、忘れたパスワード機能を実装する必要があります。私は現在、MD5で暗号化されたDBにパスワードを保存しています。PHP Forgot Password機能

「復号化」を並べ替えて電子メールで送信することはできますか?パスワードリセットページが必要ですか?

+5

パスワードMD5を暗号化して保存する考えは、あなたがそれらを解読できないということです。誰かがあなたのシステムに侵入してDBをダンプしたとしても、パスワードを取得することはできません(パスワードが弱い場合を除き、それは別の話です...) –

答えて

127

MD5ハッシュパスワードは元に戻すことができません。 (MD5はハッシングであり、実際には暗号化されていないので、微妙な違いがあります)。 はいあなたは間違いなくパスワード「リセット」プロセスを提供したいと思います。その電子メールならば、あなたに安全なパスワードのリセットのためのハイレベルのワークフローを与えること

...

  1. ユーザーが自分のパスワードをリセットするために要求すると、彼らは自分のメールアドレス
  2. を入力作るには示していません。アドレスが有効かどうか(電子メールが送信されたことを伝えてください)。これは、ユーザビリティを低下させる(すなわち、どの電子メールを登録したかわからない)が、実際にあなたのサイトに登録されている電子メールに関する情報を収集しようとする人には情報を提供しないため、
  3. トークンを生成して(おそらく塩でタイムスタンプをハッシュして)、ユーザーのレコードのデータベースに格納します。
  4. あなたのhttp リセットページ(URLのトークンと電子メールアドレス)へのリンクとともに、ユーザーに電子メールを送信してください。
  5. トークンと電子メールアドレスを使用して、ユーザーを検証します。
  6. 新しいパスワードを選択して、古いパスワードを置き換えます。
  7. さらに、特定の時間枠、通常は24時間後にトークンを期限切れにすることをお勧めします。
  8. オプションで、「忘れた」試行回数を記録し、人々が大量の電子メールを要求している場合は、より複雑な機能を実装することもできます。
  9. オプションで、リセットを要求している個人のIPアドレスを(別の表に)記録します。そのIPからカウントを増やします。それが10倍以上に達すると...将来の要求を無視する。ハッシュの中にあなたにもう少し詳細を与えることを

...

あなたがPHPでMD5()関数を使用してパスワードなどの値をハッシュすると、最終的な値が同じであることを行っていますあなたはそれを実行するサーバーに関係なく、そのパスワードのために。 (したがって、ハッシュと暗号化の間には、すぐにわかる1つの違いがあります...プライベート/パブリックキーはありません)。

これは、人々がrainbow tablesに脆弱性を言及しているところです。虹のテーブルの非常に基本的な説明は...あなたのmd5()ハッシュ値のmd5()を得るためにmd5()は辞書の単語(弱いパスワード)の束をハッシュします。それらをデータベーステーブル(虹のテーブル)に入れてください。

ウェブサイトのデータベースを侵害した場合、ユーザーのハッシュされたパスワードをレインボーテーブルに対して実行して、ハッシュをパスワードに「逆戻り」させることができます。 (あなたは実際にハッシュを "逆転"していません...しかし、あなたはそのアイデアを得る)。

あなたのパスワードを「塩漬け」するのがベストプラクティスです。これは、ユーザーのパスワードにランダムな値を追加してから、をハッシュする前に(つまり、ここでも非常に基本的な考え方です)意味します。さて、あなたのデータベースに対してレインボーテーブルを実行すると、「パスワード」のmd5()ハッシュが「password384746」と異なるため、簡単に「逆転」しません。

ここでは役立つ良いSO Q/Aがあります。 Secure hash and salt for PHP passwords

+1

本当に有益! – Liam

+1

@Jared Cobb:8とはどういう意味ですか? – testing

+2

@testing良い質問...このシナリオを除き、攻撃者はボットネット、プロキシ、または他のラウンドロビン方式を使用して、毎回異なるIPアドレスからあなたを襲っている点を除いて、ポイント9と非常に似ています。たとえば、システムで数分間または数時間以内に「Forgot Requests」が大幅に増加したことが検出された場合、機能を一時的に減速または無効にすることを検討することができます。 (もちろん、あなたのスレッシュホールドはあなたのユーザーベースのサイズと "通常の"ボリュームとみなされる主観的な判断によって決定されます)。 –

2

MD5は片方向ハッシュを意図しています。パスワードをリセットする必要があります。

1

いいえあなたはそれを解読できません。それは全体のアイデアです。

一時パスワードを送信し、リセットする必要があります。

1

パスワードリセットページを行う必要があります。 PHPでMD5を解読する方法はありません。

7

いいえ、MD5は不可逆です。ハッシングパスワードのポイントは、データベースにアクセスする攻撃者が誰のパスワードにもアクセスできないようにすることです。 MD5(特に無塩MD5)は、一般にrainbow tableを用いて攻撃することができると述べられている。セキュリティのためには、bcryptを使用する方が良いでしょう。

3

パスワードを解読することはできません。平文でユーザーにパスワードを送信することも考慮しないでください。 (それは決してサイトをもう一度使用することを可能にする#1方法です;それは巨大なセキュリティホールです)ユーザーのパスワード回復メールに送信される時間関連のキーを含むリンクからトリガーされるパスワードリセットページを提供します;これはパスワード回復の現状です。

1

MD5は一方向性関数です。それを解読することはできません。パスワードリセットページが必要です。

2

get parameterとしてmd5と電子メールアドレスを受け取り、電子メールとmd5のパスワードをdbで調べるページを作成します。 Jared Cobbのメモに従えば、それはあなたを正しい道に導くはずです。私はちょうどあなたは、ユーザーが有効なユーザーであることを知っているし、自分のパスワード

3

最高のものを変更するために例えば、URLが、これは十分であるべきhttp://yourdomain.com/resetpassword.php?code=md5codesentviaemail

$code = isset($_GET['code']) ? $_GET['code'] : ''; 
    $email = isset($_GET['email']) ? $_GET['email'] : ''; 
$checkPw = ''; 

    if(empty($code) || empty($email)) 
    { 
    die(); 
    } 
    $sqlQuery = 'SELECT * FROM users WHERE email = "'.$email.'"; 
//remember to check for sql injections 
    //then get the results as an array, i use a database class eg $user 

    if(!empty($user['password'])) 
    { 
    $checkPw = md5($user['password']); 
    }else 
    { 
    die(); 
    } 

    if($checkPw !== $code) 
    { 
    die(); 
    }else 
    { 
    //display form for user to change password 
    } 

を送信するだけでなく

いくつかの例を追加しましたあなたが登録するときに電子メールアドレスを送信するようリクエストすることです。その後、忘れてしまった場合は、パスワードを忘れた場合にパスワードをリセットして、ランダムな値を電子メールで送信してアクセスできるようにしてから、パスワードをもっと記憶に残すように変更してください。この方法でセキュリティを妥協する必要はありません。 ユーザー名を送信するだけのリンクがあるかもしれませんが、より良いセキュリティのためには、質疑応答や記憶に残る言葉が必要です。

8

このポストThe definitive guide to forms based website authenticationによれば、ステップ3.と4.のために、保存しているのと同じトークンを送信するかどうかはわかりません。

トークンを送信してハッシュし、DBにハッシュトークンを保存する必要があります。そうしないと、データベースが改ざんされた場合、パスワードのリセットページにアクセスできます。

要約すると:

ハッシュは、ハッシュアルゴリズムである
$token = md5(microtime (TRUE)*100000); 
$tokenToSendInMail = $token; 
$tokenToStoreInDB = hash($token); 

を。

+1

これは本当に良い点です。ハッシュされたトークンをDBに格納します。 +1 – Francodi

+1

予測可能なトークンを使用するのは良い考えではありません...時間のように予測可能なものに基づいてはいけません。 (攻撃者は、トークンが生成された時の値を反復することができます)PHP7では、 'random_bytes'を使用する必要があります。 PHP5では、互換性の実装または 'openssl_random_pseudo_byte'を使用する必要があります。 –

+1

(別のオプションは、秘密のランダムな文字列のハッシュとユーザーの詳細とうまくいくらかのランダムなデータを使用することです.DBに格納されているので、トークンが予測可能な理由はありません)私は長い文字列に 'password_hash'を使ってトークンを生成し、リンクにbase64でエンコードされたバージョンのハッシュを送ります)。 (DBに保存する前にもう一度ハッシュしておくとオプションになるかもしれませんが、4-24時間後にリセットリンクを切る方がより良い防御になります)(適切なランダムデータを使用して、 –

2

phpの組み込みのpassword_verifyとpassword_hashを使用します。

3

Marcus Reedが述べたように、2015/2016のPHPバージョン> = 5.5の場合、MD5を使用しないで、password_hash()とpassword_verify()はパスワードを簡単かつ安全にハッシュしてコストを提供します自動的にハッシュに塩を付けます。

私は混乱を避けるために決定的なステートメントを提供しているため、現在投票やコメントをする能力がありません。