Найкращі практики: засолювання та перець паролів?


145

Я натрапив на дискусію, в якій дізнався, що те, що я робив, насправді не солив паролі, а перекладав їх, і з тих пір я почав виконувати обидві функції:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

Ігнорування обраного алгоритму хешу (я хочу, щоб це було обговоренням солей та перців, а не конкретних алгоритмів, але я використовую безпечний), це безпечний варіант чи я повинен робити щось інше? Для незнайомих із умовами:

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

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

Чи є щось, чого мені не вистачає, і соління та перець моїх паролів найкращий варіант для захисту безпеки мого користувача? Чи є якийсь потенційний недолік безпеки, щоб зробити це таким чином?

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


3
Чи не зовсім дублікат, але дуже пов'язано: stackoverflow.com/questions/16594613 / ...
ircmaxell

2
Дублікат між веб-сайтами: security.stackexchange.com/q/3272/2113
Jacco

Відповіді:


307

Гаразд. Бачачи, як мені потрібно писати про це знову і знову , я зроблю одну останню канонічну відповідь лише на перець.

Очевидний перелік перців

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

Ось чому так багато людей вважають, що перець - хороша ідея. Це має сенс".

Реальність перців

У сферах безпеки та криптовалюти "сенсу" недостатньо. Щось повинно бути доказовим і має сенс, щоб це можна було вважати безпечним. Крім того, вона має бути реалізованою в ремонтопридатному способі. Найбезпечніша система, яку неможливо підтримувати, вважається незахищеною (адже якщо якась частина цієї безпеки порушиться, вся система розвалиться).

І перець не підходить ні для перевірки, ні для ремонту моделей ...

Теоретичні проблеми з перцем

Тепер, коли ми поставили сцену, давайте подивимося, що не так з перцями.

  • Подача одного хешу в інший може бути небезпечним.

    У вашому прикладі ви робите hash_function($salt . hash_function($pepper . $password)).

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

    Ось чому такі алгоритми, як PBKDF2, використовують для комбінування спеціальних операцій (hmac у такому випадку).

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

    Хоча це може здатися чисто теоретичним, насправді це не так. Наприклад, Bcrypt не може приймати довільні паролі . Тому передача bcrypt(hash(pw), salt)дійсно може призвести до набагато слабшого хешу, ніж bcrypt(pw, salt)якщо hash()повертає двійковий рядок.

  • Працюючи проти дизайну

    Спосіб розробки bcrypt (та інших алгоритмів хешування паролів) - це робота з сіллю. Поняття перцю так і не було введено. Це може здатися дрібницею, але це не так. Причина в тому, що сіль не є секретом. Це лише значення, яке може бути відоме зловмиснику. З іншого боку, перець, за власним визначенням, є криптографічним секретом.

    Поточні алгоритми хешування паролів (bcrypt, pbkdf2 тощо) призначені для отримання лише одного секретного значення (пароля). Додавання ще одного секрету в алгоритм взагалі не вивчалося.

    Це не означає, що це не безпечно. Це означає, що ми не знаємо, чи безпечно це. І загальна рекомендація щодо безпеки та криптографії полягає в тому, що якщо ми не знаємо, це не так.

    Тому, поки алгоритми не будуть розроблені та перевірені криптографами для використання з таємними значеннями (перцем), поточні алгоритми не повинні використовуватися з ними.

  • Складність - це ворога безпеки

    Вірите чи ні, складність - це ворог безпеки . Створення алгоритму, який виглядає складним, може бути безпечним, а може і не бути. Але шанси досить великі, що це не безпечно.

Значні проблеми з перцем

  • Це неможливо

    Ваша реалізація перців виключає можливість повороту перцевого ключа. Оскільки перець використовується на вході до функції в одну сторону, ви ніколи не можете змінювати перець протягом життя значення. Це означає, що вам потрібно буде придумати кілька непростих хаків, щоб підтримати обертання клавіш.

    Це надзвичайно важливо, оскільки це потрібно, коли ви зберігаєте криптографічні таємниці. Немає механізму повороту клавіш (періодично і після порушення) - це величезна вразливість безпеки.

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

    Це, в основному, робить ваш підхід негайним відмовою.

  • Це вимагає, щоб ви прокатали власну криптовалюту

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

    Будь-який, від найрозумнішого аматора до найкращого криптографа, може створити алгоритм, який він сам не може зламати.

    НІКОЛИ не прокатуйте власну криптовалюту ...

