Шифрование localStorage/indexedDb с использованием ключа, производного от PBKDF2 на стороне сервера, безопасно?

Вопрос или проблема

Здравствуйте, сообщество InformationSecurity!

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

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

В настоящее время мы сохраняем данные пользователя в localStorage и indexedDb, а не на наших серверах. Наша текущая реализация шифрует все данные на клиенте с помощью ключа шифрования, сгенерированного сервером, который не хранится на клиенте. Однако у меня есть сомнения, так как я знаю, что localStorage (и в принципе все другие типы хранения на клиенте) уязвимы для атак XSS. Таким образом, возникает вопрос 🙂

Процесс сохранения данных в настоящее время работает следующим образом:
Предполагая, что пользователь авторизован в нашем приложении. Под шифрованием/дешифрованием я имею в виду: AES-GCM

  1. Клиент отправляет запрос на наш сервер для получения секрета шифрования/дешифрования. Запрос включает токен аутентификации
  2. Наш сервер проверяет подпись токена аутентификации. Если подпись токена действительна, сервер извлекает userId из токена
  3. Наш сервер генерирует randomKey длиной 32 байта
  4. Этот случайный ключ + userId в комбинации с секретом на стороне сервера используются для получения ключа шифрования. encryptionKey=PBKDF2(PBKDF2(serverSideSecret, userId), randomKey)
  5. Этот ключ шифрования и случайный ключ возвращаются в браузер
  6. Случайный ключ сохраняется в localStorage, ключ шифрования остается в закрытой переменной модуля ES6, который не экспортируется. Сам ключ шифрования не сохраняется в любом клиентском хранилище
  7. Данные шифруются с использованием ключа, зашифрованный текст сохраняется в localStorage браузера.

Получение из хранилища:

  1. Случайный ключ считывается из localStorage
  2. Клиент отправляет запрос на получение ключа дешифрования для данных. Запрос содержит токен аутентификации, а также случайный ключ из шага 1
  3. Сервер проверяет токен, если он действителен, генерирует секрет для дешифрования из userId: decryptionSecret= PBKDF2(PBKDF2(serverSideSecret, userId), randomKey)
  4. Ключ дешифрования возвращается клиенту, который может дешифровать данные
  5. DOM заполняется зашифрованными данными. Пользователь может продолжить редактировать их

Главная идея в том, что мой клиент не хочет сохранять никаких данных, связанных с клиентом, на стороне сервера. Используя процесс выше, фактически каждый раз, когда данные сохраняются в localStorage, они будут зашифрованы новым ключом шифрования (поскольку каждый раз будет сгенерирован новый случайный ключ), который можно получить только с сервера с действительным токеном аутентификации.

Но у меня есть ощущение, что существуют некоторые уязвимости в безопасности. Я прав?

Ответ или решение

Эффективность шифрования localStorage/indexedDB с использованием серверного секрета, производимого через PBKDF2

Введение

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

Текущая Архитектура Шифрования

Система, предложенная вами, включает в себя несколько ключевых этапов:

  1. Клиент запрашивает шифровальный секрет у сервера, предоставляя токен аутентификации.
  2. Сервер проверяет токен и генерирует новый randomKey, который используется вместе с userId и серверным секретом для создания encryptionKey с использованием PBKDF2.
  3. randomKey сохраняется в localStorage, в то время как encryptionKey хранится только в памяти клиента.
  4. Данные шифруются с использованием encryptionKey и сохраняются в localStorage.

Оценка Уязвимостей

Несмотря на то, что ваша система шифрования имеет свои достоинства, существуют некоторые уязвимости, которые могут быть рассмотрены:

  1. Уязвимость к XSS-атакам: Хранение любых ключей шифрования на стороне клиента (даже временных) делает приложение уязвимым для XSS-атак. Если злоумышленник сможет внедрить скрипт, он сможет получить доступ к randomKey в localStorage, а значит, и к данным, которые можно расшифровать.

  2. Сетевая передача данных: Каждый раз, когда вы передаете randomKey, есть риск его перехвата. Это особенно актуально, если не используются защищенные протоколы (например, HTTPS).

  3. Ошибка аутентификации: Без надлежащего контроля над токенами аутентификации, даже мимолетная утечка токена может предоставить доступ к процессу шифрования/дешифрования.

  4. Сложность управления ключами: Каждый раз, когда создаётся новый randomKey, возникает необходимость управления множеством ключей. Это увеличивает шансы на ошибки и неправильно использованные ключи.

Рекомендации по Усилению Безопасности

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

  1. Предотвращение XSS:

    • Используйте Content Security Policy (CSP) для ограничения источников исполняемого кода.
    • Проводите регулярные аудиты на предмет уязвимостей, чтобы выявлять и устранять потенциальные XSS-угрозы.
  2. Шифрование данных перед отправкой:

    • Рассмотрите возможность начального шифрования данных перед их отправкой на сервер или перед сохранением в localStorage. Это может уменьшить количество данных, доступных в открытом виде.
  3. Кэширование токенов:

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

    • Всегда используйте HTTPS для передачи данных между клиентом и сервером, чтобы предотвратить несанкционированный доступ к данным.
  5. Регулярное обновление ключей шифрования:

    • Рассмотрите внедрение механизма периодической ротации ключей шифрования, чтобы снизить последствия их компрометации.

Заключение

Ваша текущая система шифрования данных с использованием PBKDF2 и AES-GCM содержит важные элементы безопасности. Тем не менее, наличие уязвимостей, связанных с хранением randomKey в localStorage и потенциальными рисками XSS, делает необходимым пересмотр подхода к безопасности данных. Важно внедрять дополнительные меры защиты и регулярно проверять архитектуру безопасности в соответствии с современными стандартами. Заключительной рекомендацией будет непрерывное внимание к ресурсам, которые могут помочь выявить и исправить уязвимости, и к образованию команды в вопросах безопасной разработки.

Оцените материал
Добавить комментарий

Капча загружается...