I get no response running
workssh() { sshpass -p "password" ssh user#$1 ;}
It was erroring out due to the host being unknown:
cchilders: [master]$ ssh user#host
The authenticity of host 'host (10.10.10.10)' can't be established.
RSA key fingerprint is aa:aa:aa:aa:aa:aa:aa:aa.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'host, 10.10.10.10' (RSA) to the list of known hosts.
user#host's password:
Last login: Tue Mar 15 11:16:03 2016 from 10.55.55.55
If I log in by hand once and say yes, the function workssh now works. How can I make this command work the first time even iworkssh() { sshpass -p "password" ssh user#$1 ;}f host is unknown? thank you
First of: what #chepner said in the comments; I don't recommend doing this for security reasons. But here's your answer, anyway:
workssh() { if $(grep -vq $1 ~/.ssh/known_hosts); then ssh-keyscan $1 >> ~/.ssh/known_hosts; fi ; sshpass -p "password" ssh user#$1 ;}
Notes: for this to work you will need to have HashKnownHosts set to no in man ssh_config, which, in itself, is considered a security risk.
You can go down the hole as the other answer propose, but if you want to be insecure, there are more simple ways to do that:
workssh() { sshpass -p "password" ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no user#$1 ;}
which will do basically the same. But once more, it is not recommended, because the host checking is the only mechanism protecting you from the Man In the Middle attack, as you have probably already noticed in your testing.
Related
How can you make SSH read the password from stdin, which it doesn't do by default?
based on this post you can do:
Create a command which open a ssh session using SSH_ASKPASS (seek SSH_ASKPASS on man ssh)
$ cat > ssh_session <<EOF
export SSH_ASKPASS="/path/to/script_returning_pass"
setsid ssh "your_user"#"your_host"
EOF
NOTE: To avoid ssh to try to ask on tty we use setsid
Create a script which returns your password (note echo "echo)
$ echo "echo your_ssh_password" > /path/to/script_returning_pass
Make them executable
$ chmod +x ssh_session
$ chmod +x /path/to/script_returning_pass
try it
$ ./ssh_session
Keep in mind that ssh stands for secure shell, and if you store your user, host and password in plain text files you are misleading the tool an creating a possible security gap
You can use sshpass which is for example in the offical debian repositories. Example:
$ apt-get install sshpass
$ sshpass -p 'password' ssh username#server
You can't with most SSH clients. You can work around it with by using SSH API's, like Paramiko for Python. Be careful not to overrule all security policies.
Distilling this answer leaves a simple and generic script:
#!/bin/bash
[[ $1 =~ password: ]] && cat || SSH_ASKPASS="$0" DISPLAY=nothing:0 exec setsid "$#"
Save it as pass, do a chmod +x pass and then use it like this:
$ echo mypass | pass ssh user#host ...
If its first argument contains password: then it passes its input to its output (cat) otherwise it launches whatver was presented after setting itself as the SSH_ASKPASS program.
When ssh encounters both SSH_ASKPASS AND DISPLAY set, it will launch the program referred to by SSH_ASKPASS, passing it the prompt user#host's password:
An old post reviving...
I found this one while looking for a solution to the exact same problem, I found something and I hope someone will one day find it useful:
Install ssh-askpass program (apt-get, yum ...)
Set the SSH_ASKPASS variable (export SSH_ASKPASS=/usr/bin/ssh-askpass)
From a terminal open a new ssh connection without an undefined TERMINAL variable (setsid ssh user#host)
This looks simple enough to be secure but did not check yet (just using in a local secure context).
Here we are.
FreeBSD mailing list recommends the expect library.
If you need a programmatic ssh login, you really ought to be using public key logins, however -- obviously there are a lot fewer security holes this way as compared to using an external library to pass a password through stdin.
a better sshpass alternative is :
https://github.com/clarkwang/passh
I got problems with sshpass, if ssh server is not added to my known_hosts sshpass will not show me any message, passh do not have this problem.
I'm not sure the reason you need this functionality but it seems you can get this behavior with ssh-keygen.
It allows you to login to a server without using a password by having a private RSA key on your computer and a public RSA key on the server.
http://www.linuxproblem.org/art_9.html
I am facing an issue when I run simply these commands.
The remote server want to pass yes to add the key in RSA file because first time connection established with scp.
commands are given below
#!/bin/bash
scp -P58222 root#IP:/root/K /N
/usr/bin/expect -c 'expect "\n" { expect "Are you sure you want to continue connecting (yes/no)?" }'
send "yes\r"
expect "$ "
send "exit\r"
Actually I have to pass yes in my script while asking
The authenticity of host 'ip address (ip address)' can't be established.
RSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx.
Are you sure you want to continue connecting (yes/no)?
Are you sure you want to continue connecting (yes/no)?
how can I get rid of this problem?
with
scp -o StrictHostKeyChecking=no
it is still asking.
scp -o StrictHostKeyChecking=no root#IP:/root/K
Obviously, this isn't a very secure solution. Works for one-shots where you're not concerned about man in the middle, though.
For me, this works:
yes | scp -r /opt/MyFiles root#<MyNewServerIP>:/opt/MyFiles
Regards. =)
Probably the best way to do this would be to use the following command before your scp command:
ssh-keyscan -H ${SSH_HOST} >> ~/.ssh/known_hosts
This will add the SSH_HOST to your known hosts and scp will not complain. Substitute ${SSH_HOST} for the IP address you are trying to connect to.
So far I have this:
sshpass -p "password" ssh -q username#192.168.167.654 " [ "$(whoami)" != "root" ] && exec sudo -- "$0" "$#" ; whoami ; [run some commands as root]"
I keeps giving me username as answer from whoami. I want to be root as soon as I am connected to the server (but I can only connect to it with username). How can I be root throughout the connection to the server?
Clarification:
I want to access a remote server. It is mandatory that I connect as "username" and then switch to root to run and copy files that only root is able to do. So while I am connected to that server via ssh, I want to be root until my commands are over in the remote server. My problem is that I am not able to do so because I don't have the knowledge, hence I am posting it here.
Restrictions:
-can't use rsync.
-have to connect to the server as "username" and then switch to root
sshpass -p "password" ssh -q username#192.168.167.654 exec sudo -s << "END"
whoami
commands to run
END
You can try something like this (untested)
But I've used the same concept to accomplish similar a similar task.
scp FileWithCommands.sh UserName#Hostname:/tmp
ssh Username#HostName "su -s -c /tmp/FileWithCommands.sh"
We have a number of Red Hat linux servers in our IT environment. I am being asked by my team members to write a script (preferably shell script) to change a user's password on each one of those in a single go, using SSH.
I have tried to find a solution but many of the scripts I found are using Expect. We do not have Expect installed on our servers and the system admins have refused to let us install it. Also, the users do not have root access so passwd --stdin or chpasswd cannot be used.
Is there any way a script can be written so that a user can run it and change the password of only his own user on all the servers in a list?
The remote machine(s) do not need expect installed. You can install expect on a local workstation or VM (virtualbox) or whichever *nix box, and write a wrapper that calls this .ex (expect) script (there may be small changes from distro to distro, this tested on CentOS 5/6):
#!/usr/bin/expect -f
# wrapper to make passwd(1) be non-interactive
# username is passed as 1st arg, passwd as 2nd
set username [lindex $argv 0]
set password [lindex $argv 1]
set serverid [lindex $argv 2]
set newpassword [lindex $argv 3]
spawn ssh $serverid passwd
expect "assword:"
send "$password\r"
expect "UNIX password:"
send "$password\r"
expect "password:"
send "$newpassword\r"
expect "password:"
send "$newpassword\r"
expect eof
You do not need root access to use passwd.
This shoud work just fine.
passwd <<EOF
old password
new password
new password
EOF
You should try pssh (parallel ssh at the same time).
cat>~/ssh-hosts<<EOF
user100#host-foo
user200#host-bar
user848#host-qux
EOF
pssh -h ~/pssh-hosts 'printf "%s\n" old_pass new_pass new_pass | passwd'
Building on squashbuff's example, I tried the following, which worked well for me:
#!/bin/bash
for server in `cat hostlist`; do
echo $server;
ssh username#$server 'passwd <<EOF
old_password
new_password
new_password
EOF';
done
Security wise, Could be improved to take input without echoing to the screen OR saving the plaintext to disk.
echo "name:password" | chpasswd
Another possibility: change it manually on one server. Get the encrypted password out of /etc/shadow. Now, do something like this:
for host in $HOST_LIST; do
ssh $host "passwd -p 'encrypted_passwd' user"
done
Of course, 'encrypted_passwd" is what you got out of /etc/shadow where you manually changed the password. And $HOST_LIST is a list of hosts where you want the password changed. That could be created simply with:
export HOST_LIST="server1 server2 server15 server67"
Or perhaps with a file (as others have suggested):
export HOST_LIST=`cat host_list.txt`
Where the file "host_list.txt" has a list of all the systems where you want the password changed.
Edit: if your version of passwd doesn't support the -p option, you might have the 'usermod' program available. The example above remains the same, simply replace 'passwd' with 'usermod'.
Furthermore, you might consider the useful tool pdsh, which would simplify the above example to something like this:
echo $HOST_LIST | pdsh -Rssh -w- "usermod -p 'encrypted_passwd' user"
One last "gotcha" to look out for: the encrypted password likely contains the dollar sign character ('$') as a field separator. You'll probably have to escape those in your for loop or pdsh command (i.e. "$" becomes "\$").
Install sshpass on any of the server from where you want to execute the script.
yum -y install sshpass
Prepare a text file in which you have to pass details like Host, User Name, Password and Port. (Based on your requirement).
192.168.1.2|sachin|dddddd|22
Prepare a script file using below details.
#!/bin/bash
FILE=/tmp/ipaddress.txt
MyServer=""
MyUser=""
MyPassword=""
MyPort=""
exec 3<&0
exec 0<$FILE
while read line
do
MyServer=$(echo $line | cut -d'|' -f1)
MyUser=$(echo $line | cut -d'|' -f2)
MyPassword=$(echo $line | cut -d'|' -f3)
MyPort=$(echo $line | cut -d'|' -f4)
HOST=$MyServer
USR=$MyUser
PASS=$MyPassword
sshpass -p $PASS ssh -p $MyPort -o StrictHostKeychecking=no $USR#$HOST \
-T "echo 'sachin#patel' | passwd --stdin root" \
< /dev/null | tee -a output.log
done
exec 0<&3
An alternative you may want to present to your peers would be to have them use password-less authentication. They'd generate a public/private key pair and register their public key in the ~/.ssh/authorized_keys file on each of the servers they log into.
Can you use Perl?
Here there is an script that changes the password in a set of hosts.
If requires some Perl modules (Net::OpenSSH::Parallel, Expect and their dependencies) installed on the local machine running the script but nothing on the remote servers where the password has to be changed.
Have you tried App::Unix::RPasswd
The passmass script (man page) that comes with Expect doesn't require Expect to be installed on the remote machines.
I just implemented a small tool that changes password for many users/hosts at once. It's java based application so it works on both Windows and Linux. It's free, enjoy :)
Thought I should put my solution in an answer field - not sure if this should be a part of the question..
OK, I have put together a partially working solution using Dennis' suggestion.
servers.txt looks like:
server1
server2
server3
.
.
.
I am using:
for server in `cat servers.txt`; do
ssh $server -l user 'passwd <<EOF
old_pass
new_pass
new_pass
EOF';
done
This produces:
user#server1's password: **<Type password manually>**
(current) UNIX password: New UNIX password: Retype new UNIX password: Changing password for user user.
Changing password for user
passwd: all authentication tokens updated successfully.
user#server2's password: **<Type password manually>**
(current) UNIX password: New UNIX password: Retype new UNIX password: Changing password for user user.
Changing password for user
passwd: all authentication tokens updated successfully.
So here, I still need to type my old password once for each server. Can this be avoided?
If you have ssh, why have passwords in the first place? Push the user's public ssh key to all the servers they're authorized to use and be done with it. This also lets you easily grant and revoke access all you want.
At a previous $dayjob, where we had literally tens of thousands of servers, they had a database of which engineers were allowed on which servers, and the installation of ssh keys was an automated process. Almost NOBODY had a password on ANY machine.
echo -e "wakka2\nwakka2\n" | passwd root
cat /tmp/passwords | ssh $server sudo chpasswd -e
if the password is encrypted, or
cat /tmp/passwords | ssh $server sudo chpasswd
if the password is not encrypted.
/tmp/passwords should have format of "user:password"
The real question is why were they not using some sort of name services? NIS/Yellow Pages or LDAP and you're not having to manually change passwords across a bunch of servers. A user changes their password once and it's done across the domain master.
I'm writing a C Shell program that will be doing su or sudo or ssh. They all want their passwords in console input (the TTY) rather than stdin or the command line.
Does anybody know a solution?
Setting up password-less sudo is not an option.
expect could be an option, but it's not present on my stripped-down system.
For sudo there is a -S option for accepting the password from standard input. Here is the man entry:
-S The -S (stdin) option causes sudo to read the password from
the standard input instead of the terminal device.
This will allow you to run a command like:
echo myPassword | sudo -S ls /tmp
As for ssh, I have made many attempts to automate/script it's usage with no success. There doesn't seem to be any build-in way to pass the password into the command without prompting. As others have mentioned, the "expect" utility seems like it is aimed at addressing this dilemma but ultimately, setting up the correct private-key authorization is the correct way to go when attempting to automate this.
I wrote some Applescript which prompts for a password via a dialog box and then builds a custom bash command, like this:
echo <password> | sudo -S <command>
I'm not sure if this helps.
It'd be nice if sudo accepted a pre-encrypted password, so I could encrypt it within my script and not worry about echoing clear text passwords around. However this works for me and my situation.
For ssh you can use sshpass: sshpass -p yourpassphrase ssh user#host.
You just need to download sshpass first :)
$ apt-get install sshpass
$ sshpass -p 'password' ssh username#server
For sudo you can do this too:
sudo -S <<< "password" command
I've got:
ssh user#host bash -c "echo mypass | sudo -S mycommand"
Works for me.
The usual solution to this problem is setuiding a helper app that performs the task requiring superuser access:
http://en.wikipedia.org/wiki/Setuid
Sudo is not meant to be used offline.
Later edit: SSH can be used with private-public key authentication. If the private key does not have a passphrase, ssh can be used without prompting for a password.
Maybe you can use an expect command?:
expect -c 'spawn ssh root#your-domain.com;expect password;send "your-password\n";interact
That command gives the password automatically.
This can be done by setting up public/private keys on the target hosts you will be connecting to.
The first step would be to generate an ssh key for the user running the script on the local host, by executing:
ssh-keygen
Enter file in which to save the key (/home/myuser/.ssh/id_rsa): <Hit enter for default>
Overwrite (y/n)? y
Then enter a blank password. After that, copy your ssh key onto the target host which you will be connecting to.
ssh-copy-id <remote_user>#<other_host>
remote_user#other_host's password: <Enter remote user's password here>
After registering the ssh keys, you would be able to perform a silent ssh remote_user#other_host from you local host.
When there's no better choice (as suggested by others), then man socat can help:
(sleep 5; echo PASSWORD; sleep 5; echo ls; sleep 1) |
socat - EXEC:'ssh -l user server',pty,setsid,ctty
EXEC’utes an ssh session to server. Uses a pty for communication
between socat and ssh, makes it ssh’s controlling tty (ctty),
and makes this pty the owner of a new process group (setsid), so
ssh accepts the password from socat.
All of the pty,setsid,ctty complexity is necessary and, while you might not need to sleep as long, you will need to sleep. The echo=0 option is worth a look too, as is passing the remote command on ssh's command line.
Take a look at expect linux utility.
It allows you to send output to stdio based on simple pattern matching on stdin.
ssh -t -t me#myserver.io << EOF
echo SOMEPASSWORD | sudo -S do something
sudo do something else
exit
EOF
Set SSH up for Public Key Authentication, with no pasphrase on the Key. Loads of guides on the net. You won't need a password to login then. You can then limit connections for a key based on client hostname. Provides reasonable security and is great for automated logins.
echo <password> | su -c <command> <user>
This is working.
a better sshpass alternative is: passh
https://github.com/clarkwang/passh
Login to a remote server
$ passh -p password ssh user#host
Run a command on remote server
$ passh -p password ssh user#host date
other methods to pass the password
-p The password (Default: `password')
-p env: Read password from env var
-p file: Read password from file
here I explained why it is better than sshpass, and other solutions.
You can also pass various parameters as follows:
echo password | echo y | sudo -S pacman -Syu
(Although that's a bad idea, it's just an example)
I had the same problem. dialog script to create directory on remote pc.
dialog with ssh is easy. I use sshpass (previously installed).
dialog --inputbox "Enter IP" 8 78 2> /tmp/ip
IP=$(cat /tmp/ip)
dialog --inputbox "Please enter username" 8 78 2> /tmp/user
US=$(cat /tmp/user)
dialog --passwordbox "enter password for \"$US\" 8 78 2> /tmp/pass
PASSWORD = $(cat /tmp/pass)
sshpass -p "$PASSWORD" ssh $US#$IP mkdir -p /home/$US/TARGET-FOLDER
rm /tmp/ip
rm /tmp/user
rm /tmp/pass
greetings from germany
titus
Building on #Jahid's answer, this worked for me on macOS 10.13:
ssh <remote_username>#<remote_server> sudo -S <<< <remote_password> cat /etc/sudoers
I once had a use case where I needed to run Sudo and ssh in the same command without stdin specifying all the variables needed.
This is the command I used
echo sudopassword | sudo -S -u username sshpass -p extsshpassword ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no username#ipaddress " CMD on external machine"
Breaking that command into pieces!
This will allow you to run commands through your machine using Superuser:
echo password | sudo -S -u username
This will allow you to pass ssh password and execute commands on external machines:
sshpass -p sshpassword ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no username#ipaddress " CMD on external machine"
make sure you install the sudo and openssh packages on your machine.
One way would be to use read -s option .. this way the password characters are not echoed back to the screen. I wrote a small script for some use cases and you can see it in my blog:
http://www.datauniv.com/blogs/2013/02/21/a-quick-little-expect-script/
USE:
echo password | sudo command
Example:
echo password | sudo apt-get update; whoami
Hope It Helps..
You can provide password as parameter to expect script.
su -c "Command" < "Password"
Hope it is helpful.