Monthly Columns
 

Safe and friendly read-only chroot jails for FTP and WWW

Copyright © 1999 Ruffy von Wunderhund

FTP and WWW services are often the only legitimate public services exported by most security-conscious sites, so why don't they take measures to secure them? It seems to me that the BSD operating system provides us with many interesting system facilities to abuse in the name of security.

In this article, we examine the abuse of two such BSD Unix features (the ever-popular chroot() system call, and the proof-of-concept, namespace-mangling mount_null loopback filesystem) for the sake of security AND convenience.

Read-only, chroot'd FTP/WWW services are a good way to offer public information services with limited risk. Unfortunately, such setups are also of limited use (hard to update and maintain content), since changes to the read-only filesystem are usually a major PITA.

However, thanks to the stackable VFS magic of BSD's mount_null(), we can have the best of both worlds - chroot'd, read-only public access, and open, read-write local modification. Here's how we do it:

1. Find FTP and WWW daemons that either support a chroot'd setup, or are easily hacked to do so. For ease, we'll go with the first option - OpenBSD's ftpd, and Acme Laboratories' thttpd:

http://www.openbsd.org/
http://www.acme.com/software/thttpd/

Otherwise, you'll have to modify your servers to open log files before they chroot(), and figure out what other dependencies they may have on writable files or directories.

2. Create a chroot area for these daemons, for example, /usr/jail/ftp and /usr/jail/www. The OpenBSD ftpd(8) manpage details a chroot'd anonymous FTP setup very nicely.

3. Create a mountpoint for the read-only image of this chroot area, the one in which your daemons will be jailed. Add a line to your /etc/fstab to do the null mount automatically at boot:

/usr/jail /jail null ro,nosuid 0 0

4. Make sure the 'ftp' and 'www' users your daemons will run as own NO files on the system, and that their home directories are the read-only path to the chroot area (e.g. ~ftp == /jail/ftp and ~www == /jail/www).

5. Set up your FTP and WWW configuration files to point to the read-only chroot area.

That's it. Start up your daemons, and start adding content to the read-write version of the chroot area (/usr/jail). Updates to the read-write /usr/jail tree will be immediately visible in the read-only /jail tree (thttpd has an mmap cache for static files, though, so those won't propagate as expected). You might want to set up user ~/public_ftp and ~/public_html symlinks to point to the appropriate /usr/jail directories as well.

Those with AFS experience might recognize this as a lame hack to implement read-only volumes.

Next time: leaking file descriptors thru BSD portals for fun and profit.

Ruffy von Wunderhund, ruffy@dawghaus.org