how to pass password to a command in bash - 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

Related

Expect script with encrypted passwords returning string with single quotes

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?

Auto answer ssh-copy-id in shell script

I'm writting a shell script and I want to automate login into a remote machine using ssh-copy-id, so manually when I print :
ssh-copy-id -i /root/.ssh/id_rsa $2#$4 -p $3 | echo $1
$1 refer to password,
$2 refer to username,
$3 refer to port, and
$4 refer to ip,
It is ok with that, the problem is that I have to automate inserting password after :
ssh-copy-id -i /root/.ssh/id_rsa $2#$4 -p $3
I add this "| printf $1", but it does not work it shows "password:" in the screen and still wait for the password ..
I hope you understand me and thank you.
As #Leon pointed out, you had the pipeline backwards. But even if you do it with the correct order, it will still not work because ssh-copy-id (and all other programs from openssh) do not read passwords from their stdin. The solution is to use the $SSH_ASKPASS environment variable. You can do that as follows: first, create an auxiliary script, say /var/tmp/ssh-pass.sh (actually find a better name than that), with the following contents:
#!/bin/sh
echo "$PASS"
Then you can use the following command to accomplish what you've asked for:
PASS="$1" SSH_ASKPASS="/var/tmp/ssh-pass.sh" setsid -w ssh-copy-id -i /root/.ssh/id_rsa "$2"#"$4" -p "$3"
Explanation: we use setsid -w to disassociate the ssh-copy-id process from the currently used terminal. That forces ssh-copy-id to run the executable specified in the $SSH_ASKPASS in order to obtain the password. We have specified our own script in that variable, so ssh-copy-id will execute just that. Now the script is supposed to provide the password to ssh-copy-id by printing it to its stdout. We use the $PASS variable to the password to the script, so the script just prints that variable.
2020 / Mac OS X:
Install sshpass (original answer)
brew install hudochenkov/sshpass/sshpass
Run ssh-copy-id using sshpass and with the password as an arg
sshpass -p $1 ssh-copy-id -i ~/PATH/TO/KEY $2#$4 -p $3
If you want to turn off strict host checking as well, use the -o flag, which is passed to the underlying ssh:
sshpass -p hunter2 ssh-copy-id -o StrictHostKeyChecking=no -i ~/PATH/TO/KEY $2#$4 -p $3
I tried the solution by #redneb, and installed setsid through util-linux by following this answer, but kept receiving a password denied.
I found this strategy to work for uploading my SSH key while setting up multiple raspberry pis in successino. In my script, I also run ssh-keygen -R raspberrypi.local each time too, to avoid the The ECDSA host key for raspberrypi.local has changed error.

bash: while read loop - stop if there is variable sshpass

i have a problem with my bash script. I read line by line the variable lvm_path_exec, that works. I confirmed it with echo "lvmpath".
But as soon as i place a sshpass command into the while statement the script only process the first line which got grepped.
If there is no sshpass command all lines of lvmpath_exec get processed.
Do you see the error?
lvmpath_exec=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvdisplay | grep datatest -A 3 | grep Path | awk '{ print $3 }')
echo "$lvmpath_exec" | while read lvmpath
do
lvmname=datatest
snap=_snapshot
snapname=$lvmname$snap
lvcreate=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvcreate -L20G -s -n $snapname $lvmpath)
snap_path=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvdisplay | grep $snapname -A 3 | grep Path | awk '{ print $3 }')
transfer=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} "dd if=$snap_path | gzip -c" > /tmp/$snapname)
delsnap=$(sshpass -p "${password[$i]}" ssh ${user[$i]}#${ip[$i]} -p ${port[$i]} lvremove -f $snap_path)
done
UPDATE
I fixed it:
replace
echo "$lvmpath_exec" | while read lvmpath
with
for lvmpath in $lvmpath_exec
But shouldnt it work with while read too?
sshpass works by manipulating stdin to fool ssh into thinking it is getting the password from an interactive user. When you use a ... | while style loop, the loop iterates for every line coming from stdin, which sshpass wipes out after the first call, that's why only the first line gets executed. The for loop doesn't use stdin, that's why it doesn't have this problem.
As man sshpass explains, this tool is inherently insecure and you should really be using public key authentication instead. Also keep in mind that it has other ways of passing the password, using the -p flag is the least safe method of all, and any other method would be safer, for example the -e flag seems trivially easy. I know you might insist you have a legitimate use case, but this is so important I'm just gonna quote from the man page:
First and foremost, users of sshpass should realize that ssh's insis‐
tance on only getting the password interactively is not without reason.
It is close to impossible to securely store the password, and users of
sshpass should consider whether ssh's public key authentication pro‐
vides the same end-user experience, while involving less hassle and
being more secure.
The -p option should be considered the least secure of all of sshpass's
options. All system users can see the password in the command line
with a simple "ps" command. Sshpass makes a minimal attempt to hide the
password, but such attempts are doomed to create race conditions with‐
out actually solving the problem. Users of sshpass are encouraged to
use one of the other password passing techniques, which are all more
secure.
have you tried this..have not tried though
export SSHPASS=password[$i]
sshpass -e ssh -oBatchMode=no user[$i]#{ip[$i]} ..

How Decript string previously cripted in BASH?

i have a security problem on a script. I have to pass it a username and password, but i can't give it a password not crypted.
This script is writed in bash.
#!/bin/bash
HOST=$1
USER=$2
PASSWORD=$3
#PASSWORD=`perl -e 'print pack "H*",$PASSWORD'`
wget -v $HOST --http-user=$USER --http-password=$PASSWORD --no-check-certificate
......
I have think to use something like this for generate cripted password:
perl -e 'print unpack "H*","yourpassword"'
and something like this for decript it
descrpt=`perl -e 'print pack "H*","encrypted password"'`
but it doesn't work. Someone could help me please?
Your command doesn't encrypt, it merely encodes the password as a hex string. Any programmer who sees the string will immediately know how to get the plaintext password back.
Instead, pass the password to wget in such a way that people can't just grab it from ps output. Here's one way of doing that:
wget -v "$HOST" --http-user="$USER" --no-check-certificate --config=/dev/stdin <<< "http_password = $PASSWORD"
Problem solved with:
echo $password | openssl enc -base64 -d

Prompting for MySQLDump password in a bash script?

I'm trying to write a bash script that runs a mysqldump command that uses the -p flag. This flag prompts the user for a password, which works as expected when run in the shell directly, but does not appear when run in a script.
#!/usr/bin/env
ssh user#domain.com 'mysqldump -u mysqluser -p --databases foo | bzip2' > ~/temp/foo-dump.sql.bz2
Now I could embed the password in the script or pass it as an arguments, but I really want the script to prompt the user for the password so the password doesn't show up in my scripts repo or in my bash history.
Anyone have any idea on how to accomplish this?
This should do the trick:
read -p "mysql password: " PASS && ssh user#domain.com 'mysqldump -u mysqluser -p'$PASS' --databases foo | bzip2' > foo-dump.sql.bz2 ; PASS=""
In this case, you will first enter the mysql password, and then be prompted for the ssh password. Note that the mysql password will not be hidden, i.e., someone can read it over your shoulder. If you want to avoid that, use the flag -s
read -s -p "mysql password: " PASS && ...
Note also that there mustn't be any space between the "p" (in -p for password) and the quotation mark for the password variable.
Also, your shebang is not specifying which interpreter to use, which might be a problem. I'd suggest you use #!/bin/bash or #!/usr/bin/env bash.

Resources