Какие лучшие практики следует использовать в сценарии входа в PHP?

27

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

Я буду использовать PHP и базу данных MYSQL.

Раньше я использовал md5, но я вижу, что sha256 или sha512 будут лучше (вместе с безопасным хешем и солью).

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

Я также немного отстаю от лучших практик использования сессий в PHP 5 (последний раз, когда я читал, был PHP 4), так что некоторые лучшие практики с этим были бы полезны.

Спасибо.

baritoneuk
источник
1
Бросьте свой скрипт на codereview.SE!
Крис
@Chris CodeReview поможет с ясностью кода и тому подобное. Вы определенно не должны идти к ним в целях безопасности. Во всяком случае, они почти всегда будут напоминать вам не «бросать свой», что в основном является тем же ответом, который он получит в любом сообществе программистов на SE.
Alternatex

Ответы:

21

Лучшая мысль - не изобретать велосипед. Но, как я понимаю, в мире PHP может быть трудно найти высококачественный компонент, который уже это делает (даже я уверен, что фреймворки реализуют такие вещи, и их реализации уже протестированы, надежны, проверены на код и т. Д.). )

Если по каким-то причинам вы не можете использовать фреймворк, вот несколько советов:

Предложения по безопасности

  • Используйте PBKDF2 или Bcrypt, если можете . Это сделано для этого.

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

  • Если вы не можете, по крайней мере , не используйте MD5 / SHA1. Никогда. Забудь об этом . Используйте вместо этого SHA512, например. Используйте соль тоже.

    Обоснование: MD5 и SHA1 слишком быстрые. Если злоумышленник имеет доступ к вашей базе данных, содержащей хэши, и имеет (даже не особенно) мощную машину, взлом паролей происходит быстро и легко. Если нет никаких солей, вероятность того, что злоумышленник найдет действительный пароль, возрастет (что может нанести дополнительный вред, если пароль был повторно использован где-то еще).

  • В PHP 5.5.0 и более поздних версиях используйте password_hashи password_verify.

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

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

    Еще одна защита - установить ограничение на количество отказов в час. Если пользователь отправил 3600 неправильных паролей в час, 1 пароль в секунду, трудно поверить, что это законный пользователь.

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

  • Не просите пользователей менять свои пароли каждые четыре недели. Это очень раздражает и снижает безопасность, так как поощряет безопасность после ее завершения.

    Обоснование: идея о том, что принудительное изменение паролей каждые n недель защищает систему от перебора, ошибочна. Атаки грубой силой обычно успешны в течение нескольких секунд, минут, часов или дней, что делает ежемесячные изменения пароля несущественными. С другой стороны, пользователи плохо запоминают пароли. Кроме того, если им необходимо изменить их, они либо попытаются использовать очень простые пароли, либо просто запомнят свои пароли на пост-своей.

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

  • Не запоминайте учетные данные пользователя в файлах cookie, если только пользователь не просит сделать это (флажок «Запомнить меня» должен быть по умолчанию снят, чтобы избежать человеческих ошибок).

Простота использования предложений

  • Пусть пользователь запомнит пароль, если захочет, даже если большинство браузеров уже используют эту функцию.
  • Не используйте подход Google, когда вместо запроса имени пользователя и пароля у пользователя иногда запрашивается только пароль , имя пользователя уже отображается в <span/>. Браузеры не могут заполнить поле пароля в этом случае (по крайней мере, Firefox не может этого сделать), поэтому он вынужден выйти из системы, а затем войти в систему с помощью обычной формы, заполненной браузером.
  • Не используйте JavaScript-всплывающие окна для входа в систему. Это нарушает функции запоминания паролей в браузерах (и отстой во всех случаях).
  • Позвольте пользователю ввести либо свое имя пользователя, либо свой почтовый адрес . Когда я регистрируюсь, иногда имя пользователя, которое я хочу ввести, уже занято, поэтому я должен придумать новое. У меня есть все шансы забыть это имя через два часа.
  • Всегда держите ссылку на «Забыли пароль» рядом с формой входа. Не отображайте его, только когда пользователь не смог войти в систему: пользователь, который вообще не помнит свой пароль, не подозревает, что он должен ввести неправильный пароль, чтобы увидеть ссылку «Забыли мой пароль».
  • Не используйте безопасность по почте .
  • Не придумывайте глупых правил, связанных с паролем, чтобы сделать его слабее . Пример: «Ваш пароль должен начинаться со строчной буквы.»; «Ваш пароль не может содержать пробелы».
