How to use SFTP password authentication in a Bash script using non-interactive (batch) mode

Written by - 0 comments

Published on - Listed in Coding Bash Linux Shell

As mentioned in the previous blog post, I'm currenty working on a SFTP monitoring plugin. To support both key and password authentication methods, I needed to find a way to use the provided password in the sftp command. Turns out this is not straightforward.

Using sftp in script/batch mode

To run sftp non-interactively (within a script), the parameter -b is used. This parameter tells sftp to enter "Batch mode" and read the (s)ftp commands from either a file (/path/to/file) or from stdin (-):

-b batchfile
Batch mode reads a series of commands from an input batchfile instead of stdin.  Since it lacks user  interaction it should be used in conjunction with non-interactive authentication to obviate the need  to enter a password at connection time (see sshd(8) and ssh-keygen(1) for details).

A batchfile of ‘-’ may be used to indicate standard input. sftp will abort if any of the following commands fail: get, put, reget, reput, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, chown, chgrp, lpwd, df, symlink, and lmkdir.

In my script, I am faking the stdin with the input inserted using stdin redirection:

$ sftp -b - <<EOF
> dir
> quit
sftp> dir
sftp> quit

You may notice that the sftp command above did not ask for user/password. In this case my username and ssh keyfile (running in ssh-agent) was used to establish a connection.

Using password authentication in sftp in batch mode

To be able to use user/password credentials with sftp in batch mode, there are basically two things to to consider:

  • Tell sftp to avoid key authentication (and ignore identities in ssh-agent)
  • sftp needs to be able to read the password from somehow

Disable Key Authentication

The first point is necessary because by default sftp tries to use SSH key authentication and immediately fails in batch mode (works without batch mode/in interactive mode though):

$ sftp -b - Permission denied (publickey,password).
Connection closed

On the SFTP server the following log entries appear:

Dec 23 10:38:39 sftp sshd[27691]: Failed publickey for user from port 43202 ssh2: RSA SHA256:VT5LtwGsAG0sUIW9n1OgVfj8HGNbCSEuaBxoN6jMNwY
Dec 23 10:38:39 sftp sshd[27691]: Connection closed by authenticating user user port 43202 [preauth]

To avoid using key authentication, a special SSH option (using -o) can be added to the sftp command to disable PubkeyAuthentication:

$ sftp -b - -o PubkeyAuthentication=no Permission denied (publickey,password).
Connection closed

Although the error message looks the same as before, the logs on the SFTP server shows something different:

Dec 23 10:42:54 sftp sshd[24635]: Connection closed by authenticating user user port 39218 [preauth]

There was no log entry about a failed public key anymore. In this case the communication was not established simply because the user password was not submitted. And this is when we arrive at the second point mentioned above: sftp needs to be able to read the password from somehow, as there is no sftp parameter (or SSH option) to set a password.

Use sshpass to forward SSHPASS to sftp

In combination with sshpass, the password can be used from the $SSHPASS environment variable and forwarded to the sftp command (see this Stackoverflow answer).

First sshpass needs to be installed, which can be done pretty quickly:

$ sudo apt install sshpass

According to the sshpass man page, the command either defines the password using sshpass -p 'password', read the password from a file or can read the password from the $SSHPASS variable. The last approach is much more secure, as the password won't show up in the processlist, so let's go with this solution:

$ SSHPASS=verysecret sshpass -e sftp -b - -P 22 -o PubkeyAuthentication=no <<EOF
> dir
> quit
> EOF Permission denied (publickey,password).
Connection closed

Wait... Why didn't this work now? The password is definitely correct and can be verified using an interactive sftp connection (without the -b):

$ SSHPASS=verysecret sshpass -e sftp -P 22 -o PubkeyAuthentication=no <<EOF
> dir
> quit
Connected to
sftp> dir
sftp> quit

The password is therefore definitely correct. So why wouldn't this work in batch mode (-b)?!

The reason is confusing, to say the least. Per Hedeland answered and explained this to that problem:

At some 3.x version, this was added to sftp.c:
case 'b':
>>>>>>>>>> addargs(&args, "-obatchmode yes");

From ssh_config(5):
If set to ``yes'', passphrase/password querying will be disabled.

This means that by enabling sftp in batch mode (using -b), passphrases (for keys) and passwords are disabled.

But Per also had a solution for this:

I guess this is unlikely to change though, and given that, it is now possible to do the opposite, i.e. override the "builtin" BatchMode setting on the sftp command line:

sftp -o "batchmode no" -b /tmp/bat user@host

Note that it must come *before* -b, which may be surprising - this is due to ssh processing -o options as if they were read from the config file - ssh_config(5) again.

By adding yet another SSH option "BatchMode=no" before sftp's -b parameter, the password (submitted by sshpass) is suddenly read by sftp:

$ SSHPASS=verysecret sshpass -e sftp -o BatchMode=no -b - -P 22 -o PubkeyAuthentication=no <<EOF
> dir
> quit
sftp> dir
sftp> quit

The connection worked!

TL;DR: Using sftp in batch mode with password authentication

To use the sftp command in batch mode (e.g. in a script) with password authentication, several adjustments to the sftp command must be applied:

  • Disable Key Authentication with -o PubkeyAuthentication=no
  • Use sshpass to read the value of the environment variable $SSHPASS as password
  • Use an additional SSH option -o BatchMode=no before the -b parameter

Working sftp command in batch mode using password authentication in a script:

$ cat
export SSHPASS="verysecret"

sshpass -e sftp -P 22 -o BatchMode=no -o PubkeyAuthentication=no -b - <<EOF
cd ${directory}

Add a comment

Show form to leave a comment

Comments (newest first)

No comments yet.