Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

How to Obscure Command Line Passwords UNIX
Many command line programs, such as mySQL and Apple's Xgrid, are not OS X Keychain savvy, and require passwords in plaintext on the command line. This can also be true when entering things like SMB and AFP disk mounts from the command line. Command line text will not only appear in plain view on your screen and terminal scroll-back but it persists indefinitely in your bash history file on disk. It can even sometimes be viewed in process monitors that show your executing commands to other users. Here is a way to avoid that pitfall.

A common approach is to put the passwords in environment variables the commands will access. For example, Xgrid will access the environment variable XGRID_CONTROLLER_PASSWORD if it is defined. However this does not solve the problem of how you get the password into the environment variable. Using the command line obviously is out. You can put it in your .profile or .bashrc in plain text, but this is again persistent on disk and your Time Machine backups and those are exposed to any program you run and to admin users.

I found a versatile solution in the OSX xgrid users wiki atTenGrid.com which suggests the following code:

`perl -we 'eval {system("stty -echo");$x=<>}; system("stty echo"); print "export XGRID_CONTROLLER_PASSWORD=$x"'`

When you run that from the command line, it lets you type in the password invisibly and then it puts it in the shell's environment for you. It's only accessible from within that shell, so other programs can't see it. When you eventually close that shell all traces of it vanish and at no time is it stored (directly at least) in plain text on disk. Of course, anyone with keyboard access to that terminal could probe your environment variables, but if that is true, this may be the least of your problems. You can automate this command by setting up an alias in the .bashrc or .profile like this (keep the escaped characters!)
alias xgpwd=\`perl\ \-we\ \'eval\ \{system\(\"stty\ \-echo\"\)\;\$x\=\<\>\}\;\ system\(\"stty\ echo\"\)\;\ \ print\ \"export\ XGRID_CONTROLLER_PASSWORD\=\$x\"\'\`
Now typing xgpwd and pressing return will let you set the password environment variable with no onscreen echo. Obviously you will need to edit this for other environment variable names by replacing the one used by Xgrid.

The code above does not support spaces in the password and it's written assuming a bash shell syntax. Since you may be tempted to improve it, note the eval statement. This is critical to assure that if you control-c the process that you are not returned to the command prompt without the tty echoing the keys you press!

Note that even if your command line program itself does not use the environment variables, as Xgrid does, you can still use this approach by letting the shell interpolate the variables for you like this:

dumb_command -pass $MY_ENV_PASSWORD

The shell will do the lookup and replacement of the $MY_ENV_PASSWORD corresponding environment variable's value that you previously stored. So dumb_command need not explicitly use environment variables to make this hint work. Once again a hat tip to the extensive OSX Xgrid wiki at TenGrid.com and to all it's contributors for solving this age-old dilemma!

[crarko adds: I haven't tested this one.]
    •    
  • Currently 2.50 / 5
  You rated: 3 / 5 (28 votes cast)
 
[8,903 views]  

How to Obscure Command Line Passwords | 16 comments | Create New Account
Click here to return to the 'How to Obscure Command Line Passwords' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
How to Obscure Command Line Passwords
Authored by: Anonymous on Jul 06, '10 08:02:18AM

This all looks weird for me. In *nices normal approach is to get the password from the user interactively. In some cases it is possible to put it on command line, but the option with the password should be removed before displayed in the list of processes. Sometimes you can specify the password in a config file. In both cases you are warned that such a practice is insecure.

By the way the same job as the perl script can be done in a pure shell, the advantage is that shell is always available. And moreover as far as I remember, you can turn off logging in bash.



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: SOX on Jul 06, '10 03:19:00PM
By the way the same job as the perl script can be done in a pure shell, the advantage is that shell is always available. And moreover as far as I remember, you can turn off logging in bash.

Au contrair mon ami.

First on a mac perl is always available. Second, the various other solutions posted here all rely on special features of bash, but not everyone uses bash. for example doing "read -s" in tsch won't work. But perl is always available. SO if you use tsch it's simple matter to change "export" to "setenv" in the perl script.

The larger point is that the key concept is that you can obscure the password and avoid having it ever appear on the terminal history, scroll-back or in a config file by entering it indirectly via a script. How you actually implement the script is not important, but the above is a versatile way, amenable to many different shells in a language that is more extensible than any shell language.

You could for example, have the perl extract the password from the keychain, or from a server on the net, or perhaps algorithmically generate the real password from some key word you insert. For instance, have the real password be the MD5 hash or the first letters of some easier to remember phrase like "mary had a little lamb". and let the perl do the conversion.

But the bottom line is that "HINT" in this hint is just to indirectly load the variable so it's is obscured. It does not keep anyone on your computer from seeing it--that's a problem with all environment variables, but if you have that problem, you probably have other problems as well. relax!

[ Reply to This | # ]

How to Obscure Command Line Passwords
Authored by: celiot on Jul 06, '10 08:04:48AM

A much better solution would get the password out of the keychain. Is there a way to import a keychain value into an environment variable using a shell script?



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: nxg on Jul 06, '10 08:13:31AM

There are two _much_ simpler ways of doing this.

First: If you start a command with a space, it's not entered into the scroll-back history, or the shell history. So that problem disappears

Second: If you want to get a password into an environment variable (nice idea -- I wouldn't have thought of that), then you can copy it into the clipboard (from Keychain Access or wherever it is you've got it noted down), and then

% pbpaste | read MY_PASSWORD_VARIABLE
% echo $MY_PASSWORD_VARIABLE
<OOOOHH, secret>
%



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: SOX on Jul 06, '10 03:05:48PM

<i>First: If you start a command with a space, it's not entered into the scroll-back history, or the shell history. So that problem disappears</i>

??? this is not true on my computer.
% history
196 export PASSWORD=foberry
197 history

The code is just showing a possible implementation of the general idea that you can load a password by indirection of a script. Any way is fine, the point of doing it with perl is that this versatile language allows you do more complicated things if you need to.



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: fds on Jul 06, '10 03:46:52PM

It's an option. Your HISTCONTROL environment variable has to contain ignorespace.

For example,
export HISTCONTROL=erasedups:ignorespace



[ Reply to This | # ]
Environment VARS, be careful
Authored by: jerobins on Jul 06, '10 08:19:26AM

Environment variables are also available in the process list: ps auxwwwE

MySQL passwords can be stored in a config file.

---
James E. Robinson, III
http://blog.robinsonhouse.com/


[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: mmnw on Jul 06, '10 08:20:23AM
Actually there is also a way to use the keychain at command line level. The security command covers that. Just have a look at:
man security
You could pipe the output of security directly to the input of your program or store it in a variable as described.
Although the output of security is not as straightforward as it could be. You'll probably have to process it first. I found this Blog-Entry describing a way to handle the output.

[ Reply to This | # ]
read
Authored by: gidds on Jul 06, '10 12:54:36PM

What does this do that the shell built-in read doesn't? A simple

read -s VAR

seems a good deal simpler than a mess of Perl.

(The -s flag puts it in silent (noecho) mode; other options let you show a prompt, time out, etc. It's available in sh, bash, zsh etc.)

And, as other posters have mentioned, if the result's going on a command line then it doesn't matter how you construct it, coz ps or top will see it anyway...

---
Andy/


[ Reply to This | # ]
read
Authored by: SOX on Jul 06, '10 02:02:53PM

Well for one reason not to use read is that it does nothing from the command line.
<code>
% read foxhole
hello
% echo $foxhole
foxhole: Undefined variable.
</code>



[ Reply to This | # ]
read
Authored by: efge on Jul 07, '10 01:55:56PM

You are wrong, this works perfectly well.



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: cyberdave on Jul 06, '10 02:46:01PM

I don't know why one would jump through the hoops to use Perl for this, when it can be done just as easily in the shell itself (in fact it's doing exactly the same thing, without the overhead of launching the Perl interpreter).

This code will prompt for a password and store it an environment variable called PASSWORD, without your typing being echoed back:

stty -echo && echo -n "Enter password: " && read PASSWORD ; stty sane 

(Note that, with shell scripting, the 'command1 && command2' syntax will execute command2 if command1 completes successfully, which makes sense in this case for turning off echo and reading the password; we always want to execute 'stty sane' to reset the shell to sane defaults if, e.g., the user hits Ctrl-C instead of typing in a password, so it's chained with ';' instead of '&&')

Here it is in action:

cyberdave@laptop] stty -echo && echo -n "Enter password: " && read PASSWORD ; stty sane
Enter password:
cyberdave@laptop] echo $PASSWORD
Sekrit

You can, of course, change 'PASSWORD' to whatever variable needs to be set (e.g., "read XGRID_CONTROLLER_PASSWORD")

Note, that, as another user commented, the right flags to 'ps' will show you command-line arguments, so be wary of passing passwords in this manner. Since it's an environment variable in the shell, one could probably also find it somewhere in the shell process's memory if one were to go digging (though I've not tried this).



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: SOX on Jul 06, '10 02:59:13PM

first it's weird to say perl is jumping through hoops when, by using perl, you can do much more complicated things if you so desired.

Second this is merely the illustration of the basic concept of how to obscure passwords by loading them using a script. The language used to do the loading is merely a detail.



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: cyberdave on Jul 06, '10 05:01:20PM

Don't get me wrong, I love Perl and I use it all the time..but there's also 'the right tool for the job', and in this particular example, using a bit of Perl that consists basically of two system() calls and exporting an environment variable back to your shell is overkill when you can do all that without leaving the shell, with simpler code (at least to someone like me, who is comfortable with both shell scripting and Perl scripting).

Now, if I happened to have some Perl could that could interact with the Keychain more cleanly than dealing with the 'security' command and parsing it's output, then, yeah, I'd probably using that instead of a complicated bit of shell scripting (and I'd be arguing "hey, just do it in Perl!" if this was a hint showing the excessively complicated way).

But as far as this hint goes, which when I first read it, seems to really be about reading a password in the shell and assigning it to a variable without echoing your typing, I still say the shell version is better. Now, if you (not you personally) wanted to take this hint and expand on it and turn it into a more advanced tutorial (like 1: the basic method of how to read a password at the command line and store it in an environment variable, then 2: do the same thing in Perl, then 3: demonstrate how to do more advanced things in the Perl version, and 4: make it suitably generic (though the subject suggests otherwise, this one is really geared towards the Xgrid use case, and being able to use the same method elsewhere is added on somewhat as an afterthought) so everyone could see the different ways of doing it and choose the variation that's best suited for what they're trying to do, then we'd all be happy(er). :)



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: ambrose on Jul 06, '10 04:14:34PM

In those cases where a #!script is invoked via /bin/sh, the builtin echo command behaves differently than when the script is invoked via /bin/bash -- it will not recognize the -n argument. To suppress the newline character in such circumstances, the string to be echoed should be followed by '\c'.



[ Reply to This | # ]
How to Obscure Command Line Passwords
Authored by: kps on Jul 10, '10 10:51:16AM
In this context, use
stty echo
rather than
stty sane
The latter may also change other settings.

[ Reply to This | # ]