Passing key stuff to openssl commands

Is it safe to pass a key to openssl command via command line parameters in Linux? I know this excludes the actual parameter, so it cannot be viewed through / proc, but even so is there a way to use this?

I have a python application that I want to use OpenSSL to perform encryption / description via streaming stdin / stdout in a subprocess, but I want to know that my keys are safe.

+3


source to share


2 answers


Passing credentials on the command line is insecure. This will cause your password to appear in the system process list - even if openssl removes it from the process list as soon as possible, it will be there for a moment.

openssl

provides several ways to pass credentials: the man page has a section "PASS PHRASE ARGUMENTS" that documents all the ways to pass credentials to openssl

. I'll explain the relevant ones:


env: var

Allows to pass credentials in an environment variable. This is better than using a process list because on Linux your process environment is not readable by other users by default, but this is not necessarily true on other platforms.

The downside is that other processes running as the same user or root can easily view the password through / proc.

It's pretty easy to use with a python subprocess:

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)

      


FD: number

This allows you to tell openssl

to read the credentials from the file descriptor, which it assumed is already open for reading. Using this, you can write key data directly from your process to openssl, with something like this:



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)

      

This will protect your password from other users on the same system, provided they are logged in with a different account.

With the above code, you may run into call blocking issues os.write

. This can happen when openssl

waiting for something else before reading the key. This can be solved with asynchronous I / O (like a select loop) or an additional write thread write () & close ().

One drawback to this is that it doesn't work if you pass closeFds=true

to subprocess.Popen. Subprocess has no right to say "don't close one particular fd", so if you need to use closeFds = true, I would suggest using the file:

(bottom) named pipe syntax .


File: path to file

Don't use this with an actual password file! This should be avoided for many reasons, for example. your program can be killed before it can erase the file, and with most journaling filesystems it is nearly impossible to wipe data from disk.

However, if used with a named pipe with restrictive permissions, this can be as good as using the option fd

above. The code for this will be similar to the previous snippet, except that you need to create a fifo instead of using 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

here may have the same I / O blocking issues as the call os.write

above, the permissions are the same as well.

+3


source


No, it is not safe. Regardless of what openssl opens with its command line after it has started, there is still a window of time during which information is visible in the process command line: after the process has started and before it has had a chance to zero it out.

In addition, there are many ways for a crash to occur: for example, the command line is logged by sudo before it is executed, or it ends up in the shell history file.

Openssl supports many methods for transferring sensitive information, so you don't need to specify it on the command line. From the manpage:



  • password: password

    the actual password is the password. Since the password is visible to utilities (eg "ps" on Unix), this form should only be used where security is not important.

  • env: var

    get password from environment variable var. Since the environment of other processes is visible on some platforms (eg ps under some Unix operating systems), this option should be used with caution.

  • File: path to file

    the first line of the path is the password. If the same pathname is specified for the -passin and -passout arguments, the first line will be used for the password and the next line for the output password. pathname does not necessarily refer to a regular file: it can, for example, refer to a device or a named pipe.

  • fd: number

    read the password from the file descriptor number. This can be used to send data through a channel, for example.

  • stdin

    read the password from standard input.

All but the first two are good.

+2


source







All Articles