Использован уязвимый алгоритм хеширования
Хеширование — это особое преобразование любого объема информации, в результате которого получается некое значение (хеш) — уникальная короткая символьная строка, которая присуща только этому массиву входящей информации. В криптографических целях хеширование используется для сохранения данных в зашифрованном виде, однако использование устаревших алгоритмов может серьезно снизить безопасность приложения.
Приведем некоторые свойства хеш-функций, на основе которых выбирают правильный алгоритм хеширования:
- Детерминированность: одинаковый вход всегда должен давать одинаковый результат.
- Скорость: хеширование должно быть достаточно быстрым для обработки больших объемов данных, но не настолько быстрым, чтобы стать легкой целью для атак.
- Сложность обратного вычисления: невозможность восстановления оригинальных данных из хеша.
- Чувствительность к изменениям: небольшие изменения во входных данных должны приводить к значительным изменениям хеша.
- Устойчивость к коллизиям: невозможность найти два разных набора данных, имеющих одинаковый хеш.
Основными врагами таких алгоритмов являются огромные базы данных уже посчитанных хешей для очень большого количества разных строк. Такие базы данных, называемые радужными таблицами, содержат результаты хеширования общих паролей и позволяют злоумышленникам легко находить исходные значения по хешам. Существуют сервисы, которые предоставляют доступ к таким таблицам и позволяют искать хеши простым запросом. Например, если приложение хранит ПИН-код пользователя, используя простой SHA-1(pin)
, этот хеш можно легко найти в Интернете, что приведет к утечке ПИН-кода.
Пример недостатка использования SHA-1
Другой проблемой являются коллизии, когда два абсолютно разных значения после преобразования дают одинаковый хеш. Как правило, алгоритмы хеширования признаются устаревшими после того, как становится возможным подобрать данные для успешной коллизии за приемлемое время. Например, алгоритм SHA-1 признан небезопасным, так как возможна генерация коллизий. Хорошим примером является данный репозиторий, который показывает, как два документа (оригинальный и измененный) могут иметь одинаковое значение хеша.
Рекомендации по улучшению безопасности хеширования
Чтобы избежать подобных проблем, используйте соль при хешировании. Соль — это случайные данные, добавляемые к входным данным перед хешированием, что существенно повышает энтропию и делает использование радужных таблиц практически бесполезным. Соль должна быть:
- Уникальной для каждого хеша. Это помогает защитить одинаковые пароли от одинаковых хешей.
- Случайной и длинной. Чем длиннее соль, тем труднее злоумышленнику создать радужные таблицы.
Алгоритмы хеширования, которые НЕ следует использовать
- MD5: не подходит для любых криптографических целей из-за слабой устойчивости к коллизиям и возможности быстрого вычисления радужных таблиц.
- SHA-1: также устарел для любых криптографических целей, поскольку коллизии для него уже продемонстрированы на практике.
Рекомендованные алгоритмы
Для современных приложений рекомендуется использовать такие алгоритмы, как SHA-256 или SHA-3 в сочетании с солью. Для защиты паролей также можно использовать специализированные функции PBKDF2, bcrypt или scrypt, которые включают в себя механизмы соль и настройку количества итераций, что делает атаки по словарю гораздо менее эффективными.
Практические рекомендации по генерации соли и случайных данных
Примечание
- При генерации случайных данных для любых криптографических целей (соль, вектор инициализации, ключ) следует использовать
SecureRandom
, а не обычныйRandom
, посколькуSecureRandom
обеспечивает гораздо более высокую степень случайности. - При создании вектора инициализации и соли не следует использовать тривиальные данные, такие как заполнение массива нулями или использование других значений с низкой энтропией.
- При генерации ключа (например, PBE, PBKDF2) следует устанавливать количество итераций как можно большим, исходя из возможностей аппаратной части и требований безопасности. Обычно рекомендуется значение не менее 10 000 итераций.
- Нельзя использовать пароль как ключ шифрования напрямую (без использования алгоритмов генерации ключа).
Примеры ошибок при использовании соли
Использование слова в качестве соли
Иногда разработчики в качестве значения соли используют набор байт, являющийся словом или фразой естественного языка. Такая ошибка свидетельствует, что значение соли захардкожено в коде или ресурсах приложения, а не вычисляется случайным образом. Это делает соль предсказуемой и легко подбираемой злоумышленником.
Использование соли с низкой энтропией
Неправильная практика — использовать соль, заполненную, например, нулями [0, 0, 0, …]
или другими повторяющимися данными. Это делает соль предсказуемой и не добавляет никакой дополнительной защиты, поскольку такая соль не увеличивает энтропию хеша.
Дополнительные ссылки для изучения
- Java Encryption IV – Baeldung
- Secure Data in Android: Initialization Vector – ProAndroidDev
- Android Security and Fingerprint – Medium
- Android Keystore System – Android Developers
- Using the Android Keystore System to Store Sensitive Information – Medium
- Уязвимости в мобильных приложениях – Хабр
- Безопасность Android-приложений – Хабр
- Android Security Examples – GitHub
- Padding Oracle Attack Explained – GitHub
- Padding Oracle Attack – Хабр
- Padding Oracle Attack – Wikipedia