Linux chrooting guide
short explanation of chroots:
a chroot is a "box within a box", meaning, if you have a program, a process
or maybe even a user, which should have only access to a certain part of the
system, you could either do that by patching the programm, so it can only
access a certain part of the system, thats the hard way. now we do have a weapon called chroot, that makes it possible to have that possibility without the need to rewrite parts of the program. a very popular example for a chrooted daemon would be bind, what do we need for that to work:
first thing were going to do is creating a user which bind is going to run under:
adduser named
then we open the /etc/passwd file, and edit the line for the user:
named:x:200:200:Nameserver:/chroot/named:/bin/false
the most important entries here are the :x:, the :/chroot/named and the :/bin/false.
what does this do?
:x: tells us, that we are using a shadow for passwords, this should be already understood before you even think about setting up a chroot;)
the second important part tells, where we want our bind to reside, as the example implies, this is where the game is going to be played.
the third part tells us, that the user bind wont be able to login like a normal user, cause he wont get a shell.
next we have to create a group for our new user:
addgroup named
this will create an entry in /etc/group which looks like this one:
named:x:200:
next thing we need to set is the directory structure for our bind chroot, a typical chroot for bind looks like the following:
/chroot
+-- named
+-- dev
+-- etc
| +-- namedb
| +-- slave
+-- var
+-- run
next thing, install the bind provided with your linux distribution, for debian:
apt-get -f install bind
then we are going to place our things into the chroot:
cp -p /etc/bind/named.conf /chroot/named/etc/
cp -a /var/bind/* /chroot/named/etc/namedb/
rm /var/named/etc/namedb/named.conf
(and yes, i know, there better ways, but this was a short to explain).
next we are gonna set a few permission things:
first we need to allow bind to access its config informations:
chown -R named:named /chroot/named/etc
then we need to make sure that the daemon is able to access its temp file:
chown named:named /chroot/named/var/run
ok, like most programs that are running on linux, bind needs to access a few basic devices, so lets make them within the chroot:
mknod /chroot/named/dev/null c 1 3
mknod /chroot/named/dev/random c 1 8
chmod 666 /chroot/named/dev/{null,random}
to get right timings on zonefiles, youll need one more file within the chroot:
cp /etc/localtime /chroot/named/etc/
now, since we dont want to loose our holy bind logs, were gonna tweak
the /etc/init.d/sysklogd script a lil bit:
just change the entry
SYSLOGD="" into SYSLOGD="-m 0 -a /chroot/named/dev/log".
now just restart sysklogd and the base things are done.
next we will need to take care of the access permissions on the chroot, so that no other user can access it at all:
"security is a two sided sword."
chown root /chroot
chmod 700 /chroot
chown named:named /chroot/named
chmod 700 /chroot/named
now lets have a look at the init.d script, this is a modified version
targetting our new needs:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
# for a chrooted server: "-u bind -t /var/lib/named"
# Dont modify this line, change or create /etc/default/bind9.
OPTIONS="-u bind -t /chroot/named"
test -f /etc/default/bind9 && . /etc/default/bind9
test -x /usr/sbin/rndc || exit 0
case "$1" in
start)
echo -n "Starting domain name service: named"
modprobe capability >/dev/null 2>&1 || true
# dirs under /var/run can go away on reboots.
mkdir -p /var/run/bind/run
chmod 775 /var/run/bind/run
chown root:named /var/run/bind/run >/chroot/dev/null 2>&1 || true
if [ ! -x /usr/sbin/named ]; then
echo "named binary missing - not starting"
exit 1
fi
if start-stop-daemon --start --quiet --exec /usr/sbin/named
--pidfile /var/run/bind/run/named.pid -- $OPTIONS; then
if [ -x /sbin/resolvconf ] ; then
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo
fi
fi
echo "."
;;
stop)
echo -n "Stopping domain name service: named"
if [ -x /sbin/resolvconf ]; then
/sbin/resolvconf -d lo
fi
/usr/sbin/rndc stop
echo "."
;;
reload)
/usr/sbin/rndc reload
;;
restart|force-reload)
$0 stop
sleep 2
$0 start
;;
*)
echo "Usage: /etc/init.d/bind {start|stop|reload|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
easy, eh;)
next we will need to change a few things in the bind configuration "directory","pid-file", "statistics-file".
erm, but why dont set /chroot in front of the things?
simple answer, since bind wont see the dirs outside the chroot, itll "think"
that this chroot dir is his root "/".
now just restart your bind, and have some phun with this lil hack.
ps: this howto is loosely based on the chroot-bind howto, which can be found (for example) here:
http://www.losurs.org/docs/howto/Chroot-BIND-4.html
second part, make a user chroot jail, the easy (debian) way:
the idea behind this is pretty much the same as with bind, but our
target now is bash.
we just start off with creating our subsystem:
apt-get -f install debootstrap
debootstrap woody /debian
this will create a debian woody base install under /debian.
next step, to get all network names resolved the right way, we need
to copy the existing resolv.conf to the newly created system:
cp /etc/resolv.conf /debian/etc/resolv.conf
next step would be the admin "sneak" on your new subsys:
chroot /debian su -
before youre going to do anything else, give linux its access
to the process informations on the sys:
mount -t proc none /proc
now you may want to do the base configurations on the subsys:
base-config
want to run a program from within the chroot at the startup?
add this line to your /etc/init.d/bootmisc.sh
chroot /debian su -c /etc/init.d/startup-chroot -
just customize the script you wanna call...
now the more tricky part, setting up the user homes:
first thing we want to use is a wrapper, which "forwards" the user
to the chrooted bash in case of his login, either you write one
by yourself, or use an existing one, a very good example for such a wrapper is
http://www.weidner.ch/download/chrlogin.c
now for the base idea...
open /etc/shells and insert a new line into it:
/usr/local/sbin/chrlogin
now do the obvious adduser:
adduser parisc
then open /etc/password, and change the new users line:
parisc:x:1000:1000:pour RiSC:/debian/home/parisc:/usr/local/sbin/chrlogin
the uid and gid doesnt need to be changed in this case, you get the idea...
next we chroot into our chrootjail again as root type:
chroot /debian
there we add the same user as above:
adduser parisc
and edit the /etc/password within the chroot to show the following:
parisc:x:1000:1000:pour RiSC jailed:/home/parisc:/bin/bash
this time we have especially to take care about the uid and gid, they need to be the same as outside of the jail.
then we are going to edit the chrootshell.c file, and change the following
lines to fit our needs:
first of all, which shell should our users get by default:
#define SHELL "/bin/bash"
next we have to tell the chrlogin wrapper where to find the users homes:
#define CHROOT_LEVEL 2
more information about the options can be found in the c source of the file.
finally we need to compile the file, move it into the place, and
set the right permissions on it:
gcc -Wall -O2 -s chrlogin.c -o chrlogin
cp chrlogin /usr/local/sbin (create the dir, if it doesnt exist)
chown root /usr/local/sbin/chrlogin
chmod 4755 /usr/local/sbin/chrlogin
an absolute must, in case you dont want mr. evil hacker to leave his chrootjail via a race condition or exploit for example, you have to remove all suidbits from files within the chroot environment, to find out which files do have the suid bit set on your /debian dir, run the following command:
find /debian -type f ( -perm -04000 -o -perm -02000 ) -exec ls -lg {} ;
with a chmod -s filename you may remove the suidbit, and dont worry, those arent needed to run the typical programs i could think of.
if youre really paranoid like me, you might want to take a look at the linux grsec kernel patch, which can be found on
http://www.grsecurity.net
this is it, i hope you enjoyed it as i did, stay tuned for even more fine system tricks.