5 minutes
Setup a User With Access to Only SFTP and SCP Inside a Chroot Jail on Ubuntu, Manjaro, Arch Linux
A user can be defined as someone who has access to the system, albeit only to the resources for which permission has been granted. Fortunately, adding users on Linux is quite easy thanks to utilities such as useradd
and adduser
.
Nonetheless, creating a user using the useradd
command without any extra arguments will grant that user access to the shell by default. And assuming there are no circumventions or firewall restrictions in place, this allows the user to login remotely if an SSH server is running on the system. Quite often, this behavior is undesirable.
Backstory
On Monday, I had to provision an AWS Lightsail instance running Linux and create a user on the Linux machine. This would then be used by a customer to securely send their logs for us to inspect and troubleshoot.
Being a security enthusiast, it naturally occured to me that the user should
- only be allowed to upload and download content,
- inside a specific directory (and sub-directories) only,
- and not be able to access a shell (i.e disable SSH login for that user).
The rationale behind denying the user access to a shell is to prevent any form of escalation, potentially unauthorized operations, and a listing of the filesystem. Ultimately, all that we want is for the user to transfer files (read and write) within a certain directory.
After some digging, I found that the best approach is to assign a nologin
shell and configure a chroot jail
for the user.
Instructions
Step 1: Create a Group for SFTP-Only Users
First, we create a group called sftp
. You can use any group name that you want. Later on, we’ll configure SSH to impose certain restrictions to all the users of this group.
export GROUP_SFTP="sftp"
sudo groupadd $GROUP_SFTP
Step 2: Setup the User
We can now configure the user. Two variables, NEW_USER
and CHROOT_BASE
, are used to denote the username and the user’s personal directory respectively. In this example, the user we are adding is named alice
.
export NEW_USER="alice"
export CHROOT_BASE="/home/$NEW_USER"
The useradd
command is used to create the user. Please see below how to manage an existing user.
1. For a new user:
sudo useradd $NEW_USER \
-g $GROUP_SFTP \
-d $CHROOT_BASE \
-s /sbin/nologin
Note
/usr/sbin/nologin
in Ubuntu and other Debian derivatives!This automatically adds our user to the group we created above and sets /sbin/nologin
as the user’s shell. Any user whose shell is /sbin/nologin
is automatically denied access to a shell when a login is attempted via SSH.
It’s also important to set a password for the new user.
sudo passwd $NEW_USER
2. For an existing user:
If the user already exists, usermod
should be used instead.
sudo usermod $NEW_USER \
-g $GROUP_SFTP \
-d $CHROOT_BASE \
-s /sbin/nologin
Note
/usr/sbin/nologin
in Ubuntu and other Debian derivatives!Step 3: Create a Chroot Jail
This step consists in creating the directory (chroot jail) where the user is confined to. We also need to set permission 755
on the chroot jail and give the root
user exclusive ownership of the chroot jail.
sudo mkdir -p $CHROOT_BASE/uploads
sudo chmod 755 $CHROOT_BASE
sudo chown root:root $CHROOT_BASE
The uploads
directory inside the chroot jail is where the user will have full read and write access. Therefore, we give ownership of this directory to the user.
sudo chown $NEW_USER $CHROOT_BASE/uploads
Step 4: Update SSH Configuration
Once the user has been restricted to a specific directory and denied access to a login shell, all that is left is to properly configure the SSH service by modifying some settings in the /etc/ssh/sshd_config
file.
sudo nano /etc/ssh/sshd_config
In the /etc/ssh/sshd_config
file, modify the line starting with Subsystem
as follows:
Subsystem sftp internal-sftp
Next, we need to add this block at the end of the /etc/ssh/sshd_config
file:
Match Group sftp
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PasswordAuthentication yes
Below is a description of each directive:
Match Group sftp
: This informs the SSH daemon (sshd) that the following rules should apply to all users belonging to thesftp
group.
ChrootDirectory %h
: Confine users to theirHOME
directory.
ForceCommand internal-sftp
: Request the SSH daemon (sshd) to serve the server-side of the SFTP protocol to stdout and to expect client requests from stdin.
AllowTcpForwarding no
: Disable TCP forwarding to improve security.
X11Forwarding no
: Disallow X11 forwarding as it can be a source of vulnerabilities.
PasswordAuthentication yes
: Allow users to login using password. Set tono
if you want to use public-private key pairs instead.
Step 5: Restart SSH Service
Finally, the SSH service should be restarted to pick up the changes that were made to the sshd_config
file.
sudo systemctl restart ssh
Transferring Files
There are 2 ways to connect to the SSH server: either through the sftp
command or using scp
. I have a penchant for scp
as it is faster than sftp
.
This is because unlike sftp
, scp
does not ACK (acknowledge) packets. However, one caveat of scp
is that it does not allow interrupted file transfers to be resumed. With sftp
, this is possible using the -a
flag when downloading and using the reput
command for uploads.
1. Using SCP (Secure Copy)
a) To upload a file using SCP:
scp ~/source.txt alice@192.168.100.200:/uploads
b) To download a file using SCP:
scp alice@192.168.100.200:/uploads/uploaded.txt ~/Downloads
2. Using SFTP (SSH File Transfer Protocol)
To connect via SFTP:
sftp alice@192.168.100.200
cd uploads
After a successful login, SFTP provides an interactive shell of its own. In order to accomplish anything with SFTP, specific commands are available.
a) Upload a file using SFTP:
put ~/source.txt
b) Resume uploading a file using SFTP:
reput ~/source.txt
c) Download a file using SFTP:
get uploaded.txt ~/Downloads
d) Resume downloading a file using SFTP:
get -a uploaded.txt ~/Downloads
Tip
sftp
.# Footnotes
https://man.openbsd.org/sftp-server
Comments
GUEST
Please wait...