The problem

A certain web application requires sftp access to a storage server to use it as external storage. This means that the login credentials (password or private key) will have to be stored on application server, which poses a secrutiy risk for the storage server. If the application server is breached, these credentials will allow unwanted access to the storage server, if the sftp account is not properly restricted.

The solution

In short, the remote sftp access need to be securely setup with the following restrictions:

  • sftp access only, no ssh access (= no login shell)

  • access limited to IP(s) of application server only

  • sftp access to chroot jail only, where read and write are allowed; no read or write accees to any other files or folders

  • all sftp accesses and operations are fully logged

This way, it will be guaranteed that should the application server be compromised, no extra access or attack surface will be gained on the storage server.

The following steps applies to Debian/Ubuntu, but should not differ much in other distributions.

1. Set up user account

Add a dedicated group and user for the remote access:

sudo adduser --group --system --shell /bin/false --no-create-home remote-sftp

The --group switch creates a group with the same name ('remote-sftp'), --system switch avoids asking for user info, --shell switch denies shell access, and --no-create-home avoids creating unused home directory for this user.

Use passwd remote-sftp to set up password for this user, which will also be used for sftp access. If key-based authentication will be used for sftp access, password can be omitted.

Create the folder where remote-sftp will be reading and writing files:

sudo mkdir -p /path/to/remote-sftp-storage/storage
sudo chown remote-sftp:remote-sftp /path/to/remote-sftp-storage/storage

/path/to/remote-sftp-storage/ will be the chroot jail and /path/to/remote-sftp-storage/storage will be the actual place where remote reads and writes are made. Make absolutely sure that "all components of the pathname are root-owned directories which are not writable by any other user or group" [1], meaning that /path, /path/to, and /path/to/remote-sftp-storage must be root-owned and non-writable by others, or in other words with permission 0755.

2. Set up openssh-server

Open /etc/ssh/sshd_config and add the following lines to the end:

Match User remote-sftp, Address !
     PasswordAuthentication no
     PubkeyAuthentication no

Match User remote-sftp, Address
     ChrootDirectory /path/to/remote-sftp-storage
     X11Forwarding no
     AllowTcpForwarding no
     ForceCommand internal-sftp -l VERBOSE -f LOCAL0

Replace with the application server's outgoing IP address. The Match directive dictates that following configurations only apply if the matching conditions are all met. The first one blocks ssh/sftp access from anywhere that is not the application server. The second one restricts access from application server to a chroot jail in /path/to/remote-sftp-storage, no X11 or TCP forwarding, and sftp only. The -l and -f parameters to internal-sftp command dictate logging level and logging facility, respectively [2]. This, however, does only half the job. The next step is required for the log messages to be recorded.

(Note: Other common hardening measures for ssh are still required, but not covered here.)

Restart ssh server for the modified sshd_config to take effect:

systemctl restart ssh

3. Set up rsyslog

Save the following as /etc/rsyslog.d/99-remote-sftp.conf:

local0.* /var/log/remote-sftp-storage.log
$AddUnixListenSocket /path/to/remote-sftp-storage/dev/log

The first line matches the -f LOCAL0 parameter in sshd_config and directs rsyslog where to save the log messages. The second line tells rsyslog where to listen for logging requests, and to make this work, /path/to/remote-sftp-storage/dev folder must exist [1]:

sudo mkdir /path/to/remote-sftp-storage/dev

Finally, restart rsyslog:

sudo systemctl restart rsyslog


[1] man sshd_config

[2] man sftp-server


comments powered by Disqus