Кращий шлях

Отже, з усіх вищеописаних проблем є два способи вирішення ситуації.

  • Просто використовуйте алгоритми у міру їх існування

    Якщо ви правильно використовуєте bcrypt або scrypt (з високою вартістю), всі паролі, крім самих слабких словників, повинні бути статистично безпечними. Поточний рекорд для шифрування bcrypt вартістю 5 становить 71 кш хеш за секунду. З такою швидкістю навіть шість випадкових паролів знадобиться років, щоб зламати. І якщо врахувати, що моя мінімальна рекомендована вартість - 10, це зменшує хеші в секунду в 32 рази. Тому ми говоримо лише про 2200 хешей за секунду. З такою швидкістю навіть деякі словникові фрази або модифікатори можуть бути безпечними.

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

  • Зашифруйте хеш-вихід до зберігання

    У царині безпеки існує алгоритм, призначений для обробки всього, про що ми говорили вище. Це блок-шифр. Це добре, тому що він оборотний, тому ми можемо обертати клавіші (так! Ремонтопридатність!). Це добре, тому що використовується як задумано. Це добре, оскільки не дає користувачеві ніякої інформації.

    Давайте ще раз подивимось на цей рядок. Скажімо, що зловмисник знає ваш алгоритм (який необхідний для безпеки, інакше це безпека через неясність). При традиційному підході до перцю зловмисник може створити дозорний пароль, і оскільки він знає сіль і вихід, він може жорстоко примусити перець. Гаразд, це дальний постріл, але це можливо. З шифром нападник нічого не отримує. А оскільки сіль є рандомізованим, дозорний пароль навіть не допоможе йому / їй. Тож найкраще, що їм залишається, - це атакувати зашифровану форму. Це означає, що спочатку вони повинні атакувати ваш зашифрований хеш, щоб відновити ключ шифрування, а потім атакувати хеші. Але існує багато досліджень атаки шифрів, тому ми хочемо на це покластися.

TL / DR

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


6
Дякую за включення останньої частини шифрування хеш-значень, це відповідь, з якою я можу повністю погодитися. Якщо шифрування стане частиною вашого пароля api , не було б причин не використовувати його, тому, можливо,… (я б хотів написати документацію на це)
martinstoeckli

2
@martinstoeckli: Я б не погодився додати крок шифрування до спрощеного API хешування. Причина в тому, що зберігати секрети (ключі) набагато важче, ніж люди усвідомлюють, і застрелити себе в ногу досить легко. Для 99,9% користувачів там сирого bcrypt більш ніж достатньо для всіх, крім найпростіших паролів ...
ircmaxell

7
@ircmaxell - З іншого боку, ви нічого не втратите. У гіршому випадку, коли ключ стане відомим, зловмисник повинен все-таки зламати хеш BCrypt (така ж ситуація, як і без шифрування). Це не те саме, що зберігати ключ для шифрування даних, це стосується додавання секрету на стороні сервера. Навіть жорсткий код захищає ці слабкі паролі, якщо зловмисник не має контролю над сервером / кодом. Така ситуація не є рідкістю: окрім SQL-ін'єкції, також викинуті резервні копії, відмовлені сервери… можуть призвести до цієї ситуації. Дуже багато користувачів PHP працюють на розміщених серверах.
martinstoeckli

2
@martinstoeckli Я повинен був би погодитися з ircmaxwell тут, я не думаю, що шифрування належить до api пароля. Хоча, можна відзначити, що для максимальної безпеки шифрування ваших хесів - це додаткове положення, яке можна використовувати.
foochow

У мене виникає питання щодо шифрування виводу перед зберіганням. Якщо я не помиляюся, ключі шифрування, як правило, використовуються для шифрування повідомлень однозначно або швидко. Якщо у вас є 200 000 паролів користувачів, усі зашифровані одним і тим же ключем і зберігаються разом, чи не полегшує атаку ключ? Тепер у вас 200 000 повідомлень порівняно з 1 або 2.
AgmLauncher

24

Кулак нам слід поговорити про точну перевагу перцю :

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

