Setting Up SFTP Jail on Linux
SFTP jail, often referred to as a chroot jail or SFTP chroot, is a security mechanism used to restrict users to a specific directory and its sub-directories when they connect via the Secure File Transfer Protocol (SFTP).
The term "jail" is used to convey the idea that the user is confined to a designated area, unable to navigate beyond it.
User/Group configurations
This setup was tested on a debian server. You will find as well an automated script at the end to manage the sftp configurations.
Create a group
By assigning users to a specific group associated with the SFTP jail, you can implement fine-grained access control. Group membership allows you to define permissions for the jail directory and its contents.
GROUP_NAME=jail_group
sudo groupadd $GROUP_NAME
Create a user
For security reasons, the user to be used by the SFTP jail should not have a login shell.
In addition, it's better to disable password authentication and only use ssh key-based authentication:
USER_NAME=user1
GROUP_NAME=jail_group
useradd -g $GROUP_NAME -d /home/$USER_NAME/ -m -s /sbin/nologin $USER_NAME
This will set the home directory for the user1 to /home/user1, create the home directory using the -m option, add the user to the created group and disable ssh access by setting the shell to /sbin/nologin
Set the correct permissions
When the user and group are ready, it's time to configure the permissions correctly
USER_NAME=user1
GROUP_NAME=jail_group
chown root:root /home/$USER_NAME
chmod 755 /home/$USER_NAME
mkdir -p /home/$USER_NAME/.ssh/
touch /home/$USER_NAME/.ssh/authorized_keys
chmod 600 /home/$USER_NAME/.ssh/authorized_keys
chmod 700 /home/$USER_NAME/.ssh
chown -R $USER_NAME:$GROUP_NAME /home/$USER_NAME/.ssh
mkdir /home/$USER_NAME/data
chown -R $USER_NAME:$GROUP_NAME /home/$USER_NAME/data
chmod 700 /home/$USER_NAME/data
This will set the correct permission for the ssh directory used for the user authentication and make sure the data directory is owned by the required user only with a read/write/execute permissions.
Configure SFTP jail
Enable the SFTP subsystem
Usually, the sshd config file is located at /etc/ssh/sshd_config.
The subsystem is an alternative implementation of SFTP provided internally by the SSH server itself. It's designed to improve performance and security by integrating SFTP functionality directly into the SSH server process, rather than relying on an external SFTP server process.
Edit the /etc/ssh/sshd_config to disable the old SFTP subsystem then enable the new one
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
Configure the user/group jails
To make the management easier, I will create two configuration files.
The /etc/ssh/sshd_config.d/sftp-jail-group.conf to hold the jail group configurations with the following content:
Match Group jail_group
ChrootDirectory /home/%u
PubkeyAuthentication yes
ChallengeResponseAuthentication no
PasswordAuthentication no
AllowTcpForwarding no
PermitTunnel no
X11Forwarding no
PermitTTY no
The ChrootDirectory is a directive used in the SSH daemon to specify the root directory for a user after they successfully authenticate and connect via SSH or SFTP.
The %u is used to match the username.
The other remaining configs will make sure that the password-based authentication is disabled and only the key-based authentication is enabled for this group.In addition, the port forwarding and TTY should be disabled for security reasons.
This is the purpose of creating the /home/$USER_NAME/data directory which is owned by the user with the read/write/execute permissions.
This configs will be applied for all users in the jail_group group because of Match Group jail_group.
The /etc/ssh/sshd_config.d/sftp-jail-user.conf:
Match User user1
ForceCommand internal-sftp -d /data
AuthorizedKeysFile /home/%u/.ssh/authorized_keys
This will hold the user configurations.
The ForceCommand directive is used to specify a command to be executed for all connections, regardless of what command the client requested to execute. In the case of SFTP, internal-sftp is a built-in subsystem of OpenSSH that handles SFTP connections.
The -d option provided alongside internal-sftp specifies the directory to which the SFTP session will be chrooted. So when the user1 login using SFTP, he will be chrooted to the data directory by default.
As I will be using key-based authentication, the AuthorizedKeysFile will be used to set the authorized_keys path.
Finally restart sshd using:
systemctl restart sshd
Testing
This can be tested using the sftp command.
test@test:~$ sftp [email protected]
Connected to 192.168.1.50.
sftp> put test
Uploading test to /data/test
test
sftp> ls
test
sftp> pwd
Remote working directory: /data
sftp> cd /
sftp> pwd
Remote working directory: /
sftp> put test
Uploading test to /test
dest open "/test": Permission denied
sftp>
As you see, the default working directory is /data. If you navigate to the outside of the data directory, you will get a permission denied issue. Same when trying to upload file to any directory outside the /data
Enable/Disable user
If you want to prevent the user from login, you can simply disable the user using:
USER_NAME=user1
usermod -e 1 $USER_NAME
If the user try to login, he should get the following message:
test@test:~$ sftp [email protected]
Your account has expired; please contact your system administrator.
Connection closed by 192.168.1.50 port 22
Connection closed.
Connection closed
If you want to enable it again, this can be done using:
USER_NAME=user1
usermod -e "" $USER_NAME
Automation
I've developed a fully automated script to streamline the management of user/group SFTP jails. You can find the script in my GitHub repository.
SFTP jails offer a robust and secure solution for restricting user access to designated directories, enhancing data protection and system security. By confining users to their respective directories, SFTP jails help enforce access control policies and minimize the risk of unauthorized data access or manipulation.