Арсений Мурзенко
источник
Не сталкивался с bcrypt. Каково ваше мнение, чтобы рекомендовать это? Почему не md5 / sha1? Спасибо за остальные предложения!
baritoneuk
Аргументация проста: bcryptэто делают люди с высокой квалификацией. Это также проверено, проверено и т. Д. Так что нет смысла реализовывать то же самое самостоятельно. Это похоже на создание собственного алгоритма криптографии для вашего сайта. * «Почему бы не md5 / sha1?»: См., Например, en.wikipedia.org/wiki/MD5#Security
Арсений Мурзенко,
5
bcrypt работает медленно и, как уже упоминалось, реализовано профессионалами. md5 - это алгоритм хеширования, а не шифрование, которое не совсем одно и то же. Хэширование файла быстро - это хорошо, здесь будет использоваться md5 ... хеширование пароля не должно быть таким быстрым, bcrypt может помочь здесь. Причина, по которой я говорю, заключается в том, что грубая сила становится более сложной, когда алгоритм шифрования «медленный».
Крис
2
@baritoneuk: минимум это круто. Но я не могу подсчитать, сколько сайтов, на которых я побывал, имели ограничения, такие как максимальная длина, без буквенно-цифровых символов и т. Д. Недоумение, если вы все равно собираетесь хешировать пароль - что заставляет меня беспокоиться, что это не так. они просто хранят его в своей базе данных в открытом виде.
Carson63000
1
@ Брайан Ортис: не всегда. Иногда полезно установить ограничение. Если вы этого не сделаете, вы проверяете, работает ли ваше приложение на любую длину? Как? Если вы не проверите его, как вы можете быть уверены, что он работает? Вместо этого, устанавливая ограничение на разумное значение, например, 100, вы можете легко проверить пароль на 100 символов.
Арсений Мурзенко
6
  1. Ваш сайт должен использовать HTTPS. Ни при каких обстоятельствах вы не должны представлять страницу входа в систему или принимать вход от незашифрованного соединения.
  2. Ваши куки должны быть ограничены только HTTP и безопасными соединениями, если вы используете HTTPS.
  3. Процесс входа в систему должен занять не менее 2 секунд (1, если вы считаете, что 2 секунды слишком длинные). Используйте безопасный хеш при хранении и проверке паролей и используйте соль, которую сложнее угадать. Используйте, bcryptесли возможно. В противном случае используйте другой вид повторного хэша.
  4. Никогда не создавайте запросы к вашей базе данных каким-либо образом, требующим использования таких функций, как mysql_real_escape_string. Никогда не используйте конкатенацию строк для создания вашего запроса. Используйте подготовленные, параметризованные запросы. Большинство, если не все, драйверы БД для PHP поддерживают это. Если вы не знаете , как это сделать, потратить некоторое время на обучение , как prepare, bindи с executeиспользованием любых DB вы используете. Это единственный верный способ защитить себя от SQL-инъекций. PDO поддерживает это.
  5. Предложите своим пользователям не использовать тот же пароль, который они используют для своей электронной почты. Напомните им, что если ваш сайт взломан и если они используют один и тот же пароль в обоих местах, кто-то может взломать их электронную почту.
greyfade
источник
+1 для HTTPS, так как через общедоступные сети WiFi все больше и больше трафика. Но я не согласен с точкой 3: 2 секунды слишком долго с точки зрения пользователей. 0,5 с. это просто хорошо, особенно если используются другие методы против грубой силы.
Арсений Мурзенко
Я запутался в точке № 4. Как избежать соглашения о экранировании данных с помощью mysql_real_escape_string? Все данные, представленные пользователем, не следует доверять и фильтровать соответствующим образом.
Chrisw
@ chrisw: Да, все вводимые пользователем данные должны обрабатываться так, как если бы они были вредоносными. Но когда вы используете параметризованные запросы, это, без исключения, лучший способ остановить внедрение SQL . Если вы не используете подготовленные и параметризованные запросы, вы уязвимы для внедрения SQL. mysql_real_escape_stringэто ложная безопасность - это не гарантия. Параметризованные запросы есть.
Greyfade
Я согласен теперь после того, как сделаю некоторые дальнейшие чтения в него. Функция: mysql_real_escape_string, как правило, в большинстве случаев безопасна, я не считаю это ОГРОМНЫМ обязательством, но я вижу, как использование подготовленных утверждений намного эффективнее.
Chrisw
1
Вы можете использовать PDO.
Феликс Дж
1

Используйте соленый односторонний хеш (предпочтительно SHA512, используя http://au2.php.net/manual/en/function.hash.php ) ... таким образом, если кто-то взломает вашу базу данных, даже если он знает соль они не могут извлечь пароли (без радужной таблицы, которая была бы слишком длинной для SHA512).

Используйте HTTPS.

Не посылайте подтверждения имени пользователя / пароля по электронной почте обратно пользователю при регистрации.

Если вы разрешаете куки для «Запомнить меня» - добавьте дополнительный логин для доступа к функциям администрирования и редактирования профиля.

Если пользователь неверно вводит пароль, не говорите, что он неверно вводил пароль (скажем, он всегда вводил «неправильное имя пользователя или пароль») - таким образом, меньше подсказок о том, какие действительные имена пользователей.

Попробуйте ввести псевдоним вместо входа в систему - таким образом, меньше пользователей будут отображать свое имя пользователя в списках пользователей.

HorusKol
источник
Полностью согласен с тем, что не следует отправлять электронные письма в виде простого текста по электронной почте. Я потерял счет раз, когда веб-сайты делают это. Если у вас есть 1 пароль для всех сайтов (чего, к счастью, нет), то потенциально все сайты взломаны. Такие сайты, вероятно, хранят пароли также в виде простого текста. вздох
баритонеук
1
  • Никогда не используйте алгоритмы хеширования MD5 или SHA1. Всегда придерживайтесь новых, таких как SHA512
  • Всегда используйте сильную случайно сгенерированную соль
  • Никогда не посылайте по электронной почте своим пользователям свои пароли, даже в случае «Забыли пароль»
  • Никогда не используйте функции mysql_ *. Они давно обесценились. Придерживайтесь PDO
  • Никогда не храните пароли в сессиях или куки
Робин Томас
источник
0

Вот один совет: убедитесь, что ваши файлы cookie не доступны с помощью JS, чтобы предотвратить кражу, см. Статью « Защита файлов cookie»: статья HttpOnly Джеффа Этвуда

... Благодаря продуманной конструкции некорректно сформированный URL просто пропускает дезинфицирующее средство. Окончательно обработанный код при просмотре в браузере загружает и выполняет скрипт с этого удаленного сервера.

... кто бы ни загружал эту страницу профиля с введенными сценариями, он просто невольно передал свои куки браузера на злой удаленный сервер!

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

Джеймс
источник