Вопрос или проблема
У меня есть сервер приложений, написанный на C++, который также использует REST API для обработки запросов. Базы данных нет, только простой сервис, который возвращает, если содержимое запроса допустимо.
Ситуация
Сервер находится в локальной сети и доступен только там, не имеет подключения к интернету и предназначен только для обработки запросов из той же локальной сети.
Наше решение
Теперь я хочу защитить REST API с помощью базовой аутентификации, только с одним пользователем, и у меня нет идей, безопасен ли следующий метод хранения пароля:
- Пароль будет передан как параметр во время развертывания.
- Во время развертывания пароль будет зашифрован (с использованием DES) с помощью ключа, сохранен в переменной окружения, скажем, PASSWORDENV, при этом ключ будет зашифрован в коде приложения.
- Когда приходит запрос, приложение должно прочитать заголовки HTTP для идентификатора и пароля, зашифровать пароль и сравнить с PASSWORDENV.
Заботы
- Ключ шифрования закодирован, но я не знаю другого способа проверить пароль.
- Есть ли какие-либо проблемы безопасности с нашим решением?
Базовая аутентификация даст вам немного больше безопасности, чем у вас уже есть:
Учтите векторы, против которых вы защищаетесь: злонамеренный актор, получивший доступ к сети, или недовольный сотрудник с доступом к сети.
Злонамеренный актор: Если вы не используете TLS, любой в сети увидит весь запрос/ответ (включая пароль), поэтому для предотвращения первого вектора требуется TLS.
Недовольный сотрудник: Если вы используете TLS, любой в сети с частными ключами сможет увидеть весь запрос/ответ (включая пароль), потребуется что-то большее, чтобы предотвратить все случаи второго вектора.
Теперь вам нужно оценить риск, связанный с этими уязвимостями, что требует от вас рассмотреть вероятность эксплуатации уязвимости и убытки, которые вы понесете, если уязвимость будет использована (финансовые, репутационные и т.д.)
Примечание:
Существуют широко признанные формы аутентификации на основе токенов, которые могут помочь повысить безопасность аутентификации: OAuth или OpenID могут работать в зависимости от вашего варианта использования.
Прежде всего, какой смысл в шифровании пароля? Если вы используете базовую аутентификацию, у вас уже есть пароль в открытом виде, поэтому самым простым предостережением было бы захэшировать его (например, с использованием Argon).
Во-вторых, если вы хотите вынести аутентификацию из вашей системы, просто передайте это другой системе, такой как сервер RADIUS или LDAP. Это позволит вам расширить это даже более чем на одного пользователя, например, разрешив целой группе пользователей из вашей центральной аутентификации запрашивать ваш сервис, используя свои учетные данные, на основе какого-то членства в группе.
Конечно, существует проблема безопасности, но, по крайней мере, вы определили риск, что является первым шагом. Теперь вам нужно проанализировать его и затем смягчить.
На самом деле у вас две проблемы:
- Пароль, сохраненный на диске в коде приложения.
- Пароль, передаваемый по сети.
Вы шифруете пароль в процессе передачи, так что пункт #2 будет в порядке. Вы можете добавить TLS (HTTPS вместо HTTP).
Остается проблема #1 (пароль, сохраненный на диске), но чтобы избежать этого, вам нужно пойти на центральную систему “управления идентичностью” (например, Active Directory, LDAP, сервер OAuth и т.д.). Если у вас этого нет, вы должны смягчить риск другими ‘компенсирующими’ мерами, то есть укрепляя вашу среду в целом, чтобы ‘плохие парни’ не смогли получить доступ к паролю.
Такие ‘компенсирующие’ меры могут включать: более строгий контроль доступа (кто имеет доступ к коду и может видеть пароль), регулярные аудиты, контроль доступа к сети, ограничение числа администраторов и т.д.
и доступен только там
…
только с одним пользователем
И как вы собираетесь обеспечить, чтобы ситуация оставалась такой?
Во время развертывания пароль будет зашифрован (с использованием DES) с ключом, сохранен в переменной окружения, скажем, PASSWORDENV, при этом ключ будет зафиксирован в коде приложения.
Нет. Это только немного лучше, чем просто хранить пароль в открытом виде. Либо используйте одностороннее хеширование, либо пару ключей/кворумное шифрование. Существуют готовые реализации.
Ответ или решение
Для обеспечения безопасного хранения и обработки паролей на локальном сервере, поддерживающем REST API, необходимо учитывать несколько важных аспектов. Ниже представлен анализ предложенного вами решения и рекомендации по его улучшению.
Текущее решение
Ваша схема состоит из следующих этапов:
- Пароль передается как параметр при развертывании.
- На этапе развертывания пароль шифруется с помощью DES и хранится в переменной окружения
PASSWORDENV
, в то время как ключ жестко закодирован в приложении. - При получении запроса приложение читает заголовки HTTP для идентификатора и пароля, шифрует пароль и сравнивает с
PASSWORDENV
.
Анализ и рекомендации
-
Использование шифрования DES:
- Хотя вы используете шифрование, DES считается устаревшим и небезопасным. Вам следует рассмотреть возможность использования более современных алгоритмов, таких как AES (Advanced Encryption Standard).
-
Хранение паролей:
- Вместо шифрования пароля вы должны использовать его хэширование. Алгоритмы, такие как Argon2, bcrypt или PBKDF2, предназначены для надежного хэширования паролей. Они добавляют "соль" и используют итерации для повышения безопасности, что делает атаку с использованием радужных таблиц и грубой силы значительно более сложной.
-
Жестко закодированные ключи:
- Имея жестко закодированный ключ в приложении, вы создаете уязвимость. Рекомендуется исследовать решение с использованием безопасного хранилища ключей, например, AWS Secrets Manager или HashiCorp Vault, если это применимо в вашей среде.
-
Передача пароля по сети:
- Использование Basic Authentication без шифрования соединения (TLS) делает пароль уязвимым при передаче по сети. Убедитесь, что используете HTTPS, чтобы предотвратить перехват данных.
-
Управление доступом:
- Рекомендуется реализовать механизмы контроля доступа. Например, ограничение доступа только доверенным устройствам в локальной сети и использование маршрутизации, которая предотвращает доступ к вашему серверу неавторизованным пользователям.
-
Соответствие требованиям безопасности:
- Подумайте о внедрении центральной системы управления идентификацией, такой как LDAP, Active Directory или сторонние решения для аутентификации (например, OAuth или OpenID). Это даст вам возможность управлять несколькими учетными записями и повысит безопасность в будущем.
-
Аудит и мониторинг:
- Регулярные аудиты уровня безопасности и мониторинг доступа к системе помогут обнаруживать и предотвращать потенциальные угрозы.
Заключение
Изменение процесса аутентификации с применением безопасных методов хранения и передачи паролей значительно повысит устойчивость вашей системы к атакам. Хотя ваша архитектура работает в локальной сети, это не исключает необходимость в повышении уровня безопасности, особенно если вы планируете ее расширение или добавление новых пользователей в будущем. Будьте проактивными в управлении безопасностью и применяйте лучшие практики для защиты ваших данных.