Очистка паролей пользователей

Как я должен избегать или очищать пароли, предоставленные пользователем, прежде чем я их буду хранить и сохранить в своей базе данных?

Когда разработчики PHP рассматривают пароли пользователей хэширования для целей безопасности, они часто склонны думать об этих паролях, как и любые другие данные, предоставленные пользователем. Этот вопрос часто возникает в вопросах PHP, связанных с хранением паролей; разработчик часто хочет очистить пароль, используя такие функции, как escape_string() (в разных итерациях), htmlspecialchars() , addslashes() и другие, прежде чем хэшировать его и сохранить в базе данных.

Вам никогда не следует избегать, обрезать или использовать любой другой механизм очистки паролей, которые вы будете хешировать с помощью password_hash() по ряду причин, самый большой из которых заключается в том, что для выполнения дополнительной очистки к паролю требуется ненужный дополнительный код.

Вы будете спорить (и вы видите это в каждом сообщении, в котором пользовательские данные принимаются для использования в ваших системах), что мы должны очищать все пользовательские данные, и вы были бы правы для любой другой информации, которую мы принимаем от наших пользователей. Пароли разные. Хэшированные пароли не могут предложить угрозу SQL-инъекций, потому что перед хранением в базе данных строка превращается в хэш.

Актом хэширования пароля является принятие безопасного пароля для хранения в вашей базе данных. Хеш-функция не дает особого значения для любых байтов, поэтому очистка ее ввода не требуется по соображениям безопасности

Если вы следуете мантрам, позволяющим пользователям использовать пароли / фразы, которые они желают, и вы не ограничиваете пароли , позволяя любую длину, любое количество пробелов и любое хэширование специальных символов делают пароль / парольную фразу безопасной независимо от того, что содержится в пароль. На данный момент наиболее распространенный хеш (по умолчанию), PASSWORD_BCRYPT , превращает пароль в строку шириной 60 символов, содержащую случайную соль, вместе с информацией хешированного пароля и стоимостью (алгоритмическая стоимость создания хэша):

PASSWORD_BCRYPT используется для создания новых хэшей паролей с использованием алгоритма CRYPT_BLOWFISH. Это всегда приведет к хеш-файлу с использованием формата $ 2y $ crypt, который всегда будет шириной 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 &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;! " // double quotes, ampersand and braces have been changed string(65) "I'm a &quot;dessert topping&quot; &amp; a &lt;floor wax&gt;! " // same here string(48) "I\'ma \"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() ? Все они получают хеширование, как и запрос выше. Проблема возникает при попытке проверить пароль. Если мы используем один или несколько из этих методов, мы должны повторно использовать их до сравнения их с password_verify() . Не удалось выполнить следующее:

 password_verify($_POST['upassword'], $hashed_password); // where $hashed_password comes from a database query 

Вам нужно будет запустить опубликованный пароль с помощью метода очистки, который вы выбрали, прежде чем использовать результат этого в проверке пароля. Это ненужный набор шагов и сделает хеш не лучше.


Использование версии PHP менее 5.5? Вы можете использовать пакет совместимости password_hash() .

Вы действительно не должны использовать хеши паролей MD5 .

Прежде чем хешировать пароль, вы должны нормализовать его, как описано в разделе 4 RFC 7613 . В частности:

  1. Дополнительное правило сопоставления: любые экземпляры пространства, отличного от ASCII, ДОЛЖНЫ отображаться в пространстве ASCII (U + 0020); пространство без ASCII представляет собой любую кодовую точку Юникода, имеющую общую категорию Unicode «Zs» (за исключением U + 0020).

а также:

  1. Правило нормализации: Форма нормализации Unicode C (NFC) ДОЛЖНА применяться ко всем символам.

Это позволяет гарантировать, что если пользователь вводит один и тот же пароль, но использует другой метод ввода, пароль должен быть принят.