Как испортить безопасность паролей, следуя советам с Хабра

в 20:40, , рубрики: bcrypt, hash, password security, информационная безопасность, хабр, метки: , , ,

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

Суть

Перец — такая глобальная случайная строка, которая дописывается ко всем паролям (помимо соли). Она секретна (в отличии от соли). Таким образом, получив базу, узнать пароли становится невозможно. И все, казалось бы, хорошо…

Проблема инвалидации

Перец глобален, по своей сути. Если Вы захотите его сменить, например, в случае утечки, то Вам придется сменить все пароли.

Проблема хранения

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

Проблема «иллюзии защищенности»

Перец, как бы «усиливает» слабый пароль, но только в недрах системы. Через форму логина пароль «asdf» подбирается все так же легко. Слабый пароль — это слабый пароль, как бы Вы себя не обманывали.

Проблема реализации

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

Demo time

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

<?php

// Наш перец. Невероятно непредсказуем. Хакеры в панике.
$pepper = '.dQUEtby7P35;k"5EhPB<j.;,9hqvs!(<"B]=#dBfhnyaN)v>8Z_bs%YJW/u~{w5:4B!s5F>';

// Наш пользователь - молодец. Пароль чертовски хорош.
$password = 'E&z89Usr?R7VF.^';

// Хешируем!
$hash = password_hash($pepper . $password, PASSWORD_BCRYPT);
var_dump($hash);
//string(60) "$2y$10$0V95jRy9I.P3t7YRiMHT3O7JEveN1Gya/LbvNJ.H6K1mVPxPFRsUm"
// У Вас будет другой хеш, т.к. соль генерируется автоматически

А теперь, логин (следите за руками!):

<?php

// Наш глобальный перец
$pepper = '.dQUEtby7P35;k"5EhPB<j.;,9hqvs!(<"B]=#dBfhnyaN)v>8Z_bs%YJW/u~{w5:4B!s5F>';

// Хеш нашего пользователя (подставьте свое значение)
$hash = '$2y$10$0V95jRy9I.P3t7YRiMHT3O7JEveN1Gya/LbvNJ.H6K1mVPxPFRsUm';

// Нет! Это же неправильный пароль! Ты же не сможешь войти!
$password = 'habrahabr';

// Проверяем соответствие хеша и пароля
echo password_verify($pepper . $password, $hash) ? 'Login OK' : 'Wrong password';
// Login OK
// WTF???

Таким вот нехитрым способом мы помножили всю нашу защиту на ноль.

Автор: truezemez

Источник

Поделиться

* - обязательные к заполнению поля