09 окт. 2025 г.·3 мин. чтения

Аудит хранения паролей: хеширование, соль и безопасная миграция

Узнайте, как провести аудит хранения паролей в унаследованном коде: проверить хеширование, соль и pepper, и безопасно обновлять хеши при следующем входе.

Аудит хранения паролей: хеширование, соль и безопасная миграция

Что проверяет аудит хранения паролей (и почему это важно)

Правильное хранение паролей — это простая идея: если кто‑то похитит вашу базу пользователей, эти пароли всё равно нельзя будет использовать.

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

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

Если у злоумышленников есть слабые хеши паролей, они могут запускать оффлайн‑перебор. Им не нужно обращаться к вашим серверам или триггерить лимиты; они просто пробуют варианты на своих машинах до успеха. Сломав один пароль, часто проверяют его в других сервисах, потому что пользователи повторно используют пароли.

Хорошее хранение паролей обычно включает:

  • Современный медленный алгоритм хеширования паролей (не общий хеш вроде MD5 или SHA‑1).
  • Уникальную случайную соль для каждого пароля, хранимую рядом с хешем.
  • Опциональный pepper: отдельный секрет вне базы данных.
  • Явное версионирование, чтобы можно было менять настройки без ломки входа.
  • Отсутствие случайных утечек (логи, аналитика, сообщения об ошибках, бэкапы).

Самая безопасная последовательность — сначала аудит, потом миграция. Аудит определяет, что у вас есть сегодня (алгоритм, настройки, где лежит код, как работают сбросы), а затем вы выбираете план обновления.

Обычный план — «rehash при следующем входе»: пользователи продолжают входить как обычно, а когда пароль успешно проверен, вы обновляете их хеш до нового стандарта.

Срочные тревожные сигналы, которые легко заметить в унаследованном коде

Не нужно переписывать всё, чтобы найти самые большие риски. Быстрый аудит часто начинается с простого поиска, который покажет, обрабатываются ли пароли небезопасно.

Самый тревожный сигнал — всё, что позволяет восстановить пароль. Если вы видите пароли, сохранённые прямо в колонке базы, залогированные в консоли, отправленные в аналитику или «зашифрованные» обратимо (например, AES с сохранённым ключом), рассматривайте это как инцидент. Пароли должны храниться только как односторонние хеши.

Ещё одна распространённая проблема — использование быстрых хешей. Может быть видно MD5, SHA‑1 или простой SHA‑256, применённый к паролю. Даже если он «выглядит как хеш», быстрые алгоритмы созданы для скорости и легко ломаются в масштабе. Если в коде написано hash(password) и ничего больше, это сильный признак неправильного использования функции хеширования паролей.

Быстрые проверки, которые ловят большинство серьёзных проблем:

  • Упоминания md5, sha1, sha256(password) или вспомогательных методов вроде "encryptPassword".
  • Хеши одинаковой длины и формата без признаков пер‑пользовательской соли.
  • Пароли или токены для сброса, попадающие в логи, отчёты об ошибках или дампы базы.
  • Секреты (ключи JWT, пароли БД, PEPPER=...) захардкожены в репозитории или конфиге.
  • Код входа, предпологающий только один формат хеша и не имеющий пути обновления.

Отсутствие или сломанная соль иногда тонко проявляется, но вы быстро заметите проблему, если знаете, где смотреть. Если у двух пользователей с одинаковым паролем одно и то же сохранённое значение, значит соль не работает правильно (нет соли, глобальная соль или предсказуемая соль). Здоровая система даёт разные результаты для одинаковых паролей.

Практический пример: вы унаследовали Node‑приложение и видите колонку users.password, заполненную 64‑значными hex‑строками. Хендлер входа делает sha256(req.password) и сравнивает с базой. Это «работает», но уязвимо и не даёт безопасного пути к улучшению без учёта нескольких форматов хеша.

