Expect script with encrypted passwords returning string with single quotes - bash

I am trying to use an expect script to pull configs from cisco devices. Dont ask why the client does not use a standard tool.
My issue is that they wish to use encrypted passwords for the session. I can encrypt and salt the password into a file and then use cat within the expect script to pull out the password into a variable... see code below, however, the exec command puts the string value into single quotes. Expect scripts I believe treat single quotes differently to double and certainly not like a string.
I can validate that the rest of the code works by putting the raw password into the script as a substitude and if I use 'puts' to display the variable it displays
'password'
My thought as I said is that the exec command is then putting the string back with the single quotes around them.
I have tried SED and TR piped into the end of the command string but that still gives the same result as I would expect.
Any thoughts
set salt "mrsalty"
set admincmd "cat /mrpwd.txt | openssl enc -aes-256-cbc -md sha512 -a -d -salt -pass pass:$salt"
set password [ exec sh -c $admincmd ]

(This is not really an answer, more of a long, formatted comment)
the exec command puts the string value into single quotes
No it does not.
A demo:
First, create an encrypted password file in the shell
$ salt=mrsalty
$ echo MyPass1234 | openssl enc -aes-256-cbc -md sha512 -a -e -salt -pass pass:$salt > pw.encrypted
$ cat pw.encrypted
U2FsdGVkX18bFSAmQbXqGjeSBVtE8AzJ2K8Lif4muB8=
Now in expect
expect1.1> set salt mrsalty
mrsalty
expect1.2> set file pw.encrypted
pw.encrypted
expect1.3> set password [exec openssl enc -aes-256-cbc -md sha512 -a -d -salt -pass pass:$salt -in $file]
MyPass1234
No single quotes there.
Even with storing the command in a variable and using sh
expect1.4> set admincmd "cat $file | openssl enc -aes-256-cbc -md sha512 -a -d -salt -pass pass:$salt"
cat pw.encrypted | openssl enc -aes-256-cbc -md sha512 -a -d -salt -pass pass:mrsalty
expect1.5> set password [exec sh -c $admincmd]
MyPass1234
How are you using $password later in the expect code?

Related

Cannot read encrypted password in shell script

