Creating a basic padded cell

Unix Insider –

As regular readers of Unix Insider probably know, Peter Galvin has abdicated as Unix Insider's security czar to start a new system administration column for this magazine. Following Peter's lead, this column will continue to provide practical, technical information about computer security based on real-world experiences.

I'm currently working as an independent security consultant in the New York financial market. This gives me the opportunity to design and implement solutions in different environments in parallel. Because every environment is unique, it's possible that something that worked out great for me will be totally wrong for you. There's no single solution or product that is optimal for all people at all times. My goal is to provide the gory technical details of problems encountered and solutions that have worked in most environments.

As has been discussed numerous times, most security problems are the result of human negligence. If more programmers followed the advice set forth in Peter's April 1998 column, there wouldn't be as much to write about here. I've worked with developers who refuse to even follow basic source code control such as SCCS. Unfortunately, system administrators often have no control over the development environment and are unable to impose proper development procedures.

What the administrator can do is to consider the application suspect and place it in a padded cell using chroot.

I cowrote with Peter the May and June 1998 Security columns, which described the installation of a Web server in a padded cell environment that my partner, Jonathan Klein, and I installed at a client site. I was rather surprised at all the feedback complaining that padded cells are too difficult to set up correctly. While it's true that there's a lot of technical detail involved in creating a padded cell, and while it certainly isn't a procedure for novices, it is worthwhile to learn since it's a proven procedure that has been used for years. To help make the learning process easier, this column includes scripts written by Jonathan to create a basic padded cell.

Creating a basic padded cell

A padded cell is a unique environment specifically tailored for an application. As such, these scripts probably won't work for your particular application -- you'll need to edit the sample list files. We've used these to configure the Netscape server, Sendmail, FTP, and list servers, and we edit the list files each time.

Sample padded cell scripts

The following shell scripts can be used (with modification) to create a basic padded cell:

The shell scripts use the following ASCII input files:

There's also a C program to create the proper device permissions:

You can click on the links above to see the scripts; I'll also provide quick explanations of them below.

make_cell

This is a top-level master script that calls and runs all the other scripts.

mkdir_cell

This script creates the directory structure needed to simulate a mini-Unix operating environment. It creates directories such as /etc, /usr, /lib, /usr/lib, and so on. The script decides which directories to create based on the input file, dirlist. The file provided here is an example only and needs to be edited for your particular application.

mksymdir_cell

This script makes all the required symbolic links for directories. For example, it will create the symbolic link from $root/bin to $root/usr/bin. The input file for this script is symdirlist.

mkdev_cell

This script creates the devices in the cell directory that will be required by the application. It also creates the symbolic links as required. The input file for this script is devlist. Be very careful to edit this file and include only the devices you will need. Remember, the devices listed are only a guide. This script also uses a C program, mkperm.c, to set the correct permissions for the devices.

cpfile_cell

This script copies into the cell the system files you will need to run the application. The input file is filelist.

Important note! Some of the files that are copied in must be modified to remove information you don't want public, such as the root password.

Files that must be modified include:

  • passwd and shadow: These files need to be in the cell so the application will work. However, they need to be stripped of all the user data that isn't needed in the cell. Although the root account should be in the cell's passwd and shadow files, the password data is meaningless and must not be valid. The real root account works outside the cell.
  • hosts and services: Again, just put in here what you need in the cell, although a cracker could easily find out what services you are running by running portscan.

Additional files, such as nsswitch.conf and inetd.conf,

may need to be modified.

mksymfile_cell

This script creates all the file symbolic links that are required such as the lib.so files. The input file is symfilelist.

Using the scripts

It is highly recommended that you run this on a test system first if you are unfamiliar with chroot. If you are installing a padded cell for production use, you should have it reside on a dedicated filesystem. For testing and/or learning purposes, you can just make a directory in a filesystem with sufficient space.

Copy the scripts into /usr/local/bin. In this directory, make a directory called lists and copy in the five list files (dirlist, symdirlist, devlist, filelist and symfilelist). Edit the list files accordingly. To find out which libraries the application needs, run ldd on the application. For example:

