I have a situation where I need to give a bunch of administrators a command to run from a Windows command line that contains a password. There is no workaround for this application to avoid having a password on the command line.
For example:
c:>mycommand -P mypassword
I just want to give them an encrypted string that decrypts to "mycommand -P mypassword" and executes that command with its parameters without displaying the unencrypted text.
Say like this:
c:>mycommanddecoder efouhpefibhusdvn,iu3r3ksjdfdfbpisiegf
I've googled but results tend to come up with PGP command line utilities and the like.
I could just write a custom executable to do the job but that wouldn't stop a savvy operator from viewing the object code. I could encrypt it internally but then there would still be a visible key unless I used a certificate ... and you get the idea. It quickly becomes a mission!
Any thoughts?
Thanks,
Mark
Your problem is that in the end you want the script / program / command line to result in a system call that spawns the mycommand executive with the password as a parameter. And this syscall can be observed. Whatever you do beforehand you will not get around this attack point. You probably should look for a solution where the password never needs to be stored on the computer at all, maybe outsource the functionality into a service running somewhere else.
Related
Imagine that we have a program or script that can take a password (or other sensitive information) argument:
> program.exe /password:secret
For Linux, best practice generally recommends against specifying the password directly on the command-line because of potential security concerns (the password can appear in the shell's history file and the system's process table):
$ ./program.sh --password 'secret' &
[1] 4152
$ cat /proc/4152/cmdline
/bin/sh./program.sh--passwordsecret
However, when searching around, I don't see the same vigorous recommendation for Windows.
When writing programs and scripts for Windows, should we provide an alternate means to input a password besides an argument to a command-line option to avoid unintentionally exposing the password?
The answer to this question suggests that a dedicated password input prompt improves security by preventing shoulder-surfing. Are there any other ways to exploit a visible password in a command string that justifies writing alternate input methods, both in the context of a shell and in the way Windows manages processes?
Do the security implications change when starting a program from a batch file or PowerShell script that passes a password as an argument to the program?
$password = # prompt for password
program.exe /password:$password
Edit - I understand that we can misinterpret this question as opinion-based because I mention "best practices" and "recommendations" to provide background. However, I seek specific evidence that demonstrates how a password might be vulnerable in a command argument and—if this assumption is valid—concrete examples or references that depict secure alternatives.
Windows historically didn't save command history between sessions, only within the session. This was true for the command prompt and for PowerShell.
As Bill Stewart pointed out, Windows PowerShell on Windows 10 and Windows 2016 includes PSReadline by default, which does save your command history between sessions. You can see this by looking at the file here: (Get-PSReadLineOption).HistorySavePath.
But even if it's set to off, or on an OS version that didn't offer the option, that doesn't mean entering a plaintext password as an argument is a good idea.
If you must offer that, you should also have a way to have the program prompt at run time.
For PowerShell and other .Net applications, you have another issue with accepting plaintext passwords: they linger in memory and there's no good way to explicitly clear them.
This issue is two-fold: strings are immutable in .Net, which means you cannot just modify the string with nulls or random characters to clear it in memory (you will actually be creating a brand new string), and on top of that you cannot control when a specific object will handled by garbage collection, so you can't explicitly remove it.
This is why the SecureString class exists, but not everything can use this.
In PowerShell, there is a PSCredential object which stores a user name in plain text and a password as a SecureString. This should always be used in PowerShell, and should be the preferred argument type (in lieu of a separate user name and password).
Most commands in PowerShell that require a credential take it as this type of object.
You can retrieve a plaintext version of the password easily with this object as well. Doing so then puts that into a managed string and you get the risks I mentioned above.
In my opinion though, it is still preferable to use a PSCredential object in these situations, right up until the point you need the plaintext version. It helps to maintain the standardization of this type in both a built-in/'official' capacity, as well as in user-defined commands.
This type is also easily serializable with Export-Clixml into a form that is encrypted. This can give you a really nice way of providing an automated option to use stored credentials in scripts, with nothing in plaintext, and no prompting or user intervention required.
To more directly answer my question, here's a small supplement to briantist's excellent answer:
When security is a concern, do not input or request passwords or other sensitive data as command-line arguments. Other users and programs can snoop on command-line arguments fairly trivially.
We can use Windows Management Instrumentation to pull command-line arguments in PowerShell and through other programs like those built on .NET. Here's an example using PowerShell:
PS> Get-WmiObject Win32_Process -Filter 'Name = "program.exe"' | Select-Object CommandLine
C:\program.exe /password:secret
The command-line password argument is also visible in the Task Manager for any users on the same system that can see processes from other users:
As briantist wrote in his answer, programs and scripts that we write should provide alternate means to input sensitive information besides command-line arguments. PowerShell scripts can securely pass this information between scripts using PSCredential or SecureString objects.
I'm writing a bash script that needs login credentials (username and password) to make an API call. The script will eventually become a cron job, so it's not feasible to prompt the user for login credentials. What is the best way to hide the credentials in a bash script?
If you can't set up restricted read permissions on the bash script itself (e.g. only root can read it), the usual approach is to use a separate file, with said restrictions (only root or a dedicated user can read it (chmod 400 filename)).
This is how you store your ssh keys in ~/.ssh/, as well.
If you are worried about someone having full access to your drive, e.g. someone stealing it, try cryptsetup/luks.
If you are worried about someone reading the unencrypted raw device, you might try breaking up the password, and assemble it in memory when needed...
SSHPASS=$_pass sshpass -e ssh -o StrictHostKeyChecking=no $_host
I use this bit for instance and prompt user input to a restricted file, a bit more security not actually passing the variable during SSH session, but instead defining as an env variable. Haven't had many concerns from my work place Security Engineers. You can always do as others stated and have that file already containing creds rather than prompting and do the same here.
I have a windows bat which is called by the Windows task scheduler every 5 mins. In there I am connecting to a network drive, something like this
net use G: \hostname\shared mypassword /user:myuserid /persistent:yes
it works with no issue, but I don't want to put the password in the bat file as a plain txt. is there anyway to protect my password or put a encrypted password or store it somewhere safe in there to make it secure?
Use an environment variable.
Net use .... %password%
Then define the variable in the context which the batch runs. This is better than script source because the script is mobile, it can be copied from this machine to that, it can end up in the source control and so on. It is not more secure against a local host attack, i.e. If one user could see the password in the script it is also likely to find it in the environment.
There are more advanced solutions if you are willing to switch to PowerShell. https://social.technet.microsoft.com/wiki/contents/articles/4546.working-with-passwords-secure-strings-and-credentials-in-windows-powershell.aspx
You could use a Md5 generator (or hash code generator written by your own) to generate a password from any file in your computer. Whenever you run it, the batch file will generate the password from that specific file by the generator.
Your password is no longer in plain text, but hidden in generator and the corresponding file.
hope it helps.
I'm working on a shell script where it zips up a file then uploads it to a server i have.
So far i have it so it asks for the server password and then keeps that variable. After it does that the script zips up a folder with a bunch of files in it. Then it dose the "scp" command to send it to my server.
Now, this is where i need help... I want it to fill in the password that was provided earlier in the script when it asks for the server password. I'm sure your asking "why doesn't just put in the password when the "scp" command asks for it. The reason being is that the file i have is going to be large, and i dont want to sit around and watch it zip up. So thats why i provide the password early on.
here are the steps:
1) user provides server password which is saved as the variable "password"
2) the script zips up the file
3) the script sends the file to the server (when i run this part in the script it asks for the password. i have to put in the password variable here.)
Any ideas on how to do this? thanks so much, will,
Step 1 is flawed, for several reasons, both security-related and technical.
What you should do is to create a "null" SSH session in the background that generates a master connection (see the ControlPath and ControlMaster options in the ssh_config(5) man page). Using the same control settings for the subsequent SCP operation will use this connection without having to ask for the password. Don't forget to kill the null session once the script is done.
I'd like to write a shell script that does something like the following
while read line; do
echo $line
done<input.txt | ssh > output.txt
This is a bit pseudo codey at the moment (the original is at work), but you should be able to tell what it's doing. For simple applications this works a treat, but ssh checks the input to see whether it's stdin is a terminal.
Is there a way to fool ssh into thinking that the contents of my piped loop are a terminal rather than a pipe?
EDIT : Sorry for not adding this originally, this is intended to allow ssh to log in via the shell script (answering the password prompt)
ssh -t -t will do what you want - this tells ssh to allocate a pseudo terminal no matter whether it is actually running in one.
Update
This problem (after updating your question and various comments, it became clear you are looking for a way to conveniently get public key encryption into place) could perhaps be solved by 'thinking upside down'.
Instead of trying very hard to get your clients public key onto a server that doesn't yet authenticate the client, you can try to receive an authenticated identity (private key) from that server.
Simple terms: generate a keypair on the server instead of the client, and then find a way to get the keypair on the client. The server can put the public key in it's authorized_keys in advance, so the client can connect right away.
Chances are that
the problem of getting the key across is more easily solved (you could even use a 'group' key for access from various clients)
if a less-secure mechanism is chosen (convenience over security) at least only the security of the client is reduced, not as-much that of the server (directly).
Original answer:
Short answer: Nope. (it would be a security hole for ssh, because ssh 'trusts' the tty for password entry, and the tty only)
Long answer, you could try to subvert/creatively use a terminal emulator (look at script/scriptreplay for inspiration).
Why would you want to do it?