I'm trying to connect to a Tableau Server using an encrypted password. The usual command to connect is:
tabcmd login -u user -p password
I have encrypted a password and stored it into a text file with the following script.
echo "strongpw" | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 \
-salt -pass pass:Secret#123# > secret.txt
strongpw being the string I want to encrypt
Secret#123# being the password that is used during the encryption
Once that done, I have a secret.txt file with something like this:
U2FsdGVkX1/VyNZZ/RTaymM4F5DHNNG0iYapp3u3+WI=
I can then use the following script to decrypt my password:
cat secret.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 \
-salt -pass pass:Secret#123#
output: strongpw
Finally, I created an .sh script the user might execute to connect to the server.
The script is supposed to decrypt the password and store it in the variable.
#bin/bash
USERNAME=test
PASSWD=`cat secret.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 \
-iter 100000 -salt -pass pass:Secret#123#`
tabcmd login -u $USERNAME -p $PASSWD
I then made my script executable with chmod +x
Unfortunately, when trying to running, I'm always encountering either invalid argument or extra arguments given as errors.
Any suggestion on how to fix this?
Thank you!
maybe you can try with the '-in' tag to provide the input file instead of using cat?
Thanks to #MarcoLucidi for showing me shellcheck.net :)
Here's how I had to modify my .sh file to make it work:
#bin/bash
USERNAME=test
var=$(cat secret.txt | openssl enc -aes-256-cbc -md sha512 -a -d -pbkdf2 -iter 100000 \
-salt -pass pass:Secret#123#)
tabcmd login -u “$USERNAME” -p “$var”
tabcmd runschedule "PMS Daily 6AM"

Hiding sensitive ruby shell commands

I'm using fastlane and sh command to decrypt some credentials but seems ruby prints the output in logs. How do I hide the sensitive information from logs?
cmd_decrypt = "openssl enc -aes-256-cbc -d -a -k \"#{ENV["MATCH_PASSWORD"]}\" -in #{enc_file} -out #{dec_file[0]}"
sh(cmd_decrypt)
output:
[09:38:15]: --------------------------------------------------------------------
[09:38:15]: Step: openssl enc -aes-256-cbc -d -a -k "PASSWORD_SHOWN!" -in /var/folders/7g/yy/T/d20190925-1304-1qv6cj1/vault/zz-out /var/folders/7g/yy/T/d20190925-1304-1qv6cj1/vault/xx
[09:38:15]: --------------------------------------------------------------------
[09:38:15]: $ openssl enc -aes-256-cbc -d -a -k "PASSWORD_SHOWN!" -in /var/folders/7g/yy/T/d20190925-1304-1qv6cj1/vault/zz -out /var/folders/7g/yy/T/d20190925-1304-1qv6cj1/vault/xx
You can pass sh extra parameters. In this case, you would call it like this:
sh(cmd_decrypt, log: false)
The documentation for sh is here: https://docs.fastlane.tools/actions/sh/
You get can get the docs for other built-in actions here:
https://docs.fastlane.tools/actions/
And the docs for other plugin's actions here: https://docs.fastlane.tools/plugins/available-plugins/
Since you have an environment variable, why not just run with that?
cmd_decrypt = "openssl enc -aes-256-cbc -d -a -k \"$MATCH_PASSWORD\" -in #{enc_file} -out #{dec_file[0]}"
sh(cmd_decrypt)
From there shell interpolation should take over and make it work. One thing to note is your -in parameter doesn't have shell escaping, which it usually must have, done using shellescape.
You really should be specifying these as separate arguments, though, whenever possible to avoid injection issues. The problem is you lose shell interpolation at that point.
The good news is you can always write a wrapper script to provide safety and ease of use, something like:
#!/bin/sh
# descrypt.sh
openssl enc -aes-256-cbc -d -a -k "$MATCH_PASSWORD" -in $1 -out $2
So then you can call it like this:
sh('descrypt.sh', enc_file, dec_file[0])
Now it logs something a lot quieter as well as a bonus. You can pick which arguments to pass through, or even throw them all through with $*.

Bash special character used in YAML file

I am struggling with some bash script that generates some Environment Variables for me. I am using it in .travis.yml file later.
My encrypted key looks like that:
someRandomCharacters
withNewLine
In Terminal I checked three possibilities.
echo "someRandomCharacters
withNewLine" | openssl enc -aes-128-cbc -a -salt -pass pass:SomePassword -base64 -d
and
echo "someRandomCharacters\nWithNewLine" | openssl enc -aes-128-cbc -a -salt -pass pass:SomePassword -base64 -d
will give me correct output.
echo "someRandomCharactersWithNewLine" | openssl enc -aes-128-cbc -a -salt -pass pass:SomePassword -base64 -d
This one above will return error reading input file
So far so good - I understand why it works like that. But when I try to enter any of abovementioned options - for example like that:
- SOME_ENV=`echo "someRandomCharacters\nWithNewLines" | openssl enc -aes 128-cbc -a -salt -pass pass:SomePassword -base64 -d`
into travis.yml, two last options will return error reading input file and the first one will crash the whole build due to incorrect .yaml syntax.
I've tried to use any of these three above + many more for example with "\n" as special character as I found in examples here on STO. Any of them would return error reading input file and none of them returned me decrypted SOME_ENV into travis. Is there any solution for that? Or maybe my poor experience with BASH and YAML blocks me for seeing obvious mistake?
While it's hard to tell what exactly the problem is given fake data, here are some data points:
dash (the shell you get if you just run sh on modern Linux distros) and bash behave differently in certain cases.
You should never assume that a code snippet runs with bash, because any number of reasons can cause it to be run with sh instead, and it's sometimes hard to tell.
Here's a script containing a \n sequence that works with sh but fails with bash:
$ cat myfile
echo "U2FsdGVkX19EB+D8no\n9+9bnl4dE5H2WbOUSvsGZjK7s=" | openssl enc -aes-128-cbc -a -salt -pass pass:MyPassword -base64 -d
$ sh myfile
My test data
$ bash myfile
error reading input file
If we instead use echo -e, we get the opposite result where dash fails and bash works:
$ cat myfile
echo -e "U2FsdGVkX19EB+D8no\n9+9bnl4dE5H2WbOUSvsGZjK7s=" | openssl enc -aes-128-cbc -a -salt -pass pass:MyPassword -base64 -d
$ sh myfile
error reading input file
$ bash myfile
My test data
This is why POSIX recommends not using echo. If we instead use printf, it works on both:
$ cat myfile
printf "U2FsdGVkX19EB+D8no\n9+9bnl4dE5H2WbOUSvsGZjK7s=\n" | openssl enc -aes-128-cbc -a -salt -pass pass:MyPassword -base64 -d
$ sh myfile
My test data
$ bash myfile
My test data
However, the line feed sequence in the middle is optional for openssl, and can just be removed (even though you seem to say that this doesn't work: maybe you removed the \ but not the n?)
$ cat myfile
echo "U2FsdGVkX19EB+D8no9+9bnl4dE5H2WbOUSvsGZjK7s=" | openssl enc -aes-128-cbc -a -salt -pass pass:MyPassword -base64 -d
$ sh myfile
My test data
$ bash myfile
My test data

OpenSSL Command Line Tool: "-in" argument from string

How can I trick the -in argument of the OpenSSL command line tool in order to get data from string instead a file?
Normally, I could use echo command to do it:
echo 'test string 1' | openssl enc -aes-256-cbc -a -salt -pass pass:mypassword
Is there a way I can do it without echo and pipe? Similar to the -pass pass: argument?
Thanks in advance!
If your shell is bash and your OS supports it, you can use process substitution:
openssl enc -in <(echo 'test string 1') -aes-256-cbc -a -salt -pass pass:mypassword
I found a way to go around this! Instead of passing everything before and since openssl has an interactive mode, it's possible to run the command without input:
openssl enc -aes-256-cbc -a -salt -pass pass:mypassword
And OpenSSL will be waiting for data to encrypt. This can be also useful for streams!
Then type in the string or data you want to encrypt and send a EOT (End of Transmission) in Terminal is usual ^D Control+D it it will output to stdout the encrypted string!
Hope this may help someone some day!

how to pass password to a command in bash

I want to write a bash script that will execute one command in the script, and the command need read some thing as password. So how can I pass the password to the command in the script?
$ota_gen -k $ota_key -i $1 -p $ota_tools $2 $ota_out_file
ota_key is a private key that need to be visited with a password, so how can I do it?
thank you.
ps: thanks hlovdal for help.
expect maybe what can help. But I don't know if it can interact with bash script, such as how to pass parameters from script to expect.
A quite common tool for feeding programs with proper input (like for instance passwords) non-interactively is the tool expect. The following example is given on the wikipedia page:
# Assume $remote_server, $my_user_id, $my_password, and $my_command were read in earlier
# in the script.
# Open a telnet session to a remote server, and wait for a username prompt.
spawn telnet $remote_server
expect "username:"
# Send the username, and then wait for a password prompt.
send "$my_user_id\r"
expect "password:"
# Send the password, and then wait for a shell prompt.
send "$my_password\r"
expect "%"
# Send the prebuilt command, and then wait for another shell prompt.
send "$my_command\r"
expect "%"
# Capture the results of the command into a variable. This can be displayed, or written to disk.
set results $expect_out(buffer)
# Exit the telnet session, and wait for a special end-of-file character.
send "exit\r"
expect eof
OK, I google and get the answer of how to interact with expect in bash script.
I have added lines bellow in my script.Ant it tack effect.
th
EXEC=$(expect -c "
spawn $ota_gen -k $ota_key -i $1 -p $ota_tools $2 $ota_out_file
expect \"Enter password for .... key>\"
send \"$PASSWD\r\"
interact
")
echo $EXEC
If you are passing sensitive information around and use it regularly you are probably best encrypting it.
Putting something like
#create key as follows - will prompt for password
#echo -n 'secret you want encrypted' | openssl enc -aes-256-cbc -a -salt -pbkdf2|base64
export MY_SECRET='VTJGc2RHVmtYMTlzVnBGWXNYUitLWlpYT3BWdStaQXJXeUVwc1JORnFsNWswZXJKT1dkRWpsWkxLWVFnK1hONQo='
Into your .bashrc will give you an encrypted environment variable that you can access where ever you need a secret, and you will be prompted for you passphrase/password that you used when creating the environment variable.
In the example above it is 'secret'
You access it is a command as follows
`echo $MY_SECRET|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2 `
e.g.
xfreerpd /parameters.... /p:`echo $MY_SECRET|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2`
For your query where $ota_key is the secret
$ota_gen -k $ota_key -i $1 -p $ota_tools $2 $ota_out_file
You can create the variable as follows
ota_key=`echo -n 'secret you want encrypted' | openssl enc -aes-256-cbc -a -salt -pbkdf2|base64`
Then use it as follows
$ota_gen -k `echo $ota_key|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2 ` -i $1 -p $ota_tools $2 $ota_out_file
openssh will prompt you for a password to encrypt and decrypt each time, you can supply one as part of the command, but then you are just hiding things from the history etc. Have a look at https://www.tecmint.com/generate-encrypt-decrypt-random-passwords-in-linux/ for some info on using openssh for this. https://www.serverlab.ca/tutorials/linux/administration-linux/how-to-base64-encode-and-decode-from-command-line/ for base64 and How to assign an output to a shellscript variable? for different options on command substitution I have used back-tick ` above
PS Adding a function like
get-key()
{
echo -n "$1"|base64 --decode|openssl enc -aes-256-cbc -a -d -salt -pbkdf2
}
To your bashrc gives you quick access to the secret if you need it

Resources