Наконец, проверьте, может ли поток входа обработать изменения. Если код не умеет проверять устаревшие хеши и потом перехешировать с более сильным методом при следующем успешном входе, обновления рискованны и могут привести к блокировкам.

Картирование мест, где обрабатываются пароли и потоки сброса

Аудит идёт быстрее, если начать с простой карты: все места, где пароль или токен сброса создаётся, отправляется, обрабатывается или хранится. В унаследованном коде рисковые участки зачастую не в папке «auth»: они разбросаны по формам UI, API‑маршрутами, фоновых задачам и административным инструментам.

Начните с перечисления каждой точки входа, через которую пароль может попасть в систему, затем подтвердите каждую из них в коде и в продакшн‑конфигурациях. Частые места: регистрация, вход (включая обходные пути SSO), сброс и восстановление пароля, админ/поддержка и импорты или миграции (CSV‑загрузки, синхронизация CRM, seed‑скрипты).

Далее найдите, где в базе хранится связанная с паролем информация. Проверьте очевидные колонки (password, password_hash, hashed_password), а также старые таблицы и теневые копии (например, users_legacy, которые ещё может читать фоновая задача). Если есть несколько полей для хеша пароля, отметьте, какое именно используется при входе.

Логирование — ещё один распространённый источник утечек. Ищите в коде и в настройках мониторинга всё, что может захватить чувствительные значения: request logs, события аналитики, отчёты об ошибках и debug prints. Реалистичная ошибка: обработчик неудачного входа логирует полное тело запроса «для отладки», тихо отправляя открытые пароли в логи.

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

Наконец, обозначьте границы сервиса. Отметьте все компоненты, которые касаются аутентификации: клиент, API‑шлюз, сервис аутентификации, фоновые воркеры (email, SMS) и любые сторонние провайдеры идентификации. В AI‑сгенерированных проектах часто находят лишние эндпоинты, оставшиеся после итераций, поэтому включите старые маршруты и отключённые feature‑флаги в сканирование.

Подтвердите алгоритм хеширования и его настройки

Бесплатный аудит хранения паролей
Мы проверим ваши хеши, соль, поток сброса пароля и журналы на предмет реальных рисков утечки.

Аудит хранения паролей начинается с прямого вопроса: вы используете функцию хеширования паролей или общий хеш?

Если вы видите MD5, SHA‑1, SHA‑256 или что‑то, описанное как «encrypt password», считайте это серьёзной проблемой. Эти инструменты не предназначены, чтобы замедлять атакующего.

Предпочитайте специализированные хеши паролей: Argon2id, bcrypt или scrypt. Они сделаны так, чтобы взлом стоил дорого, так что слитые хеши сложнее превратить в реальные пароли.

Как понять по хешу, что у вас применяется

Большинство систем сохраняют алгоритм и настройки внутри строки хеша, поэтому быстрого взгляда на значение в базе часто достаточно.

Типичные паттерны:

  • Argon2id часто начинается с $argon2id$ и содержит параметры памяти и итераций.
  • bcrypt часто начинается с $2a$, $2b$ или $2y$ и содержит cost вроде 10 или 12.
  • scrypt может содержать $scrypt$ или параметры N, r, p в зависимости от библиотеки.

Если вы видите фиксированную hex‑строку (например, 32 или 64 hex символа) без $‑разделителей, это может быть общий хеш или кастомная схема, требующая более глубокого обследования.

Проверяйте настройки, а не только имя

Выбор алгоритма — лишь половина истории. Argon2id может быть слабым при малом объёме памяти. bcrypt — слабым при низком cost.

Найдите, где задаётся фактор работы (work factor) и можно ли менять его без деплоя. Здоровые настройки держат параметры в конфиге, используют встроенный verify метода библиотеки (а не ручные сравнения строк) и сравнивают в константное время.

Также убедитесь, что у эндпоинта входа есть базовые защиты: rate limiting по аккаунту и по IP, а также разумные правила блокировок. Короткие временные блокировки обычно безопаснее постоянных.

Часто задаваемые вопросы

