If you’re forced to use a Linux script to connect to a password-protected resource, you probably feel uneasy about putting that password in the script. OpenSSL solves that problem for you.
Passwords and Scripts
It isn’t a great idea to put passwords in shell scripts. In fact, it’s a really bad idea. If the script falls into the wrong hands, everyone who reads it can see what the password is. But if you’re forced to use a script, what else can you do?
You can enter the password manually when the process reaches that point, but if the script is going to run unattended, that won’t work. Thankfully, there’s an alternative to hard-coding the passwords into the script. Counterintuitively, it uses a different password to achieve this, along with some strong encryption.
In our example scenario, we need to make a remote connection to a Fedora Linux computer from our Ubuntu computer. We’ll be using a Bash shell script to make an SSH connection to the Fedora computer. The script must run unattended, and we don’t want to put the password for the remote account in the script. We can’t use SSH keys in this case, because we’re pretending that we don’t have any control or admin rights over the Fedora computer.
We’re going to make use of the well-known OpenSSL toolkit to handle the encryption and a utility called sshpass
to feed the password into the SSH command.
RELATED: How to Create and Install SSH Keys From the Linux Shell
Installing OpenSSL and sshpass
Because a lot of other encryption and security tools use OpenSSL, it might already be installed on your computer. However, if it isn’t, it only takes a moment to install.
On Ubuntu, type this command:
sudo apt get openssl
To install sshpass
, use this command:
sudo apt install sshpass
On Fedora, you need to type:
sudo dnf install openssl
The command to install sshpass
is:
sudo dnf install sshpass
On Manjaro Linux, we can install OpenSSL with:
sudo pacman -Sy openssl
Finally, to install sshpass
, use this command:
sudo pacman -Sy sshpass
Encrypting on the Command Line
Before we get into using the openssl
command with scripts, let’s become familiar with it by using it on the command line. Let’s say that the password for the account on the remote computer is rusty!herring.pitshaft
. We’re going to encrypt that password using openssl
.
We need to provide an encryption password when we do. The encryption password is used in the encryption and decryption processes. There are a lot of parameters and options in the openssl
command. We’ll take a look at each of them in a moment.
echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password'
We’re using echo
to send the remote account password through a pipe and into the openssl
command.
The openssl
parameters are:
- enc -aes-256-cbc: The encoding type. We’re using the Advanced Encryption Standard 256-bit key cipher with cipher-block chaining.
- -md sha512: The message digest (hash) type. We’re using the SHA512 cryptographic algorithm.
- -a: This tells
openssl
to apply base-64 encoding after the encryption phase and before the decryption phase. - -pbkdf2: Using Password-Based Key Derivation Function 2 (PBKDF2) makes it much more difficult for a brute force attack to succeed in guessing your password. PBKDF2 requires many computations to perform the encryption. An attacker would need to replicate all of those computations.
- -iter 100000: Sets the number of computations that PBKDF2 will use.
- -salt: Using a randomly applied salt value makes the encrypted output different every time, even if the plain text is the same.
- -pass pass:’pick.your.password’: The password we’ll need to use to decrypt the encrypted remote password. Substitute
pick.your.password
with a robust password of your choosing.
The encrypted version of our rusty!herring.pitshaft
password is written to the terminal window.
To decrypt this, we need to pass that encrypted string into openssl
with the same parameters that we used to encrypt, but adding in the -d
(decrypt) option.
echo U2FsdGVkX19iiiRNhEsG+wm/uKjtZJwnYOpjzPhyrDKYZH5lVZrpIgo1S0goZU46 | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'pick.your.password'
The string is decrypted, and our original text—the password for the remote user account—is written to the terminal window.
That proves that we can securely encrypt our remote user account password. We can also decrypt it when we need it using the password that we provided in the encryption phase.
But does this actually improve our situation? If we need the encryption password to decrypt the remote account password, surely the decryption password will need to be in the script? Well, yes, it does. But the encrypted remote user account password will be stored in a different, hidden file. The permissions on the file will prevent anyone but you—and the system’s root user, obviously—from accessing it.
To send the output from the encryption command to a file, we can use redirection. The file is called “.secret_vault.txt.” We’ve changed the encryption password to something more robust.
echo 'rusty!herring.pitshaft' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password' > .secret_vault.txt
Nothing visible happens, but the password is encrypted and sent to the “.secret_vault.txt” file.
We can test that it worked by decrypting the password in the hidden file. Note that we’re using cat
here, not echo
.
cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password'
The password is successfully decrypted from the data in the file. We’ll use chmod
to change the permissions on this file so that no one else can access it.
chmod 600 .secret_vault.txt
ls -l .secret_vault.txt
Using a permissions mask of 600 removes all access for anyone other than the file owner. We can now move on to writing our script.
RELATED: How to Use the chmod Command on Linux
Using OpenSSL in a Script
Our script is pretty straightforward:
#!/bin/bash # name of the remote account REMOTE_USER=geek # password for the remote account REMOTE_PASSWD=$(cat .secret_vault.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 -salt -pass pass:'secret#vault!password') # remote computer REMOTE_LINUX=fedora-34.local # connect to the remote computer and put a timestamp in a file called script.log sshpass -p $REMOTE_PASSWD ssh -T $REMOTE_USER@$REMOTE_LINUX << _remote_commands echo $USER "-" $(date) >> /home/$REMOTE_USER/script.log _remote_commands
- We set a variable called
REMOTE_USER
to “geek.” - We then set a variable called
REMOTE_PASSWD
to the value of the decrypted password pulled from the “.secret_vault.txt” file, using the same command that we used a moment ago. - The location of the remote computer is stored in a variable called
REMOTE_LINUX
.
With that information, we can use the ssh
command to connect to the remote computer.
- The
sshpass
command is the first command on the connection line. We use it with the-p
(password) option. This lets us specify the password that should be sent to thessh
command. - We use the
-T
(disable pseudo-terminal allocation) option withssh
because we don’t need to have a pseudo-TTY allocated to us on the remote computer.
We’re using a short here document to pass a command to the remote computer. Everything between the two _remote_commands
strings is sent as instructions to the user session on the remote computer—in this case, it’s a single line of Bash script.
The command sent to the remote computer simply logs the user account name and a timestamp to a file called “script.log.”
Copy and paste the script into an editor and save it to a file called “go-remote.sh.” Remember to change the details to reflect the address of your own remote computer, remote user account, and remote account password.
Use chmod
to make the script executable.
chmod +x go-remote.sh
All that’s left is to try it out. Let’s fire up our script.
./go-remote.sh
Because our script is a minimalist template for an unattended script, there’s no output to the terminal. But if we check the “script.log” file on the Fedora computer, we can see that remote connections have been successfully made and that the “script.log” file has been updated with timestamps.
cat script.log
Your Password Is Private
Your remote account password isn’t recorded in the script.
And although the decryption password is, in the script, no one else can access your “.secret_vault.txt” file in order to decrypt it and retrieve the remote account password.