Introduction
This tutorial shows you how to setup a minimal working chroot jail restricting some user logging in via SSH to just the login shell.
Besides having an already installed and running SSH server we will start from scratch.
Prerequisites
- SSH service based on OpenSSH installed
Step 1 - Provide chroot environment
Step 1.1 - Minimal setup
All binaries that shall be executed in the chroot environment along with their dependencies on the shared linked objects must be part of the chroot environment.
First create a new directory which will be root for the chroot environment. For this tutorial the directory /chroot-jail-root
will be used. As the login shell is minimal required it must be copied at least.
mkdir -p /chroot-jail-root/usr/bin && cp /usr/bin/bash /chroot-jail-root/usr/bin/bash
When you try to chroot into this directory you will see an error saying that bin/bash
is not found. In reality the binary exists but required libraries are not yet part of the chroot environment.
ldd
does the job of printing the dependencies:
- Archlinux:
$ ldd /usr/bin/bash
linux-vdso.so.1 (0x00007ffeeddfc000)
libreadline.so.8 => /usr/lib/libreadline.so.8 (0x00007f806dfb9000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f806dfb2000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f806dde5000)
libncursesw.so.6 => /usr/lib/libncursesw.so.6 (0x00007f806dd74000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f806e118000)
- Debian
$ ldd /usr/bin/bash
linux-vdso.so.1 (0x00007ffc6cfa4000)
libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f864f0f3000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f864f0ee000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f864ef2d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f864f250000)
The linux-vdso.so.1
is virtual so you can ignore this dependency.
So we create the directory for the library and copy the required shared object files into the newly created directory:
mkdir -p /chroot-jail-root/usr/lib
ln -rs /chroot-jail-root/usr/lib /chroot-jail-root/lib
ln -rs /chroot-jail-root/usr/lib /chroot-jail-root/lib64
cp /usr/lib/libreadline.so.8 /usr/lib/libdl.so.2 /usr/lib/libc.so.6 /usr/lib/libncursesw.so.6 /usr/lib64/ld-linux-x86-64.so.2 /chroot-jail-root/usr/lib/
If you did everything correctly chroot /chroot-jail-root/ /usr/bin/bash
should work now.
Step 1.2 - Provide functionality of binaries
As the chroot command works now, we can provide some basic configuration and files which will be most likely required.
Copy minimal set of configuration files:
mkdir -p /chroot-jail-root/etc /chroot-jail-root/usr/share
cp /etc/{group,passwd,shadow,hosts} etc/
cp -r /usr/share/terminfo /chroot-jail-root/usr/share/
Other files that might be desired:
/etc/bash.bashrc
/etc/inputrc
Provide the special files in directories in /dev
:
mkdir /chroot-jail-root/dev
mknod /chroot-jail-root/dev/null c 1 3
mknod /chroot-jail-root/dev/zero c 1 5
mknod /chroot-jail-root/dev/tty c 5 0
mknod /chroot-jail-root/dev/random c 1 8
mknod /chroot-jail-root/dev/urandom c 1 9
chmod 0666 /chroot-jail-root/dev/{null,tty,zero}
chown root:tty /chroot-jail-root/dev/tty
In case you want to translate the user and group ids into readable strings you will need to setup the NSS by copying the following files into the chroot environment:
/etc/nsswitch.conf
libnss_systemd.so
libnss_files.so
libcrypt.so
Continue copying desired binaries and libraries.
You can copy ldd
into the chroot to check binaries inside the chroot environment if all required shared object files are present.
Tip: Play around with whoami
and strace
(look out for openat()
calls resulting in ENOENT
) to identify the required files.
Step 1.3 - Optional extensions to the chroot environment
Here are some ideas you could apply to the chroot environment, which won't be described within this tutorial but might give you a starting point for internet research:
- Maintain files within chroot environment by package manager
- archlinux:
pacman --dbpath <db_path> --cachedir <cache_dir> --config <config_file> --root <chroot root directory>
where root is/chroot-jail-root/
and all other files and directories are located outside of the chroot directory
- archlinux:
Step 2 - Create user
Create the user that shall jailed into the chroot environment.
The user name used in this tutorial will be called prisoner
and use the bash as login shell.
Move or create the home directory of the prisoner
user into the chroot environment.
mkdir -p /chroot-jail-root/home
useradd --base-dir /chroot-jail-root/home --create-home --shell /usr/bin/bash prisoner
Copy the changed /etc/passwd
, /etc/shadow
, /etc/group
into the chroot environment.
Step 3 - Configure SSH to chroot
Edit the configuration /etc/ssh/sshd_config
as required to jail a user, group, host, local address, local port, address.
For more details see man sshd_config
.
Match User prisoner
ChrootDirectory /chroot-jail-root
PasswordAuthentication no
To apply the changes restart the sshd daemon or trigger a reload of the configuration.
systemctl reload sshd.service
Step 4 - Configure SSH login (Optional)
We want to allow the prisoner
user to login with a SSH key, as SSH employs a strict check of the access level to ~/.ssh
directory and authorized_keys
file, make sure to set comply with the rules (.ssh
owned by the user and authorized_keys
file only readable (and writable) for the user).
su prisoner
mkdir -p ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit
Copy the desired public keys into the authorized_keys
file (absolute path is /chroot-jail-root/home/prisoner/.ssh/authorized_keys
).