Skip to content

rmdir/prison

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mod_prison : is an Apache httpd module that attempt to put httpd
children in a very restrictive context :

- chroot with no need of shared libs
- network restrictions
- system calls restrictions
- CPU stickiness and limitation
- Memory usage limit

Unlike mod_unixd restrictions (ChrootDir, RLimit), mod_prison create
a global restricted context and attach each child in it.

Currently mod_prison is a FreeBSD only stuff using jail, rctl and
cpuset.

DEPENDENCIES

- FreeBSD version that supports libjail (> 7.2).
check ldconfig -r | grep jail

- rctl compiled into the kernel
options RACCT
options RCTL

- Apache httpd-2.4 compiled with dso support (2.2 may work
but is untested).

INSTALL

Simply uses the Makefile : make && make install

You can specify apxs path when building :
make APXS=/usr/local/httpd/bin/apxs

By default PARANOID is set. You can remove it by editing the Makefile

USAGE

1) PrisonDir : the directory we will be jailed on

DocumentRoot must be relative to this path so you must use httpd -T
to start Apache. If PARANOID is set at compile time, PrisonDir must
be owned by root and not be world or group writable.

Eg:
PrisonDir /usr/local/www
DocumentRoot /sites

2) PrisonIP : A single ipv4 or ipv6 string representation (default none).

Apache still bind everything specified in Listen. PrisonIP is just used for
script stuff like database connections, dns lookup...
If PARANOID is set you can't use INADDR_ANY (0.0.0.0).

Eg:
PrisonIP 192.168.0.1
PrisonIP ::1

3) PrisonSecurity : None|ALL|IPC

NONE : security settings are inherit from the system.

ALL : restrict system calls

The idea is to restrict systems operations even if the attacker gains root
privileges.

- disallow SysV IPC.
- disallow row devices access (/dev/io, /dev/mem, /dev/kmem, newfs).
- disallow loding modules into the kernel.
- reduce the possibility to have information about mount-points.
- disallow row sockets
- disallow changing IP filter rules
- disallow chflags
- disallow mount and quota management
- limit socket creation to IPv4, IPv6 and unix

IPC : like ALL but SysV IPC are allowed. 

The default is NONE (ALL if PARANOID is set).

4) PrisonCPU : the CPU in which children will be execute.

- a single cpu. Eg:
PrisonCPU 1
- a list of cpu. Eg:
PrisonCPU 1,2,6
- a cpu range. Eg
PrisonCPU 8-10 # means 8,9 and 10

5) PrisonMemory : total of memory usable within the jail.

Args are : report deny
Eg:
PrisonMemory 900M 1G

This means that when the total of all children memory usage will be of
900MB an event will be reported (via devd on FreeBSD). When this total
is 1GB further usage will be denied.

Warning : usage is not allocation (look at the difference between SIZE
and RES in a top command). This rule apply to the effective memory use.
Allocation should be larger.

Zero means infinite. Eg:
PrisonMemory 512k 0 # Report at 512k. Never deny.

On FreeBSD vm.overcommit has to be set to 1, otherwise the processes will
be pushed in swap by deny.

6) PrisonOptions : various options.
Currently OneSite and OneListen are implemented. OneSite deny VirtualHosts 
in configuration. OneListen deny multiple listen statements.

It's useful if you want your users to access quite whole config but not to change
Listen statement or add some vhosts.

SeverName plop.rmdir.fr
Listen 127.0.0.1:8080
#mpm config ...
DocumentRoot /html
PrisonPath /home/user/
PrisonOptions OneSite OneListen

# A listen or virtualhost in this file 
# will makes configtest to fail

Include /home/user/conf/apache.conf



EXAMPLES

# httpd.conf
PrisonDir /usr/local/www/plop
DocumentRoot /htdocs
ServerName plop.rmdir.fr
Listen *:8088
PrisonIP ::1
PrisonCPU 1
PrisonSecurity IPC
PrisonMemory 200M 256M


# Starting apache 
$ sudo httpd -k start -T 

# We now have a jail
$ sudo  jls jid name host.hostname ip4.addr ip6.addr path
65 plop_rmdir_fr plop.rmdir.fr - ::1 /usr/local/www/plop


# We now have our processes jailed
$ pgrep -j 65
61100
61086
61085
61084
61083
61082

# Listening on port 8088
$ sockstat -j 65
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS      
joris    httpd      61100 3  tcp4 6 *:8088                *:*
joris    httpd      61100 4  tcp4   *:*                   *:*
joris    httpd      61086 3  tcp4 6 *:8088                *:*
joris    httpd      61086 4  tcp4   *:*                   *:*
joris    httpd      61085 3  tcp4 6 *:8088                *:*
joris    httpd      61085 4  tcp4   *:*                   *:*
joris    httpd      61084 3  tcp4 6 *:8088                *:*
joris    httpd      61084 4  tcp4   *:*                   *:*
joris    httpd      61083 3  tcp4 6 *:8088                *:*
joris    httpd      61083 4  tcp4   *:*                   *:*
joris    httpd      61082 3  tcp4 6 *:8088                *:*
joris    httpd      61082 4  tcp4   *:*                   *:*

# Our cpuset
$ cpuset -g -j 65
jail 65 mask: 1

# Our rctl rules
# rctl -l process:61100
$ sudo rctl -l process:61100
jail:plop_rmdir_fr:memoryuse:deny=104857600
jail:plop_rmdir_fr:memoryuse:devctl=52428800

# Our sysctls set
$ curl -i http://www.rmdir.fr:8088/sysctl.cgi
HTTP/1.1 200 OK
Date: Wed, 10 Oct 2012 16:24:38 GMT
Server: Apache/2.4.3 (Unix)
Transfer-Encoding: chunked
Content-Type: text/plain

security.jail.jailed: 1
security.jail.set_hostname_allowed: 0
security.jail.socket_unixiproute_only: 1
security.jail.sysvipc_allowed: 1
security.jail.allow_raw_sockets: 0
security.jail.chflags_allowed: 0
security.jail.mount_allowed: 0
security.jail.mount_devfs_allowed: 0
security.jail.mount_nullfs_allowed: 0
security.jail.mount_procfs_allowed: 0
security.jail.mount_zfs_allowed: 0
security.jail.enforce_statfs: 2
kern.securelevel: 3

# We only see the root mountpoint of the jail

$ mount | grep plop
tank/plop on /usr/local/www/plop (zfs, local, nfsv4acls)
tmpfs on /usr/local/www/plop/tmp (tmpfs, local)
$ curl http://www.rmdir.fr:8088/mount.cgi
tank/plop on / (zfs, local, nfsv4acls)

SYSTEM DATABASES 

With a basic NSS configuration, name resolution will work if there is a 
route between PrisonIP and the resolver (take a particular care when 
setting loopback IPs). /etc/hosts will no work. No resolv.conf is needed 
inside the prison. As other system databases lookup, it will fail even 
if the relevant file is accessible within the prison.

$ curl http://www.rmdir.fr:8088/id.cgi
uid=1001 gid=1001 groups=1001
$ sudo mkdir /usr/local /usr/local/www/plop/etc
$ sudo cp /etc/passwd /usr/local/www/plop/etc/
$ curl http://www.rmdir.fr:8088/id.cgi
uid=1001 gid=1001 groups=1001

NETWORK

Child process will access incomming requests and apache IPC. 
They also will access what is routable through PrisonIP.

BUGS AND STATUS

This is work in progress. 

- What about ChrootDirectory.

IMPLEMENTATION NOTE

The main problem in implementation is that jail is a kernel context which
has to be persistent before there is any process in it but not persistent 
if you want it to die at the same time as httpd.

Currently everything is set in post_config
- create or update the jail
- fork a process that waits a few time before setting it non persistent.

It sounds like a hack, but I really hesitate to make things much more complicate
with some IPC. The current implementation has around no overhead and is really 
simple to understand.

SEE ALSO

mod-jail : http://code.google.com/p/mod-jail/
	 

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages