Які найкращі практики слід використовувати в сценарії входу в PHP?


27

Я хочу переписати свої сценарії для входу для веб-сайтів клієнтів, щоб зробити їх більш безпечними. Я хочу знати, які найкращі практики я можу втілити у цьому. Панелі керування, захищені паролем, мають їх велику кількість, але, здається, мало хто застосовує кращі практики щодо написання коду, швидкості та безпеки.

Я буду використовувати PHP та базу даних MYSQL.

Раніше я використовував md5, але бачу, що sha256 або sha512 буде краще (разом із захищеним хешем і сіллю).

Деякі скрипти входу записують ip-адресу протягом сеансу чи навіть агента користувача, але я хочу уникати цього, оскільки він не сумісний із проксі-серверами.

Я також трохи відстаю від найкращої практики використання сеансів у PHP 5 (останній раз, коли я прочитав, це був PHP 4), тому деякі найкращі практики з цим були б корисні.

Спасибі.


1
Киньте свій скрипт на codereview.SE!
Кріс

@Chris CodeReview допоможе в чіткості коду тощо. Ви точно не повинні їхати до них заради безпеки. Якщо що-небудь, вони майже завжди нагадують вам не «котити своє», що в основному є такою ж відповіддю, як і він збирається потрапити до будь-якого спільноти програмування на SE.
Альтернатекс

Відповіді:


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
@Brian Ortiz: Не завжди. Іноді корисно встановити ліміт. Якщо ви цього не зробите, чи перевіряєте ви, чи працює ваша програма будь-якої тривалості? Як? Якщо ви не тестуєте його, як ви можете бути впевнені, чи працює він? Натомість, встановлюючи обмеження на розумне значення, наприклад 100, ви можете легко перевірити пароль на 100 символів.
Арсеній Муренко

6
  1. Ваш сайт повинен використовувати HTTPS. Ні в якому разі не слід представляти сторінку входу або приймати вхід із нешифрованого з'єднання.
  2. Ваші файли cookie повинні бути обмежені лише HTTP і обмежуватись безпечними з'єднаннями, якщо ви використовуєте HTTPS.
  3. Процес входу повинен тривати не менше 2 секунд (1, якщо ви думаєте, що 2 секунди занадто довгі). Використовуйте захищений хеш, зберігаючи та перевіряючи паролі, і використовуйте сіль, важче здогадатися. Використовуйте, bcryptякщо можливо. В іншому випадку використовуйте інший вид ітераційного хешу.
  4. Ніколи не створюйте запити до вашої бази даних будь-яким способом, який вимагає використання таких функцій mysql_real_escape_string. Ніколи не використовуйте об'єднання рядків для створення вашого запиту. Використовуйте підготовлені параметризовані запити. Більшість, якщо не всі, драйвери БД для PHP підтримують це. Якщо ви не знаєте , як це зробити, витратити деякий час на навчання , як prepare, bindі з executeвикористанням будь-яких DB ви використовуєте. Це єдиний вірний спосіб убезпечити себе від ін'єкції SQL. PDO підтримує це.
  5. Закликайте своїх користувачів не використовувати той самий пароль, який вони використовують для своєї електронної пошти. Нагадайте їм, що якщо ваш сайт порушений і якщо вони використовують один і той же пароль в обох місцях, хтось може викрасти їх електронну пошту.

+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.

Не надсилайте підтвердження імені користувача / пароля електронною поштою назад, коли він реєструється.

Якщо ви дозволите файли cookie для «запам'ятати мене» - додайте додатковий логін для доступу до адміністрування та функцій редагування профілю.

Якщо користувач помилився з паролем, не кажіть, що він помилився з паролем (скажімо, що він завжди отримував "ім'я користувача або пароль неправильний") - таким чином, менше підказок про те, що є дійсними іменами користувачів.

Спробуйте застосувати ім'я екрана проти входу - таким чином менше користувачів відображатиме своє ім’я для входу в списки користувачів.


Повністю погоджуйтеся з тим, що не надсилати повідомлення електронним листом у звичайному тексті. Я втратив кількість разів, коли це роблять веб-сайти. Якщо у вас є 1 пароль для всіх сайтів (що, на щастя, у мене немає), потенційно всі веб-сайти можуть бути порушені. Такі веб-сайти, ймовірно, зберігають і паролі у простому тексті. зітхання
баритонеук

1
  • Ніколи не використовуйте алгоритми хешування MD5 або SHA1. Завжди дотримуйтесь нових, таких як SHA512
  • Завжди використовуйте сильну випадкову сіль
  • Ніколи не надсилайте електронним повідомленням своїх користувачів свої паролі, навіть у випадку "Забули пароль"
  • Ніколи не використовуйте функції mysql_ *. Вони довго знецінюються. Дотримуйтесь PDO
  • Ніколи не зберігайте паролі в сеансах чи файлах cookie

0

Ось одна порада: переконайтеся, що до ваших файлів cookie не можна отримати доступ до JS, щоб запобігти крадіжці, див. Захист файлів cookie: Стаття HttpOnly від Джеффа Етвуда

... Завдяки розумній конструкції, неправильно підібрана URL-адреса просто вдається проскочити повз дезінфікуючий засіб. Остаточний наданий код при перегляді в браузері завантажує та виконує скрипт із цього віддаленого сервера.

... хто завантажує цю сторінку профілю користувача, що вводиться скриптом, мимоволі передав файли cookie свого браузера на злий віддалений сервер!

Як ми вже встановили, щойно хтось має кукі-файли вашого веб-переглядача для певного веб-сайту, він, по суті, має ключі від королівства для вашої особи там ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.