Як треба хешировать паролі і як не треба

В черговий раз закінчуючи проводити аудит інформаційної безпеки веб-проекту, моя особиста бочка з гнівом переповнилася обуренням так, що воно перелилося через край в цей пост.

Постараюся дуже лаконічно і швидко окреслити ситуацію з хешамі.

Матчастину (коротка)


Hash = хеш функція - (згортка) функція однозначного відображення рядка (будь-якої довжини) на кінцеве безліч (рядок заданої довжини).
Саме число (рядок) хеш - результат обчислення хеш-функції над даними.
Існують криптографічні та некріптографіческіе (класифікуються окремо, до них відносяться, наприклад, контрольні суми) хеш-функції.

Для криптографічних хеш є три додаткових умови, які відрізняють їх від всіх інших:

  • Незворотність: для заданого значення хеш-функції m повинно бути обчислювально нездійсненно знайти блок даних X, для якого H (X) = m.
  • Стійкість до колізій першого роду: для заданого повідомлення M має бути обчислювально нездійсненно підібрати інше повідомлення N, для якого H (N) = H (M).
  • Стійкість до колізій другого роду: має бути обчислювально нездійсненно підібрати пару повідомлень

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

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

Нижче перераховані вимоги, яким ваш хеш в базі повинен задовольняти:

  • стійкість до атак перебору (прямий перебір і перебір по словнику)
  • неможливість пошуку однакових паролів різних користувачів по Хешам

Для виконання першої вимоги потрібно використовувати стійкі в даний час (а не в 90-х роках!) Хеш-функції.
Для виконання другого - до паролю перед хешированием додається випадкова рядок (сіль). Таким чином, у двох користувачів з паролем «123456» будуть різні солі «соль1» і «соль2», а відповідно і хеш-функції від «123456соль1» і «123456соль2» в базі теж будуть різні.

Тепер трохи про систему зберігання - і сіль і сам хеш зберігаються в базі даних.
Тобто отримавши доступ до СУБД, зловмисник отримує і значення хешів і солі.

Використовуйте локальний параметр!


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

Це по суті «друга сіль» дописується до всіх (паролів + сіль) конструкцій, і є однаковою для всіх хешів в базі. У чому ж трюк? У тому, що локального параметра в базі немає. Це константа системи, яка зберігатися в пам'яті програми, куди вона потрапляє з конфіга (будь-яким способом, тільки не з бази).

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

Єдиний раз ми (ONsec) ламали хеші з локальним параметром, виробивши при цьому тактику атаки на сам локальний параметр (реєструємося в додатку, потім шукаємо в базі свій хеш, сіль (свій пароль ми і так знаємо) і перебираємо ЛП). І марно. На довжинах 16+ байт для сучасних функцій хешування - це дуже дорого по залізу. У підсумку простіше виявилося скомпрометувати систему аутентифікації (проставити собі role = admin в базі через UPDATE;))

Захищайте свої сховища надійно і грамотно!

висновок


Буду реалістом - природно, ніхто не стане переписувати свої проекти заради «якихось» хешів. Але нові проекти можна писати на scrypt / bcrypt. А також - впроваджуйте локальний параметр навіть на слабких MD5 - він правда допомагає, перевірено :)

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

У висновку, привожу швидкості перебору хешів (одиниці вимірювання - мегахеші в секунду, тобто кількість), отриманих на картці AMD Radeon 7990 вартістю менше $ 1000 (навіть за старим курсом):

Як треба хешировать паролі і як не треба

Хешування паролів в PHP 5.5 з використанням нового API
Використання BCrypt є загальноприйнятим і найкращим способом для хешування паролів, але велика кількість розробників і раніше використовують старі і слабкі алгоритми, на кшталт MD5 і SHA1. Деякі розробники навіть не використовують сіль для хешування. Новий API хешування в PHP 5.5 ставить собі за мету привернути увагу до BCrypt, спрощуючи роботу з

Як треба хешировать паролі і як не треба

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

Як треба хешировать паролі і як не треба

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

Як треба хешировать паролі і як не треба

Трохи про хешах безпечно зберігати паролів
Привіт, Хабр! Сьогодні, в процесі розробки системи аутентифікації для свого проекту переді мною постав вибір - в якому вигляді зберігати паролі користувачів в базі даних? В голову приходить безліч варіантів. Найбільш очевидні: Зберігати паролі в БД у відкритому вигляді. Використовувати звичайні хеши crc32, md5, sha1.

Як треба хешировать паролі і як не треба

Про догми в криптографії
Вчора я нарешті випустив першу публічну версію Lamer News, це одночасно і реальний приклад використання Redis у вигляді сайту напободіе Hacker News, і проект абсолютно незалежного сайту про новини зі світу програмування. Проект був добре прийнятий співтовариством, і був в топі HN протягом деякого часу. Дякую за зворотній зв'язок.