Какие есть хорошие практики безопасного хранения конфиденциальной информации в ASP.NET
Что проверяют
Различаете ли вы секреты приложения (строки подключения, ключи API) и конфиденциальные данные пользователей, потому что защищаются они по-разному. Следом обычно просят рассказать, где у вас лежала строка подключения к боевой базе и как она туда попадала.
Как отвечать
Секреты конфигурации в ASP.NET Core:
- User Secrets:
dotnet user-secrets setкладёт значение вsecrets.jsonв профиле пользователя, вне репозитория. Файл не шифруется, инструмент только для разработки; - переменные окружения: двойное подчёркивание заменяет двоеточие,
ConnectionStrings__Main. Базовый вариант для контейнеров, но значения видны вdocker inspect; - менеджер секретов: Azure Key Vault через
AddAzureKeyVault, HashiCorp Vault или облачный аналог. Приложение ходит туда по управляемой идентичности, без пароля в конфиге, а секреты ротируются без передеплоя; IOptions<T>: секрет попадает в типизированный объект, в коде нет строковых литералов.
Данные пользователей:
- пароли не шифруются, а хэшируются с солью.
PasswordHasher<TUser>из ASP.NET Core Identity использует PBKDF2, свой алгоритм писать не нужно; - поля в базе шифруются через
AesGcmс ключом из хранилища секретов или средствами СУБД, например Always Encrypted в SQL Server; - Data Protection API:
CreateProtector("purpose")защищает куки, токены сброса, временные данные. Для многолетнего хранения не предназначен, ключи по умолчанию живут 90 дней.
Добавьте HTTPS с HSTS, запрет логировать секреты и минимальные права у учётки базы.
Где спотыкаются
Кладут пароль в appsettings.json и успокаиваются тем, что файл в .gitignore. Секрет всё равно окажется в образе, а пароль, однажды попавший в историю Git, считается скомпрометированным и меняется.
Не настраивают хранение ключей Data Protection. В контейнере или на нескольких инстансах ключи теряются при перезапуске, и пользователи разом вылетают из сессии. Нужны PersistKeysToFileSystem или другое общее хранилище и ProtectKeysWithCertificate.
Шифруют пароли обратимо, «чтобы можно было восстановить». Восстановления пароля не бывает, бывает только сброс.