ハッシュしてデータベースに保存する前に、ユーザーが指定したパスワードをどのようにエスケープまたはクレンジングする必要がありますか?
PHP開発者がセキュリティのためにユーザーのパスワードをハッシュすることを検討する場合、他のユーザーが提供するデータと同じようにそれらのパスワードを考える傾向があります。この主題は、PHPパスワードの保存に関する質問;開発者は、escape_string()
(さまざまな反復)、htmlspecialchars()
、addslashes()
などの関数を使用してパスワードをクレンジングしたいことがよくあります。ハッシュしてデータベースに保存する前に。
PHPの password_hash()
でハッシュするパスワードに対して、エスケープ、トリム、または他のクレンジングメカニズムを使用しないでください。いくつかの理由があります。パスワードをクレンジングするには、不必要な追加コードが必要です。
すべてのユーザー入力をクレンジングする必要があると主張します(そして、システムでのユーザーデータの使用が受け入れられるすべての投稿に表示されます)。パスワードは異なります。 ハッシュされたパスワードは、データベースに格納する前に文字列がハッシュに変換されるため、SQLインジェクションの脅威を提供できません。
パスワードをハッシュする行為は、パスワードをデータベースに安全に保存する行為です。ハッシュ関数はどのバイトにも特別な意味を与えないため、セキュリティ上の理由から入力のクレンジングは不要です
ユーザーが パスワード/フレーズ を使用できるようにするというマントラに従っている場合、ユーザーは パスワードを制限しないでください を使用して、長さ、スペース、特殊文字を許可しますハッシュを使用すると、パスワードに何が含まれていても、パスワード/パスフレーズが安全になります。現在、最も一般的なハッシュ(デフォルト) _PASSWORD_BCRYPT
_ は、パスワードを、ハッシュされたパスワード情報とコストとともにランダムなソルトを含む60文字幅の文字列に変換します(ハッシュ作成のアルゴリズムコスト):
PASSWORD_BCRYPTは、CRYPT_BLOWFISHアルゴリズムを使用して新しいパスワードハッシュを作成するために使用されます。これにより、常に "$ 2y $"暗号化形式を使用するハッシュが生成されます。これは常に60文字幅です。
ハッシュを保存するためのスペース要件は、異なるハッシュメソッドが関数に追加されると変更される可能性があります。そのため、VARCHAR(255)
やTEXT
など、保存されたハッシュの列タイプを大きくすることをお勧めします。
完全なSQLクエリをパスワードとして使用すると、ハッシュ化され、SQLエンジンで実行できなくなります。
_SELECT * FROM `users`;
_
_$2y$10$1tOKcWUWBW5gBka04tGMO.BH7gs/qjAHZsC5wyG0zmI2C.KgaqU5G
_にハッシュできます
さまざまなサニタイズ方法がパスワードにどのように影響するかを見てみましょう-
パスワードは_I'm a "dessert topping" & a <floor wax>!
_です(パスワードの末尾には5つのスペースがあり、ここには表示されません。)
次のトリミング方法を適用すると、かなり異なる結果が得られます。
_var_dump(trim($_POST['upassword']));
var_dump(htmlentities($_POST['upassword']));
var_dump(htmlspecialchars($_POST['upassword']));
var_dump(addslashes($_POST['upassword']));
var_dump(strip_tags($_POST['upassword']));
_
結果:
_string(40) "I'm a "dessert topping" & a <floor wax>!" // spaces at the end are missing
string(65) "I'm a "dessert topping" & a <floor wax>! " // double quotes, ampersand and braces have been changed
string(65) "I'm a "dessert topping" & a <floor wax>! " // same here
string(48) "I\'m a \"dessert topping\" & a <floor wax>! " // escape characters have been added
string(34) "I'm a "dessert topping" & a ! " // looks like we have something missing
_
これらをpassword_hash()
に送信するとどうなりますか?上記のクエリと同様に、すべてハッシュされます。パスワードを確認しようとすると、問題が発生します。これらのメソッドを1つ以上使用する場合、 password_verify()
と比較する前にそれらを再使用する必要があります。以下は失敗します:
_password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query
_
パスワード検証でその結果を使用する前に、選択したクレンジング方法でポストされたパスワードを実行する必要があります。これは不必要な一連の手順であり、ハッシュの改善にはつながりません。
PHP 5.5未満のバージョンを使用していますか?password_hash()
compatibility pack を使用できます。
MD5パスワードハッシュ を使用しないでください。
パスワードをハッシュする前に、 RFC 7613のセクション4 で説明されているようにパスワードを正規化する必要があります。特に:
- 追加のマッピングルール:非ASCIIスペースのインスタンスは、ASCII space(U + 0020)にマップする必要があります。非ASCIIスペースは、 "ZsのUnicode一般カテゴリを持つUnicodeコードポイントです。 (U + 0020を除く)。
そして:
- 正規化ルール:Unicode正規化フォームC(NFC)は、すべての文字に適用する必要があります。
これにより、ユーザーが同じパスワードを入力したが、別の入力方法を使用した場合でも、パスワードが受け入れられるようになります。