Что на самом деле проверяет аудит хранения паролей?

Вы проверяете, позволит ли украденная база пользователей восстановить реальные пароли. Хорошее хранение использует медленный односторонний хеш пароля с уникальной солью для каждого пользователя и избегает утечек через логи, бэкапы или потоки сброса пароля.

Также проверяется, можно ли безопасно обновлять схему со временем, чтобы вы не остались навсегда с уязвимым решением.

Почему использование MD5 или SHA-256 для паролей небезопасно?

Быстрые хеши вроде MD5, SHA-1 или простого SHA-256 созданы для скорости — а это именно то, чего хотят злоумышленники при оффлайн-переборе. Если база утекает, они могут пробовать миллиарды вариантов на своих машинах, не обращаясь к вашим серверам.

Специализированные хеши паролей (Argon2id, bcrypt, scrypt) сделаны вычислительно дорогими, поэтому превращать слитые хеши в реальные пароли сложнее.

Как узнать, какой метод хеширования использует моё приложение?

Посмотрите на формат сохранённого значения пароля и на код, который его проверяет. Многие современные схемы сами описывают алгоритм внутри строки и начинаются с маркеров вроде $argon2id$ или $2b$ (bcrypt).

Если вы видите фиксированную длину hex (32 или 64 символа) и в коде есть sha256(password) перед сравнением, это почти наверняка не специализированный хеш паролей.

Что значит «уникальная соль для каждого пользователя» и как заметить плохую соль?

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

Если у двух пользователей с одинаковым паролем хранится одинаковое значение, скорее всего соль либо не используется, либо она общая, либо предсказуема — и это серьёзный риск.

Стоит ли использовать pepper или достаточно солей?

Перец (pepper) — это секрет, добавляемый к паролю перед хешированием и хранящийся только на сервере (не в базе). Он полезен при опасении утечки базы: даже имея хеши, атакующий всё равно будет нуждаться в перце.

Используйте перец только если умеете хранить его как секрет и готовы к аккуратной ротации — изменение перца без плана может заблокировать всех пользователей.

Где ещё, кроме колонки базы данных, происходят утечки паролей?

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

Проверьте логи, отчёты об ошибках и любые места, где отладочная информация может попасть в хранилище логов.

Что проверить в потоке сброса пароля?

Токены сброса паролей часто хранят в открытом виде. Если кто-то получит доступ к базе или логам, эти токены позволяют захватить аккаунты.

Безопаснее хранить только хеш токена, делать срок жизни коротким, помечать токены как одноразовые и гарантировать, что после смены пароля старые токены перестают работать.

Что такое «rehash on next login» и почему это безопаснее всего при миграции?

«Rehash on next login» — это подход, при котором существующие пользователи продолжают входить как обычно, а при следующем успешном входе их пароль проверяется старым методом (если нужно) и затем сразу перехешируется современным алгоритмом и сохранится в новой форме.

Так вы избегаете массовой принудительной смены паролей и постепенно переводите активных пользователей на более безопасный формат.

Какие ошибки миграции чаще всего приводят к блокировкам пользователей?

Частые ошибки: попытки пересчитать хеш при неудачной попытке входа (это перезаписывает хеш мусором и блокирует доступ), изменение правил нормализации пароля (обрезание пробелов, изменение работы с Unicode) или гонки при одновременных входах на разных устройствах.

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

Чем это отличается, если код был сгенерирован быстро AI-инструментами?

В AI-сгенерированных прототипах аутентификация часто «работает в демо», но небезопасна в хранении: быстрые хеши, захардкоженные секреты, логирование чувствительных данных или остаточные эндпоинты. Быстрый выигрыш — карту всех точек входа для паролей и токенов, затем исправление самых рискованных мест.

Если вы не знаете, что именно хранится и где живут секреты, FixMyMess (fixmymess.ai) предлагает бесплатный аудит кода и обычно выполняет исправления в течение 48–72 часов, включая безопасные миграции без блокировок.