Передача ключевого материала командам openssl - PullRequest
3 голосов
/ 09 марта 2012

Безопасно ли передавать ключ в команду openssl через параметры командной строки в Linux? Я знаю, что он обнуляет фактический параметр, поэтому он не может быть просмотрен через / proc, но, даже с этим, есть ли способ использовать это?

У меня есть приложение на python, которое я хочу использовать OpenSSL для выполнения шифрования / описания посредством потоковой передачи stdin / stdout в подпроцессе, но я хочу знать, что мои ключи безопасны.

Ответы [ 2 ]

3 голосов
/ 09 марта 2012

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

openssl дает вам несколько способов передачи учетных данных - на странице руководства есть раздел «ПАРАМЕТРЫ ПАРОЛЬНОЙ ФРАЗЫ», который документирует все способы передачи учетных данных в openssl. Я объясню соответствующие:


ENV: вар

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

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

.

Это довольно легко использовать с подпроцессом python:

new_env=copy.deepcopy(os.environ)
new_env["MY_PASSWORD_VAR"] = "my key data"
p = subprocess.Popen(["openssl",..., "-passin", "env:MY_PASSWORD_VAR"], env=new_env)

ФД: номер

Это позволяет вам openssl прочитать учетные данные из файлового дескриптора, который, как он полагает, уже открыт для чтения. Используя это, вы можете записать данные ключа непосредственно из вашего процесса в openssl, примерно так:

r, w = os.pipe()
p = subprocess.Popen(["openssl", ..., "-passin", "fd:%i" % r], preexec_fn=lambda:os.close(w))
os.write(w, "my key data\n")
os.close(w)

Это сохранит ваш пароль в безопасности от других пользователей в той же системе, при условии, что они вошли в систему с другой учетной записью.

С помощью приведенного выше кода вы можете столкнуться с проблемами с блокировкой вызовов os.write. Это может произойти, если openssl ждет, пока что-то произойдет, прежде чем считывать ввод. Это может быть решено с помощью асинхронного ввода-вывода (например, цикла выбора) или дополнительного потока для выполнения write () & close ().

Одним из недостатков этого является то, что он не будет работать, если вы передадите closeFds=true в подпроцесс. Подпроцесс не может сказать «не закрывать один конкретный fd», поэтому если вам нужно использовать closeFds = true, тогда я бы предложил использовать синтаксис file: (ниже) с именованным каналом.


Файл: путь к файлу

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

Однако, если используется с именованным каналом с ограничивающими разрешениями, это может быть так же хорошо, как использование опции fd выше. Код для этого будет аналогичен предыдущему фрагменту, за исключением того, что вам необходимо создать fifo вместо использования os.pipe():

pathToFifo = my_function_that_securely_makes_a_fifo()
p = subprocess.Popen(["openssl", ..., "-passin", "file:%s" % pathToFifo])
fifo = open(pathToFifo, 'w')
print >> fifo, "my key data"
fifo.close()

У print здесь могут быть те же проблемы с блокировкой ввода / вывода, что и у вызова os.write выше, разрешения также такие же.

2 голосов
/ 09 марта 2012

Нет, это не безопасно.Независимо от того, что openssl делает со своей командной строкой после запуска, все равно есть окно времени, в течение которого информация отображается в командной строке процесса: после запуска процесса и до того, как он получил возможность обнулить

Плюс, есть много причин, по которым может произойти авария: например, командная строка регистрируется в sudo до ее запуска или заканчивается в файле истории оболочки.

Openssl поддерживает множество методов передачи конфиденциальной информации, поэтому вам не нужно вводить ее в открытом виде в командной строке.С man-страницы:

  • пароль: пароль

    фактический пароль - пароль.Поскольку пароль виден утилитам (например, «ps» в Unix), эту форму следует использовать только в тех случаях, когда безопасность не важна.

  • env: var

    получить пароль из переменной окружения var.Поскольку окружение других процессов видно на определенных платформах (например, ps в определенных ОС Unix), этот параметр следует использовать с осторожностью.

  • file: pathname

    первая строка пути - это пароль.Если один и тот же аргумент pathname указан для аргументов -passin и -passout, то первая строка будет использоваться для входного пароля, а следующая строка для выходного пароля.имя пути не обязательно должно ссылаться на обычный файл: оно может, например, ссылаться на устройство или именованный канал.

  • fd: number

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

  • stdin

    считывание пароля со стандартного ввода.

Все, кроме первых двух вариантов, хороши.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...