<font face="Courier">
# ldd /usr/lib/sendmail
        libresolv.so.2 =>        /usr/lib/libresolv.so.2
        libsocket.so.1 =>        /usr/lib/libsocket.so.1
        libnsl.so.1 =>   /usr/lib/libnsl.so.1
        libkstat.so.1 =>         /usr/lib/libkstat.so.1
        libc.so.1 =>     /usr/lib/libc.so.1
        libdl.so.1 =>    /usr/lib/libdl.so.1
        libdl.so.1 (SUNW_0.7) =>         (version not found)
        libdl.so.1 (SISCD_2.3) =>        (version not found)
        libintl.so.1 =>  /usr/lib/libintl.so.1
        libmp.so.1 =>    /usr/lib/libmp.so.1
        libdl.so.1 (SUNW_0.7) =>         (version not found)
        libdl.so.1 (SUNWprivate_1.1) =>  (version not found)
        libdl.so.1 (SISCD_2.3) =>        (version not found)
        libw.so.1 =>     /usr/lib/libw.so.1
#
</font>

If you're creating a production cell, make a filesystem just for the cell (e.g., /usr/local/cell) and mount it as /usr/local/cell (or whatever). If you're just using this for testing or learning purposes, it isn't necessary to make a separate filesystem. For test purposes, I'm using a directory, /tmp/cell_test as an example.

<font face="Courier">
# /usr/local/bin/make_cell  /usr/local/bin/lists  /tmp/cell_test
Make Directory Entries
Make Directory Symbolic Links
Make Device Entries
Copying Files
Make File Symbolic Links
Padded Cell creation complete
#

# ls -lR /tmp/cell_test 
</font>

(Click here if you want to see the output of

<font face="Courier">ls -l</font>
in the example above.)

Don't forget to clean up /etc/passwd and /etc/shadow! Also check all the other system files that were copied in. In this case, I copied in /bin/sh to use as an example. If you don't need it in the cell, remove it.

Here's a basic example of how the cell works:

<font face="Courier">
# pwd
/usr/local/bin
# /usr/sbin/chroot  /tmp/cell_test  /bin/sh
# pwd
/
# cd /usr/bin
# ./ls
./ls: not found
# /usr/bin/ls
/usr/bin/ls: not found
[control-D]
# pwd
/usr/local/bin
</font>

Because I didn't copy /usr/bin/ls into the cell, it isn't found when I run /bin/sh under chroot.

Copy the application binaries into the cell. For an application that needs to be built, run the build outside the cell because it will require system resources for the build that aren't necessary to run the application. When you copy the binaries in, remember that you are considering the directory /tmp/cell_test to be root (/). For example, Sendmail would be copied in to /tmp/cell_test/usr/lib/sendmail. Make sure the appropriate permissions are set.

<font face="Courier">
# cp -p /usr/lib/sendmail  tmp/cell_test/usr/lib
# ls -l  /tmp/cell_test/usr/lib/sendmail
r-sr-x--x   1 root     bin       378264 Dec  6 15:09 /tmp/cell_test/usr/lib/sendmail
</font>

Test to make sure the application works in the cell:

<font face="Courier">
# /usr/sbin/chroot  /tmp/cell_test  /usr/lib/sendmail  -bt
ld.so.1: /usr/lib/sendmail: fatal: libresolv.so.2: open failed: No such file or
directory
Killed
</font>

Sometimes the errors are pretty obvious, as in the example above. For the more obscure errors, use truss as follows:

<font face="Courier">
 mount /proc as a loopback filesystem for debugging purposes:
# mkdir /tmp/cell_test/proc
# mount -F lofs /proc  /tmp/cell_test/proc
# cp  /usr/bin/truss  /tmp/cell_test/usr/bin/truss
	# /usr/sbin/chroot  /tmp/cell_test /usr/bin/truss  /usr/lib/sendmail 2>& 1 | tee>/tmp/out
	# more  /tmp/out

