749

How to automate SSH login with password? I'm configuring my test VM, so heavy security is not considered. SSH chosen for acceptable security with minimal configuration.

ex)

echo password | ssh id@server

This doesn't work.

I remember I did this with some tricks somebody guided me, but I can't remember now the trick I used...

7
  • 2
    FreeBSD did not accept password-less keys. Don't be tempted. However some Linux servers accepted it. I believe the Linux server was misconfigured.
    – Eonil
    Mar 1, 2011 at 14:32
  • 44
    This is a valid question. For example, I want to allow a user to enter a password, then login in to another machine using it. I can't assume that there will be ssh keys distributed across all our machines. The answers below so far do not help this situation.
    – dfrankow
    Apr 12, 2012 at 16:30
  • 1
    Very important question. I need an answer too, my webspace provider blocks to put keyfiles on the server, so I must pass the passwort without keyfiles.
    – Radon8472
    Jul 11, 2018 at 13:45
  • 1
    Here is a purely bash answer, --- file starts --- #!/bin/bash [[ $1 =~ password: ]] && cat || SSH_ASKPASS="$0" DISPLAY=nothing:0 exec setsid "$@" --- file ends--- Save it as pass, do a chmod +x pass and then use it like this: $ echo mypass | ./pass ssh user@host Sep 14, 2020 at 0:09

8 Answers 8

905
$ sudo apt-get install sshpass
$ sshpass -p your_password ssh user@hostname
27
  • 75
    Yup, sometimes you can't use key based auth for various reasons.. for example right now I can't use keyauth on a plesk server because out the box it's not enabled and I don't have root.
    – John Hunt
    Jul 4, 2013 at 13:33
  • 29
    +1! As a side note, you need to run plain ssh once before using sshpass, in order to confirm the RSA fingerprint Aug 2, 2013 at 8:08
  • 55
    -1 for having to use the password in the command. This logs the password at .bash_history in plain text on your machine.
    – user164495
    Apr 11, 2014 at 21:18
  • 25
    @MisterDood You could run history -r after the command to erase your history. Good point though. May 14, 2015 at 18:37
  • 44
    Pro tip: If you don't want to have a specific command show up in .bash_history, prefix the command with a space. It just works. However, users of this command should be more concerned that non-privileged users on the system can see the full command-line with ps, which, of course, includes the password. Since ssh sessions tend to be long-lived, this is a security issue. Jul 16, 2016 at 15:47
128

While the correct answer for your question is sshpass (see other answer for details), there is a more secure way - SSH keys. You are just three easy steps away from the solution:

All the following commands are being run on the client side, i.e. your machine

Enter the following command to start generating a rsa keypair:

# ssh-keygen

When the message 'Enter file in which to save the key' appears, just leave the filename blank by pressing Enter.

When the terminal asks you to enter a passphrase, just leave this blank (Warning: read below) too and press Enter.

Then copy the keypair onto the server with one simple command:

# ssh-copy-id userid@hostname

you can now log in without a password:

# ssh userid@hostname

WARNING: Leaving SSH keys exposed without encrypting them is a not good practice even if you encrypt your whole drive. What is much safer is to actually enter a passphrase when generating keys and then use Keychain (MacOS, Linux) or SSH agent to remember the passphrase until you signout or suspend or timeout, depending on what you prefer.

17
  • 2
    Works fine with the default values. Using ~/rsa4live.pub didn't work for me when attempting ssh-copy-id. Jun 4, 2015 at 10:08
  • 1
    If you want this steps to work for different user, 1. ssh-keygen 2. ssh-copy-id nazir@hostname 3. ssh nazir@hostname Jun 17, 2016 at 10:23
  • 2
    For me it was ssh-copy-id -i ~/.ssh/tatu-key-ecdsa user@host Sep 8, 2017 at 21:47
  • 60
    This isn't an answer to the question. Nov 27, 2017 at 23:10
  • 6
    And? The answer is above, sshpass...
    – lzap
    Nov 30, 2017 at 16:21
64

Use expect:

#!/usr/bin/expect -f
#  ./ssh.exp password 192.168.1.11 id
set pass [lrange $argv 0 0]
set server [lrange $argv 1 1]
set name [lrange $argv 2 2]

spawn ssh $name@$server
match_max 100000
expect "*?assword:*"
send -- "$pass\r"
send -- "\r"
interact

Example:

# ./1.ex password localhost ooshro
spawn ssh ooshro@localhost
ooshro@localhost's password: 
Linux ubuntu-1010-server-01 2.6.35-25-generic-pae #44-Ubuntu SMP Fri Jan 21 19:01:46 UTC 2011 i686 GNU/Linux
Ubuntu 10.10

Welcome to Ubuntu!
 * Documentation:  https://help.ubuntu.com/
Last login: Tue Mar  1 12:41:12 2011 from localhost
7
  • 2
    It worked but it can't print stdout of remote machine.
    – Eonil
    Mar 1, 2011 at 12:41
  • it works well for some machine can't put the key in advance since IP address is changed everytime.
    – larrycai
    Dec 19, 2012 at 6:14
  • 4
    it will be good to add -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null for ssh command as well to avoid accept the machine into known_hosts
    – larrycai
    Dec 19, 2012 at 6:15
  • 1
    B.. b but muh ssh keys...
    – Damien
    Jun 1, 2017 at 5:50
  • More detailed example of this script you can find at: linuxaria.com/howto/… This examples here should work with remote commands too
    – Radon8472
    Jul 11, 2018 at 13:39
58

SSH single sign-on is usually achieved with public key authentication and an authentication agent. You could easily add your test VM key to an existing auth agent (see example below). Other methods such as gssapi/kerberos exist but are more complex.

sshpass

In situations where password is the only authentication method available, sshpass can be used to automatically enter the password. Please pay particular attention to the SECURITY CONSIDERATIONS section of the man page. In all three options, the password is visible or stored in plaintext at some point:

Anonymous pipe (recommended by sshpass)

# Create a pipe
PIPE=$(mktemp -u)
mkfifo -m 600 $PIPE
# Attach it to file descriptior 3
exec 3<>$PIPE
# Delete the directory entry
rm $PIPE
# Write your password in the pipe
 echo 'my_secret_password' >&3
# Connect with sshpass -d
sshpass -d3 ssh user@host

# Close the pipe when done
exec 3>&-

It is quite cumbersome in bash, arguably easier with programming languages. Another process could attach to your pipe/fd before the password is written. The window of opportunity is quite short and limited to your processes or root.

Environment variable

# Set your password in an environment variable
 export SSHPASS='my_secret_password'
# Connect with sshpass -e
sshpass -e ssh user@host

You and root can read your process' environment variables (i.e. your password) while sshpass is running (cat /proc/<pid>/environ | tr '\0' '\n' | grep ^SSHPASS=). The window of opportunity is much longer but still limited to your own processes or root, not other users.

Command-line argument (least secure)

 sshpass -p my_secret_password ssh user@host

This is convenient but less secure as described in the man page. Command line arguments are visible to all users (e.g. ps -ef | grep sshpass). sshpass attempts to hide the argument, but there is still a window during which all users can see your password passed by argument.

Side note

Set your bash HISTCONTROL variable to ignorespace or ignoreboth and prefix your sensitive commands with a space. They won't be saved in history.


SSH public key authentication

# Generate a key pair
# Do NOT leave the passphrase empty
ssh-keygen
# Copy it to the remote host (added to .ssh/authorized_keys)
ssh-copy-id user@host

The passphrase is very important. Anyone somehow obtaining the private key file won't be able to use it without the passphrase.

Setup the SSH authentication agent

# Start the agent
eval `ssh-agent`
# Add the identity (private key) to the agent
ssh-add /path/to/private-key
# Enter key passphrase (one time only, while the agent is running)

Connect as usual

ssh user@host

The advantage is that your private key is encrypted and you only need to enter its passphrase once (via a safer input method too).

5
  • 16
    If you really can't resist answering "don't do that", this is how you should do it! Answer the actual question and then throw in your unsolicited advice at the end. Good job @nrolans.
    – Timmmm
    Dec 18, 2019 at 10:59
  • sshpass is not an option - there is not such thing in git bash. it should be installed Apr 20, 2021 at 10:32
  • ssh-add is what I was looking for! Oct 11, 2021 at 8:22
  • I can't install expect but do have access to ssh. Can't ssh send the password to the other command I'm trying to run? echo $SU_PASSWORD | /afs/cs/software/bin/reaut Nov 25, 2022 at 20:24
  • What is the difference in security between using -d with anonymous pipe (gpg -dq pwd.encrypted >&3 as shown above, and sshpass -f <(gpg -dq pwd.encrypted) ssh host? AFAIK process substitution creates an anonymous pipe.
    – nyg
    Feb 25, 2023 at 1:35
36

I am surprised nobody mentioned plink from the putty-tools package in Ubuntu:

plink user@domain -pw mypass  [cmd]

It also available on Windows and the syntax is mostly compatible with the openssh client.

6
  • 4
    For windows your answer is good, unfurtunally linux / unix user usually dont have plink
    – Radon8472
    Jul 11, 2018 at 13:48
  • 8
    it is in the putty-tools package
    – eadmaster
    Sep 14, 2018 at 16:14
  • 3
    Depending on your circumstances, this is still deeply insecure. Passwords on the command line are visible in the process list and might be logged by your shell.
    – antiduh
    Oct 30, 2019 at 21:29
  • sure it is insecure, btw nothing is stopping you from store and read the password from the KDE Wallet (or GNOME Keyring), or another password manager.
    – eadmaster
    May 8, 2020 at 15:57
  • I don't have plink :( but I do have ssh and need to use my password. Nov 25, 2022 at 20:25
23

This might not be any use to you, but you can do it with Perl:

\#!/usr/bin/perl  
use warnings;  
use strict;  

use Net::SSH::Perl;  
my $host = 'remote.serv.er';  
my $user = 'root';  
my $pass = 'hunter2';  
my $ssh = Net::SSH::Perl->new('$host');  
$ssh->login('$user', '$pass') or die "Oh noes! $!";
1
9

I prefer passh https://github.com/clarkwang/passh

sshpass is broken by design.

when the ssh server is not added already in my known_hosts, sshpass will not show me the message to add the server to my known hosts, passh do not have this problem.

Login to a remote server:

$ passh -p password ssh user@host
3
  • 1
    How to install on mac osx?
    – PKHunter
    Mar 15, 2022 at 21:53
  • @PKHunter the github repo says it works in mac os too, so you have to compile it first, this is what I did in windows too. I do not use mac os so cannot tell you how to compile there , but google can help you, it is one file so easy to compile. Mar 16, 2022 at 6:44
  • @PKHunter it does work on macOS. Here's a 1-liner: git clone https://github.com/clarkwang/passh && cd passh && cc -o passh passh.c && cp passh /usr/local/bin
    – luckman212
    Jul 14, 2023 at 14:57
6

Depending on your automation needs, perhaps Ansible would be a good fit for you. It can nicely manage things like prompting for password, prompting for sudo password, various ways of changing use, securely using encrypted secrets (vault).

If that’s not suitable, I would suggest Expect, as suggested in another answer.

1
  • 5
    Using Ansible for simple ssh automation is like using a caterpillar to perform a headstand on a steeple. Yes, you can do it, but ..
    – Tino
    Jun 29, 2021 at 15:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .