24

We know we can encrypt a file with openssl using this command:

openssl aes-256-cbc -a -salt -in twitterpost.txt -out foo.enc -pass stdin

The password will be read from stdin. As such, to provide the password beforehand, all we need do is prepend

echo "someGoodPassword" |

to the above command. My question is: How can I do this more securely? The above method doesn't look secure enough.

I'd appreciate some comments about this so I can understand this issue better.

Enchilada
  • 3,859
  • 1
  • 36
  • 69

4 Answers4

32

pretty much any mechanism you use will be snoopable by root, so bear this in mind.

The echo option, will display in the 'ps' listings, making it vulnerable to ordinary users snooping and finding the password.

You can use -pass file:filename to use a file, so you can use:

sumask=$(umask)
umask 077
rm -f passfile
cat >passfile <<EOM
someGoodPassword
EOM
umask $sumask

this creates the file, unreadable by other accounts (but still readable by root). One assumes that the script is being used once only to create the passfile, as if you repeat the process, it tends to be in a file, and therefore you need to chmod go-rwx the file to make it unreadable by other users.

then you use:

openssl aes-256-cbc -a -salt -in twitterpost.txt -out foo.enc -pass file:passfile

to perform the encryption, using the pre-created password file.

Other mechanisms are -pass env:ENVVAR for using an environment variable (again getting it in there without revealing it is the trick)

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
  • So if I have some software that gets the user to type in a password in some UI, and then it writes this password to this file (with the right permissions), and then it calls these terminal commands, would you say that is safe? In this sense: If the computer has been compromised by a 2nd app to obtain this password, then the user has some serious security issues to worry about. Actually, it could be some software specifically designed to attack my own software :) What are your thoughts on this? – Enchilada Jun 12 '11 at 13:06
  • 1
    That would make things relatively safe, however if there is an application specifically designed to attack your program, then all bets are off - We can snoop the keyboard as the password is typed in, we can read the I/O as the file is being written, we can read the file, we can read your environment. There is practically no protection that is 100% safe - You can use the 'open file, unlink it but keep file handle open and pass the handle around' trick so there's no trace of the password on the file system (use fd:number as the argument to -pass) the app with the UI uses an fd also – Anya Shenanigans Jun 12 '11 at 19:43
  • 1
    If this is part of a desktop application in gnome, you can use the gnome-keyring as a secure storage location for the password, as it is encrypted and generally inaccessible when the user is not logged in (KDE has kwallet IIRC). Adobe AIR applications have a password storage mechanism also (I don't know of AIR's mechanism of securing it), but because you're using shell script idioms, I expect these are not really an option. – Anya Shenanigans Jun 12 '11 at 19:57
  • 1
    echo doesn't show up in `ps` listings as it is a built-in (at least in bash) – zeroimpl Feb 07 '17 at 03:06
  • `pkcs12: Unrecognized flag pass` The flag is called `-passin`. – AndreKR Nov 27 '19 at 09:23
  • 1
    @AndreKR `pkcs12` supports reading and writing with a password, which is why there are separate options for that (`-passin` and `-passout`). This was for the `aes-256-cbc` command, which only needs the one argument. – Anya Shenanigans Nov 27 '19 at 09:41
  • just use `builtin echo` to be sure you are using a builtin and it will not show in ps – Jakub Bochenski Apr 13 '21 at 12:23
20

Short version

Use a named pipe.

openssl aes-256-cbc -a -salt -in twitterpost.txt -out foo.enc -pass file:<( echo -n "someGoodPassword" )

Long version

Use a named pipe. You can create it in bash with

<( *output* )

e.g.

<( echo -n "content" ) # without -n echo will add a newline

It will open a named pipe, usually a FIFO queue, and you will see on the process list something like

/dev/fd/63

It will be readable only by the current user and will be automatically closed after it has been read, so you don't have to worry about permissions and cleaning up the disk (the pipe would close if the program crash, while a file created by you as suggested in another answer would stay on disk).

This way it will close in the fastest way possible, just after the command read it and without waiting for it to finish his task (I just did a test: encrypt some gigabytes and try to read the named pipe (it's visible in the process list): the named pipe closes instantaneously even if openssl takes ages to encrypt).

About your comments

If the computer has been compromised by a 2nd app to obtain this password, then the user has some serious security issues to worry about. Actually, it could be some software specifically designed to attack my own software

If your computer has been hacked and the attacker has your same user rights, you're done for. At example the attacker may easily modify your .bashrc to alias openssl so that it starts an hypotetic "evil-openssl" that copy your password and data before handling everything to the real openssl, leaving you with your false sense of security.

That said, I'm not a security expert, so if anyone want to downvote me into oblivion (and tell me why), you're welcome.

Riccardo Galli
  • 12,419
  • 6
  • 64
  • 62
5

If I understand right, your concert about

$ echo "someGoodPassword" | openssl (...) -pass stdin

is that the password will be visible in the process list to all users for some short amount of time. That can be easily worked around with bash's <<< redirection (will not work in plain old POSIX shell, though):

$ openssl (...) -pass stdin <<<"someGoodPassword"

This construct supports variable interpolation (<<<"$password") and the command output can be piped further or redirected to file as usual.

firegurafiku
  • 3,017
  • 1
  • 28
  • 37
3

You can use several methods for pass through the password: https://www.openssl.org/docs/man1.0.2/apps/openssl.html#PASS-PHRASE-ARGUMENTS

As @Petesh said, the root can read everything!

Therefore, if you write down the password into any common(!) file, e.g.

  • into a temporary file with any safe permission
  • or into the script what does do your echo trick into a pipe

the root user could find this!

Don't prefer to use everything what available via /proc (e.g. by the ps)

So, do not use...

openssl aes-256-cbc ... -passin 'pass:someGoodPassword'

or

PASSWORD='someGoodPassword'
openssl aes-256-cbc ... -passin 'env:PASSWORD'`

The best solution

  • Avoid storing passwords in plain text on your system (e.g. use password manager)
  • Pass through passwords to openssl via pipe/fifo:

    password_manager get_password | openssl aes-256-cbc ... -passin 'stdin'
    

    or

    # https://stackoverflow.com/a/7082184/1108919
    password_manager get_password >&3
    openssl aes-256-cbc ... -passin 'fd:3'
    

    or

    openssl aes-256-cbc ... -passin "file:<(password_manager get_password)"
    
andras.tim
  • 1,964
  • 1
  • 13
  • 23