execve("/usr/lib/sendmail", 0xEFFFFE28, 0xEFFFFE30)  argc = 1
open("/dev/zero", O_RDONLY)                     = 3
mmap(0x00000000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, 
MAP_PRIVATE, 3, 0) = 0xEF
7C0000
open("/usr/lib/libresolv.so.2", O_RDONLY)       Err#2 ENOENT
ld.so.1: /usr/lib/sendmail: fatal: libresolv.so.2: open failed: No such file or
directory
write(2, " l d . s o . 1 :   / u s".., 90)      = 90
getpid()                                        = 23561 [23559]
        *** process killed *** +
</font>

In this case, I'm missing libresolv.so.2. (Actually, I removed it to generate the error.) Using truss can be rather painful, but it's very helpful in identifying missing devices.

Once you get all the libraries and devices the application needs in the cell, test it again to see what else it may need:

<font face="Courier">
	# /usr/sbin/chroot /tmp/cell_test /usr/lib/sendmail -bt

/etc/sendmail.cf: line 59: fileclass: cannot open /etc/mail/sendmail.cw: No such
 file or directory
dbm map "Alias0": missing map file /etc/mail/aliases: No such file or directory
WARNING: cannot open alias database /etc/mail/aliases; reading text version
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
>[control-D]
</font>

The cell is missing some files that Sendmail needs, such as /etc/mail/aliases and /etc/sendmail.cw. (I previously copied in a basic /etc/sendmail.cf file.) As always, check any file you copy into the cell to make sure it's something you want public. After you have the required files for the application, try it again:

<font face="Courier">
# /usr/sbin/chroot /tmp/cell_test /usr/lib/sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> 3,0,4 fennelly@wkeys.com
rewrite: ruleset   3   input: fennelly @ wkeys . com
rewrite: ruleset  96   input: fennelly < @ wkeys . com >
rewrite: ruleset  96 returns: fennelly < @ wkeys . com . >
rewrite: ruleset   3 returns: fennelly < @ wkeys . com . >
rewrite: ruleset   0   input: fennelly < @ wkeys . com . >
rewrite: ruleset 199   input: fennelly < @ wkeys . com . >
rewrite: ruleset 199 returns: fennelly < @ wkeys . com . >
rewrite: ruleset  98   input: fennelly < @ wkeys . com . >
rewrite: ruleset  98 returns: $# local $: fennelly
rewrite: ruleset   0 returns: $# local $: fennelly
rewrite: ruleset   4   input: $# local $: fennelly
rewrite: ruleset   4 returns: $# local $: fennelly
> 3,0,4 user@unixinsider.com
rewrite: ruleset   3   input: user @ unixinsider . com
rewrite: ruleset  96   input: user < @ unixinsider . com >
rewrite: ruleset  96 returns: user < @ unixinsider . com . >
rewrite: ruleset   3 returns: user < @ unixinsider . com . >
rewrite: ruleset   0   input: user < @ unixinsider . com . >
rewrite: ruleset 199   input: user < @ unixinsider . com . >
rewrite: ruleset 199 returns: user < @ unixinsider . com . >
rewrite: ruleset  98   input: user < @ unixinsider . com . >
rewrite: ruleset  98 returns: $# smtp $@ firebox $: user < @ unixinsider . com . >
rewrite: ruleset   0 returns: $# smtp $@ firebox $: user < @ unixinsider . com . >
rewrite: ruleset   4   input: $# smtp $@ firebox $: user < @ unixinsider . com . >
rewrite: ruleset   4 returns: $# smtp $@ firebox $: user < @ unixinsider . com . >
>
</font>

At this point, it looks like my application is working and I can proceed with production testing. When the application is considered ready for production, the system startup files can be modified to start the application in the padded cell, as in a modified version of /etc/init.d/sendmail to start Sendmail in the padded cell. The modified startup of Sendmail could look something like this:

<font face="Courier">
	PADDED_CELL=/usr/local/cell
	/usr/sbin/chroot ${PADDED_CELL} /usr/lib/sendmail -bd -q15m
</font>

Conclusion

1 2 3 Page
Insider: How the basic tech behind the Internet works
Join the discussion
Be the first to comment on this article. Our Commenting Policies