Yet another how to chroot a user guide
There are loads of "how to set up chroot" guides out there, and this is yet another one as I had to piece together quite a few to get things to work they way I needed them to and to my liking. So as I need to make notes for when I inevitably need to set this up again I figure I may as well share those notes. Hopefully this well be a suitably idiot guide. This is written for a Ubuntu system so on other systems your mileage may vary.
The basics
I'm going to break this down to the first steps that are vital for getting any chroot jail to work and then look at making it useful. But even these basic steps could probably be made even more minimal if you really wanted to.
For the purpose of these notes just assume that every
command is either done as
root
or prefixed with
sudo
also that unless explicitly stated that the chroot directory is
the working directory.
Create the basic directories
First create the directory that will be the root of your chroot jail:
mkdir /home/chroot
Within that directory create directories for dev etc bin and tmp and also vitally
lib/x86_64-linux-gnu
mkdir -p dev etc tmp lib/x86_64-linux-gnu
That's the basic structure that's needed to do pretty much anything, other
directories will be created later as needed.
Having created our basic directory structure we can start to populate it with the files we just can't live with out. The idea here is to create as little as possible as the less there is in the jail the less there is to abuse.
Populate $chroot/dev
Next up populate
dev
change into your newly created
dev
directory and
:
- mknod -m 666 null c 1 3
- mknod -m 666 ptmx c 5 2
- mknod ram c 1 1
- mknod -m 444 random c 1 8
- mknod systty c 4 0
- mknod -m 666 tty c 5 0
- mknod tty1 c 4 1
- mknod tty2 c 4 2
- mknod tty3 c 4 3
- mknod tty4 c 4 4
- mknod urandom c 1 9
- mknod -m 666 zero c 1 5
- mkdir pts
- mkdir shm
You quite possibly don't need all of those, but
null
,
random
and
urandom
are almsot certainly required.
The final vital files
Now to add a few things to our new etc directory, as ever depending on what you want to do with your chroot jail you may not need this much - add only the bare minimum you need.
- grep ^root /etc/passwd > passwd
- grep ^user /etc/passwd >> passwd
One further file has to be copied into our chroot jail before
you can even think about testing things. The file
libnss_files.so.2
is required to look verify
the chrooted user in the minimal
/etc/passwd
file.
cp /lib/x86_64-linux-gnu/libnss_files.so.2 /home/chroot/lib/x86_64-linux-gnu/ libnss_files.so.2
Now that's in place we can test the chroot environment:
chroot --userspec=user /home/chroot/
chroot: failed to run command /bin/bash : No such file or directory
Predictably things didn't work, as we have no executables that can be run in the
chroot jail. What executables and other files you need to add depend very much on what
you want to do. I was creating a minimalist user environment so that will be my example.
Making it useful
Populating $chroot/etc
First a few more things in
etc
:
- cp /etc/resolv.conf ./
- cp /etc/localtime ./
- cp /etc/hosts ./
- cp /etc/mailcap ./
- cp /etc/mime.types ./
Create a
profile
of some sort in
etc
to reflect
what you want to do, at the very least you want to set the path.
Depending on how restricted your environment and how much hassle you can live
with - you could make this a non-standard path to obscure things a bit and make it
harder for peopel to guess at things. However due to the assumptions that many many
programs make you'll almost certianly need a
/bin
directory containing
sh
. For the puposes of this example I'm going to assume
almost everything gets dumped in
bin
.
This is where you need to determien what the minimum set of commands are that you want to make available. You also want to make sure there's nothing that is too handy for breaking out of the jail, so really avoid anything setuid or setgid.
For my particular needs I want to mainly use
ksh
and a few other utilities so I copied the following into
bin
- ksh
- pdmenu
- date
- logger
I actually have a few more bits installed but those will do by way of example.
Given the problems that arise from a lack of
/bin/sh
I created a symlink from
ksh
to
sh
and to provide
a restricted shell also to
rksh
Now as I didn't recompile all of those as static binaries they won't work without
also copying across the relevant libraries so time to run
ldd
against each one and see what's needed.
e.g.
ldd ksh
linux-vdso.so.1 => (0x00007fff1dbfe000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9658885000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965857f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f96581b8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9658a92000)
So I can now copy the refernced libraries into the same place within my chroot jail
cp /lib/x86_64-linux-gnu/libdl.so.2 /home/chroot/lib/x86_64-linux-gnu/libdl.so.2
Copy in each library, and then run
ldd
on
the next program and repeat. There are scripts out there
that makes this easier, but it's good to understand how it actually works.
Final steps
That's pretty much it, depending on what the purpose of your chroot is and who'll be using it. In my case I need it for what has to be considered a hostile environment (the Internet), so I want to tighten things up a bit further.
To make life a bit better I created a home directory for the chrooted user,
but then change the ownership and remove all write permissions.
All the profile and
rc
files were created outside of the home directory and
symlinks created for them. Every file and directory which didn't need to be
writable was made read only (so everything but
tmp
and
dev
)
With all that done I added the chroot option to my SSHD config and let people in.
ChrootDirectory /home/chroot
That is of course all well and good if you're using SSH, if
you're using something else such as
telnetd
that
relies on say
/etc/pam.d/login
then you'll need
to configure
pam_chroot
. Thankfully this is also
surprisingly easy. Just edit the relevant PAM configuration
file (let's assume
login
) to add the line:
session required pam_chroot.so
in the relevant place. Then create or edit the file
/etc/security/chroot.conf
to add the user to be
chrooted and where their jail is. The
JailKit
page goes into more details about this.
Futher gotchas
Given that package managers are all the rage these days and often safer than compiling your own. If you want to download and install a package in chroot without breaking your main system. Say maybe a lighter mail server. Then you'll want to follow these instructions:
-
Download the package
.debfile, via whatever mechanism you like. -
Run the command
dpkg-deb -x package-name.deb output-directory - look in the output directory for the extracted files, find the program file you need.
-
Copy it into the chroot jail and run the
lddprocess as previously.
Acknowledgements
I looked at far too many pages trying to work out how to set up just the chrooted environment that I neeeded. However the following were particualrly useful: