web-dev-qa-db-ja.com

ユーザーのパスワードを安全に保存するにはどうすればよいですか?

これは単純な MD5 よりもはるかに安全ですか?パスワードのセキュリティについて調べ始めたばかりです。私はPHPが初めてです。

$salt = 'csdnfgksdgojnmfnb';

$password = md5($salt.$_POST['password']);
$result = mysql_query("SELECT id FROM users
                       WHERE username = '".mysql_real_escape_string($_POST['username'])."'
                       AND password = '$password'");

if (mysql_num_rows($result) < 1) {
    /* Access denied */
    echo "The username or password you entered is incorrect.";
} 
else {
    $_SESSION['id'] = mysql_result($result, 0, 'id');
    #header("Location: ./");
    echo "Hello $_SESSION[id]!";
}
168
Rebar

パスワードストレージスキームを安全にする最も簡単な方法は、標準ライブラリを使用することです

セキュリティはほとんどのプログラマが単独で取り組むよりもはるかに複雑で目に見えないねじ込みの可能性がある傾向があるため、標準ライブラリを使用することはほとんどの場合最も簡単で最も安全な(唯一ではないにしても)利用可能なオプションです。


新しいPHP password API(5.5.0+)

PHPバージョン5.5.0以降を使用している場合は、新しい簡易パスワードハッシュAPIを使用できます

PHPのパスワードAPIを使用したコードの例:

<?php
// $hash is what you would store in your database
$hash = password_hash($_POST['password'], PASSWORD_DEFAULT, ['cost' => 12]);

// $hash would be the $hash (above) stored in your database for this user
$checked = password_verify($_POST['password'], $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

(レガシー5.3.7以降をまだ使用している場合は、 ircmaxell/password_compat をインストールして、組み込み関数にアクセスできます)


塩漬けハッシュの改善:コショウを追加する

追加のセキュリティが必要な場合は、セキュリティ担当者(2017年)は( pepper 'を(自動的に)ソルトされたパスワードハッシュに追加することを推奨しています。

このパターンを安全に実装する単純なクラスのドロップがあります。 Netsilik/PepperedPasswordsgithub )。
これにはMITライセンスが付属しているため、独自のプロジェクトでも、好きなように使用できます。

Netsilik/PepperedPasswordsを使用したコードの例:

<?php
use Netsilik/Lib/PepperedPasswords;

// Some long, random, binary string, encoded as hexadecimal; stored in your configuration (NOT in your Database, as that would defeat the entire purpose of the pepper).
$config['pepper'] = hex2bin('012345679ABCDEF012345679ABCDEF012345679ABCDEF012345679ABCDEF');

$hasher = new PepperedPasswords($config['pepper']);

// $hash is what you would store in your database
$hash = $hasher->hash($_POST['password']);

// $hash would be the $hash (above) stored in your database for this user
$checked = $hasher->verify($_POST['password'], $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}


OLD標準ライブラリ

注意してください:これはもう必要ないはずです!これは歴史的な目的でのみここにあります。

Portable PHPパスワードハッシュフレームワークphpass可能な場合は必ずCRYPT_BLOWFISHアルゴリズムを使用してください。

Phpass(v0.2)を使用したコードの例:

<?php
require('PasswordHash.php');

$pwdHasher = new PasswordHash(8, FALSE);

// $hash is what you would store in your database
$hash = $pwdHasher->HashPassword( $password );

// $hash would be the $hash (above) stored in your database for this user
$checked = $pwdHasher->CheckPassword($password, $hash);
if ($checked) {
    echo 'password correct';
} else {
    echo 'wrong credentials';
}

PHPassは、いくつかの非常に有名なプロジェクトに実装されています。

  • phpBB3
  • WordPress 2.5+およびbbPress
  • Drupal 7リリース、(Drupal 5&6で利用可能なモジュール)
  • その他

良いことは、詳細について心配する必要がないことです。これらの詳細は経験のある人によってプログラムされ、インターネット上の多くの人々によってレビューされています。

パスワードストレージスキームの詳細については、 Jeff `sのブログ投稿を参照してください。 おそらくパスワードを誤って保存している

私は自分でやる、ありがとう」のアプローチに行くなら、あなたが何をしても、MD5を使用しないまたはSHA1もう。これらはニースハッシュアルゴリズムですが、セキュリティ上の理由で破損と見なされます

現在、CRYPT_BLOWFISHで crypt を使用することがベストプラクティスです。
CRYPT_BLOWFISH in PHPはBcryptハッシュの実装です。BcryptはBlowfishブロック暗号に基づいており、高価なキー設定を使用してアルゴリズムを遅くします。

265
Jacco

SQLステートメントを連結する代わりにパラメーター化されたクエリを使用すると、ユーザーの安全性が大幅に向上します。そして、 ソルト はユーザーごとに一意であり、パスワードハッシュと共に保存する必要があります。

28
Anton Gogolev

より良い方法は、各ユーザーが固有のソルトを持つことです。

ソルトを使用する利点は、攻撃者がすべての辞書WordのMD5署名を事前に生成することを難しくすることです。しかし、攻撃者が固定ソルトがあることを知った場合、攻撃者は、固定ソルトのプレフィックスが付いたすべての辞書WordのMD5署名を事前に生成できます。

より良い方法は、ユーザーがパスワードを変更するたびに、システムがランダムなソルトを生成し、そのソルトをユーザーレコードと共に保存することです。 MD5署名を生成する前にソルトを検索する必要があるため、パスワードをチェックするのに少し費用がかかりますが、攻撃者がMD5を事前生成することははるかに困難になります。

11

PHP 5.5(以前のバージョンでも利用可能です。以下を参照)では、新しい組み込みソリューションの使用を提案したいと思います。 password_hash() および password_verify() 。必要なパスワードセキュリティのレベルを達成するためにいくつかのオプションを提供します(たとえば、_$options_配列を介して「コスト」パラメーターを指定することにより)

_<?php
var_dump(password_hash("my-secret-password", PASSWORD_DEFAULT));

$options = array(
    'cost' => 7, // this is the number of rounds for bcrypt
    // 'salt' => 'TphfsM82o1uEKlfP9vf1f', // you could specify a salt but it is not recommended
);
var_dump(password_hash("my-secret-password", PASSWORD_BCRYPT, $options));
?>
_

戻ります

_string(60) "$2y$10$w2LxXdIcqJpD6idFTNn.eeZbKesdu5y41ksL22iI8C4/6EweI7OK."
string(60) "$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d."
_

ご覧のとおり、文字列にはソルトとオプションで指定されたコストが含まれています。また、使用されるアルゴリズムも含まれています。

したがって、パスワードをチェックするとき(たとえば、ユーザーがログインするとき)、相補的なpassword_verify()関数を使用するとき、パスワードハッシュ自体から必要な暗号化パラメーターを抽出します。

ソルトを指定しない場合、ソルトはランダムに生成されるため、生成されるパスワードハッシュはpassword_hash()を呼び出すたびに異なります。したがって、正しいパスワードであっても、以前のハッシュと新しく生成されたハッシュを比較すると失敗します。

検証は次のように機能します。

_var_dump(password_verify("my-secret-password", '$2y$10$BjHJbMCNWIJq7xiAeyFaHOGaO0jjNoE11e0YAer6Zu01OZHN/gk6K'));
var_dump(password_verify("wrong-password", '$2y$10$BjHJbMCNWIJq7xiAeyFaHOGaO0jjNoE11e0YAer6Zu01OZHN/gk6K'));

var_dump(password_verify("my-secret-password", '$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d.'));
var_dump(password_verify("wrong-password", '$2y$07$TphfsM82o1uEKlfP9vf1fOKohBqGVXOJEmnUtQu7Y1UMft1R4D3d.'));
_

これらの組み込み関数を提供することで、プログラマーが適切な実装をしなければならない思考の量を減らすため、データ盗難の場合にすぐにパスワードセキュリティが向上することを願っています。

PHP 5.3.7+のPHP 5.5の_password_hash_を提供する小さなライブラリ(1つのPHPファイル)があります。 https:// github.com/ircmaxell/password_compat

11
akirk

それは私でいいです。 Atwood氏は Rainbowテーブルに対するMD5の強さ について書いています。

また、最近人気が高まっていると思われるSHA-1も見ることができます。

0
nickf

追加したい:

  • ユーザーのパスワードを長さで制限しないでください

古いシステムとの互換性のために、多くの場合、パスワードの最大長に制限を設定します。これは不適切なセキュリティポリシーです。制限を設定する場合は、パスワードの最小長にのみ設定します。

  • ユーザーのパスワードをメールで送信しないでください

パスワードを忘れた場合は、ユーザーがパスワードを変更できるアドレスを送信する必要があります。

  • ユーザーのパスワードのハッシュを更新する

パスワードハッシュが古くなっている可能性があります(アルゴリズムのパラメーターが更新されている可能性があります)。関数 password_needs_rehash() を使用すると、チェックアウトできます。

0
Aleksey Bykov