Типовим сценарієм буде SQL-ін'єкція, викинуті резервні копії, відмовлені сервери ... Ці ситуації не такі рідкісні, як це звучить, і часто не під вашим контролем (сервер-хостинг). Якщо ви використовуєте ...

  • Унікальна сіль на пароль
  • Алгоритм повільного хешування, як BCrypt

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

Друге питання - як застосувати перець ?

Часто рекомендований спосіб застосувати перець - поєднувати пароль і перець перед тим, як передати його до хеш-функції:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

Однак є ще один кращий спосіб:

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

Це не тільки дозволяє додати секрет на стороні сервера, але також дозволяє обміняти $ serverSideKey, якщо це необхідно. Цей метод передбачає трохи більше роботи, але якщо код колись існує (бібліотека), немає підстав не використовувати його.


Отже, ви скажете, що перець додає безпеку лише сіллю, коротше? Дякуємо за допомогу щодо того, як реалізувати.
Glitch Desire

1
@LightningDust - Так, для слабких паролів, якщо перець залишається в секреті. Це пом'якшує деякі чітко визначені типи загроз.
martinstoeckli

@martinstoeckli, безумовно, хороший спосіб здійснити це. Приємно бачити, що хтось із певним досвідом безпеки підтримує цей метод. Чи був би AES_ENCRYPT($passwordHash, $serverSideKey)виклик MySQL також відповідним способом реалізації цього?
foochow

1
@Foo_Chow - Я не знаю реалізації функції MySQL, але, здається, вони використовували режим EBC, щоб уникнути IV-вектора. Разом з відомим простим текстом (хеш-значення завжди починаються з одних і тих же символів) це може бути проблемою. На своїй домашній сторінці я опублікував приклад реалізації, який обробляє це шифрування.
martinstoeckli

@martinstoeckli цікаві, не надто знайомі з поняттями; однак здається, що IV бажано отримати найбільш надійні результати. Здається, це не додасть великих витрат на додаткову вигоду.
foochow

2

Сенс солі та перцю полягає у збільшенні вартості попередньо обчисленого пароля, що називається веселковою таблицею.

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

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

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

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


Тож чи солі + перець пропонують більшу безпеку, ніж просто сіль? Або мені буде краще кинути перець і виконувати більше ітерацій скріпту?
Glitch Desire

2
Головне в таблиці веселки - це те, що ви не створюєте його для конкретної атаки, ви завантажуєте попередню. Існують довгі таблиці з веселками для популярних хеш-алгоритмів лише в Google!
Річард

1
@LightningDust Я сам не можу придумати жодної причини. Однак Річард в іншому потоці придумав один. Ви можете сховати перець у своєму вихідному коді, а це означає, що вам потрібно отримати доступ до іншого місця, до якого зловмисник повинен отримати доступ, лише для того, щоб зібрати веселковий стіл разом.
Арон

@Aron - Ну ось що я подумав, оскільки у нас є сервери додатків окремо від серверів баз даних (тобто якщо ви потрапили rootна наш db-сервер, ви все ще не маєте доступу до нашого сервера додатків), що приховує перець у вихідному коді (у наш конфігураційний файл) забезпечив би додаткову безпеку.
Glitch Desire

1

Неможливо зберігати твердокодированное значення у вихідному коді як такого, що стосується безпеки. Це безпека через незрозумілість.

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


1
Це зробить попередньо обчислену таблицю веселки для таблиці несолоного пароля марною. Коротше кажучи, навіть якщо зловмисник знав ваш перець, йому знадобиться створити новий столик з веселки.
Арон

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

Солі - це одна з функцій, навіть успішно примусовий пароль дасть вам лише цей пароль, і не допоможе вам отримати саме значення перцю.
Glitch Desire

1
@LightningDust Я думаю, ти маєш на увазі "Хеші - це функції, що займаються". Так, неможливо з'ясувати сіль та / або перець із безпечного хешу (адже це визначення безпечного хешу).
Арон

6
@Aron Security Через непрозорість може бути дійсною технікою, що використовується як шар захисту. Справа в тому, що на нього ніколи не слід покладатися як на захист, а натомість використовувати його для "уповільнення нападника". Якби це не було, щось подібне до медового горщика не використовувалося б. Натомість ми можемо ефективно використовувати безпеку через невідомість, щоб допомогти повільним зловмисникам знижувати, доки ми не покладаємось на неї для безпеки нашого додатку.
ircmaxell
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.