Вопрос или проблема
В настоящее время я использую PostgreSQL с расширением pgcrypto
для хранения и проверки паролей пользователей. Когда пользователь входит в систему, я сравниваю введенный пароль с сохраненным хэшем с помощью следующего запроса:
SELECT id FROM users
WHERE email="[email protected]"
AND password = crypt('введенный_пароль', password);
Примечание: В этом примере пароль передается как константа, но в реальном приложении используется метод, свободный от SQL-инъекций.
Я понимаю, что этот подход может быть небезопасным против атак по времени из-за использования оператора =
в запросе.
Тем не менее, я хочу подтвердить с экспертами по безопасности, действительно ли этот метод безопасен и есть ли какие-либо потенциальные уязвимости или лучшие практики, о которых мне следует знать.
Вопрос:
Безопасно ли использование crypt
таким образом против атак по времени?
Спасибо за ваши мнения!
Нет, прямое сравнение CHAR
или VARCHAR
в PostgreSQL не безопасно по времени.
PostgreSQL внутренне использует функцию memcmp
из стандартной библиотеки C. По крайней мере в GNU C Library (glibc), функция возвращает результат сразу, как только встречает символ, который не совпадает – и трудно представить какую-либо другую реализацию.
Если вы хотите безопасное по времени сравнение, вам нужно реализовать его самостоятельно. Вы можете, например, пройтись по всем символам и сравнить их, не возвращаясь раньше времени. Либо вы можете вычислить код аутентификации сообщения на основе хэша (HMAC) для обоих операндов и сравнить эти HMAC. Поскольку злоумышленник не может самостоятельно вычислить HMAC (если он не компрометировал ключ), различия во времени ничего полезного о хэшах паролей не раскрывают.
Обратите внимание, что есть и другие проблемы:
- Функция
crypt
и ее алгоритм на самом деле устарели. Только bcrypt (называемыйbf
вpgcrypto
) все еще более-менее приемлем, но с 1999 года были разработаны более сильные алгоритмы, такие как Argon2. - Когда вы хэшируете пароли в системе базы данных, это означает, что вам сначала нужно передать пароль в открытом виде. Это значительно увеличивает риск случайной утечки пароля, например, через журнал запросов или при передаче.
Гораздо лучше хэшировать пароль в приложении. Это также позволяет вам использовать более современные хэш-алгоритмы (такие как Argon2), которые в настоящее время не реализованы в pgcrypto
.
Ответ или решение
Использование функции crypt
в PostgreSQL для сравнения паролей действительно не обеспечивает защиту от атак по времени. Ваша первоначальная идея о том, что использование оператора =
может сделать ваш подход уязвимым, верна.
Причины уязвимости:
-
Сравнение строк: PostgreSQL использует функцию
memcmp
для сравнения строковых значений, что приводит к тому, что сравнение возвращает результат как только встречает первый несовпадающий символ. Это создает временную зависимость: если злоумышленник знает, что некоторые символы совпадают, он сможет оценить, сколько времени потребовалось на выполнение запроса, что потенциально может дать ему подсказки о пароле. -
Библиотеки и реализация: В частности, в GNU C Library (glibc),
memcmp
прекращает выполнение при обнаружении первого несовпадения. Подобное поведение наблюдается во многих реализациях, что делает любые сравнения незащищенными от атак по времени.
Решения:
Чтобы защитить свою систему от атак по времени, вам необходимо реализовать безопасное сравнение самостоятельно. Вот несколько подходов:
-
Безопасное посимвольное сравнение: Вы можете сравнивать символы последовательно, не прерывая выполнение функции при первом несовпадении, таким образом, время выполнения не будет зависеть от значения символов, а только от их количества.
-
Использование HMAC: Рассмотрите возможность использования хешированного кода аутентификации на основе сообщения (HMAC) для сравнения. Например, вы можете создать HMAC для обоих операндов и сравнить их. Это предотвращает утечку информации о правильности пароля, даже если злоумышленник имеет доступ к результатам запроса.
Дополнительные замечания:
-
Устаревшие алгоритмы: Алгоритм, используемый в
crypt
, считается устаревшим. Хотя bcrypt, который доступен вpgcrypto
, еще может быть приемлемым выбором, современные алгоритмы, такие как Argon2, обеспечивают гораздо более высокий уровень безопасности и устойчивости к атакам. -
Секьюрность передачи паролей: При хешировании паролей на стороне базы данных вам необходимо передавать исходный пароль, что увеличивает риск его утечки через журналы запросов или в процессе передачи. Храните пароли в зашифрованном виде и осуществляйте хеширование на уровне приложения, что позволяет уменьшить объем передаваемых данных и повысить безопасность.
Рекомендации:
Рекомендуется использовать современные библиотеки для хеширования и управления паролями на уровне приложения. Это позволит вам применять современные методы, такие как Argon2, и избежать уязвимостей, связанных с сравнениями по времени в базах данных.
Вывод: использование crypt
для сравнения паролей в PostgreSQL не является безопасным подходом из-за уязвимости к атакам по времени. Внедрение безопасных методов сравнения и использование современных алгоритмов хеширования — важные шаги к улучшению безопасности вашего приложения.