How to Create Jailed Users?

6,764

Ok, you're using kind of a weird setup, but just in general:

First off, linux doesn't support true (bsd style) jails (unless you install openvz or vserver), but setting everything to run as a non priviledged user + chroots can very seriously improve security. Running things as a non-root user is essential, chroots are just an (arguably sizable) stumbling block for would-be attackers).

According to the php-fpm site, chrooting is supported via a configuration command. Of course, php-fpm has like, no documentation... If you poke through the source tarball you might find some documentation, or at least an example config. http://php-fpm.org/about/ says that setting the user, group, and chroot are possible. I've never used php-fpm, but it should be fairly commonsense.

To get nginx running as a non-root user, open the nginx configuration file, find the line that starts with "user" and change it to a non privileged user on the system. Create a new user with nologin as a shell or use the nobody user.

Then the process to chroot any daemon is basically as follows:

  • Create a directory for the specific daemon's root
  • Create a skeleton directory structure in the chroot directory (so ./etc, ./usr/lib, etc)
  • Copy over any needed binaries and configuration files (so the nginx.conf, the nginx binary, any helper programs that you'll need)
  • Copy over additional files that are needed inside the chroot. This will be at least a stub of /etc/password file (not the shadow password file, there simply needs to be a way of looking up usernames to uids), /etc/group file, and /etc/localtime (php will complain endlessly if you don't have timezone info).
  • Lastly, run ldd on the binaries that you've copied over. This will give you a list of libraries to copy. Go through this list, and copy the needed shared objects to their equivalent place in the chrooted directory. Try to preserve symlinks, or copy the original file in the place where there was previously a symlink.
  • Create any needed devices with mknod. If you don't know the device numbers, google them (ex: /dev/random is c 1 8, /dev/null is c 2 2)
  • While the paths to things in your config files should stay the same, occasionally they need tweaking. When you are manually chrooting a daemon, everything in the config file should IGNORE the part of the path that will not be visible once you're chrooted, for example /var/log/somelogfile will remain /var/log/somelogfile despite it's new path actually being /chroot/nginx/var/log/somelogfile

Keep in mind that any daemon which can be chrooted via the configuration file will not require this set of steps - the chrooting will be done by the program after the relevant library dependencies and configuration files have been loaded. Which makes life much simpler.

Once you've done this, in theory you should be ready to run nginx (or anything else) chrooted. In your /etc/init.d/ script for nginx, find where the nginx binary is actually run, and change it to use chroot, for example:

$DAEMON -c $CONFIGFILE

becomes

/usr/sbin/chroot /chroot/directory/here $DAEMON -c $CONFIGFILE

Then you can start nginx normally with your init.d script. *If you get an error from chroot like "chroot: cannot run command `/bin/that/actually/exists': No such file or directory" then you're missing some libraries, or something else essential. Anything that causes the binary to fail to run at all will result in that error (actually, one centos box of mine says Operation not permitted instead).

Since I don't have high enough of rep points to post a lot of links, check out www (dot) securityfocus (dot) com (slash) infocus/1694 (securing apache step by step) - it's a different http daemon, it's the same basic steps, at least as far as chrooting goes.

Also keep in mind that your file permissions in the chroot folder need to be attended to - basically as long as the user that nginx runs as can read/deal with your files in the chroot, everything will be fine.

Lastly, as an example of what type things are required in a chroot environment, here's a random list of files from an openwall box that's running a number of things chrooted. I'm using mysql as an example:

localhost!root:/# find /chroot/mysql 
/chroot/mysql
/chroot/mysql/var
/chroot/mysql/var/run
/chroot/mysql/var/run/mysql.sock
/chroot/mysql/var/run/mysqld.pid
/chroot/mysql/var/log
/chroot/mysql/etc
/chroot/mysql/etc/my.cnf
/chroot/mysql/etc/hosts
/chroot/mysql/etc/host.conf
/chroot/mysql/etc/resolv.conf
/chroot/mysql/etc/group
/chroot/mysql/etc/passwd
/chroot/mysql/etc/my.cnf.orig
/chroot/mysql/etc/nsswitch.conf
/chroot/mysql/tmp
/chroot/mysql/lib
/chroot/mysql/lib/libtermcap.so.2
/chroot/mysql/lib/libdl.so.2
/chroot/mysql/lib/libc.so.6
/chroot/mysql/lib/librt.so.1
/chroot/mysql/lib/libpthread.so.0
/chroot/mysql/lib/libz.so.1
/chroot/mysql/lib/libcrypt.so.1
/chroot/mysql/lib/libnsl.so.1
/chroot/mysql/lib/libstdc++.so.6
/chroot/mysql/lib/libm.so.6
/chroot/mysql/lib/libgcc_s.so.1
/chroot/mysql/lib/ld-linux.so.2
/chroot/mysql/lib/libnss_compat.so.2
/chroot/mysql/lib/libnss_files.so.2
/chroot/mysql/lib/libnss_compat-2.3.6.so
/chroot/mysql/lib/libnss_files-2.3.6.so
/chroot/mysql/data
/chroot/mysql/data/mysql
/chroot/mysql/data/mysql/db.frm
/chroot/mysql/data/mysql/db.MYI
/chroot/mysql/data/mysql/db.MYD
[further mysql tables have been omitted]
/chroot/mysql/dev
/chroot/mysql/dev/null
/chroot/mysql/usr
/chroot/mysql/usr/local
/chroot/mysql/usr/local/libexec
/chroot/mysql/usr/local/libexec/mysqld
/chroot/mysql/usr/local/charsets
/chroot/mysql/usr/local/charsets/README
/chroot/mysql/usr/local/charsets/Index.xml
/chroot/mysql/usr/local/charsets/armscii8.xml
/chroot/mysql/usr/local/charsets/ascii.xml
/chroot/mysql/usr/local/charsets/cp1250.xml
/chroot/mysql/usr/local/charsets/cp1251.xml
/chroot/mysql/usr/local/charsets/cp1256.xml
/chroot/mysql/usr/local/charsets/cp1257.xml
/chroot/mysql/usr/local/charsets/cp850.xml
/chroot/mysql/usr/local/charsets/cp852.xml
/chroot/mysql/usr/local/charsets/cp866.xml
/chroot/mysql/usr/local/charsets/dec8.xml
/chroot/mysql/usr/local/charsets/geostd8.xml
/chroot/mysql/usr/local/charsets/greek.xml
/chroot/mysql/usr/local/charsets/hebrew.xml
/chroot/mysql/usr/local/charsets/hp8.xml
/chroot/mysql/usr/local/charsets/keybcs2.xml
/chroot/mysql/usr/local/charsets/koi8r.xml
/chroot/mysql/usr/local/charsets/koi8u.xml
/chroot/mysql/usr/local/charsets/latin1.xml
/chroot/mysql/usr/local/charsets/latin2.xml
/chroot/mysql/usr/local/charsets/latin5.xml
/chroot/mysql/usr/local/charsets/latin7.xml
/chroot/mysql/usr/local/charsets/macce.xml
/chroot/mysql/usr/local/charsets/macroman.xml
/chroot/mysql/usr/local/charsets/swe7.xml
/chroot/mysql/usr/local/share
/chroot/mysql/usr/local/share/mysql
/chroot/mysql/usr/local/share/mysql/english
/chroot/mysql/usr/local/share/mysql/english/errmsg.sys
/chroot/mysql/bin
/chroot/mysql/bin/test
/chroot/mysql/bin/nohup

An example of the setup for a daemon that can be chrooted via it's configuration file is maradns:

localhost!root:/# find /chroot/maradns/
/chroot/maradns/
/chroot/maradns/logger
/chroot/maradns/db.[removed]
/chroot/maradns/db.[removed2]
/chroot/maradns/db.[removed3]

As you can see, maradns did not require much to get it chrooted (actually it just required "chroot_dir = "/chroot/maradns" in the /etc/mararc file.

Anyway, this has been a long and extremely rambling post aimed towards software slightly different from that which you are using, however I hope this information is still useful.

Share:
6,764

Related videos on Youtube

Miko
Author by

Miko

Updated on September 17, 2022

Comments

  • Miko
    Miko almost 2 years

    My servers run CentOS: Nginx + PHP-FPM (PHP via Fast-CGI). Every site is on its own VirtualHost.

    Currently both Nginx and PHP-FPM run under root. I know this is bad practice, and there is no reason for any of the sites to have access to files outside of their own directory.

    How would I go about creating jailed users and instructing nginx && php-fpm to play along accordingly?