Los sistemas tipo BSD disponen de chroot desde la época de 4.2BSD. chroot permite restringir el directorio raÃz de un conjunto de procesos creando un entorno seguro y separado del resto del sistema, es una buena herramienta para tareas sencillas que no requieran mucha flexibilidad, caracterÃsticas complejas o muy avanzadas. Por desgracia, desde su invención se han ido encontrando formas de saltarse las barreras que impone, es evidente que chroot no es la solución ideal para ejecutar servicios con seguridad. Este es uno de los principales motivos por los que se crearon las jaulas.
Jails es una herramienta muy potente pero no es la panacea en cuanto a seguridad, existen varias maneras de conseguir root en el jail si cooperan un usuario no privilegiado en el servidor de virtualización y un usuario root en el jail. La mayorÃa de estos ataques pueden ser mitigados asegurándose de que el root filesystem del jail no sea accesible por usuarios no privilegiados dentro del servidor de virtualización.
Un jail se puede montar de dos modos distintos:
- Virtual system: Sistema operativo completo.
- Service: Se arranca un proceso dentro del chroot. Si el jail es un servicio el parámetro exec.start debe ser modificado.
El jail se puede montar tanto desde paquetes binarios como desde las fuentes, en este manual optaremos por los paquetes binarios en favor de una mayor celeridad.
Definimos donde vamos a montar nuestro jail:
export DESTDIR=/var/jail/www
Ahora tenemos dos posibilidades, extraer solo el sistema base:
tar -xf base.txz -C $DESTDIR
O extraer el sistema completo, base y ports:
tar -xf base.txz -C $DESTDIR
fetch http://ftp.freebsd.org/pub/FreeBSD/snapshots/amd64/12.0-STABLE/ports.txz
tar -xf ports.txz -C $DESTDIR
Indicamos que queremos arrancar las jails en el boot:
Permitimos los raw sockets en los jails para que el ping funcione, no es algo imprescindible pero al principio para debugear nos vendrá bien:
echo ‘security.jail.allow_raw_sockets=1’ » /etc/sysctl.conf
La red puede funcionar de distintos modos:
- Una única ip : Si solo tenemos una ip en el host podemos utilizarla tanto para el host como para el jail siempre y cuando los servicios entre los jails y el host no se solapen.
- Varias ip con alias : Si tenemos varias ips podemos crear un alias en el host y asignar la ip secundaria al jail.
- Utilizar una interfaz vnet : Otra opción es utilizar vnet, dotando al jail de su propia pila TCP/IP de este modo podemos natear o bridgear el jail. Además ya no tendremos que preocuparnos por los bindeos que haga el padre.
Una única ip
Configuramos el jail:
www {
host.hostname = www.alfaexploit.com; # Hostname
ip4 = "inherit"; # IP config
allow.raw_sockets = 1; # Needed for ping
path ="/var/jail/www"; # Path to the jail
mount.devfs; # Mount devfs inside the jail
exec.start = "/bin/sh /etc/rc"; # Start command
exec.stop = "/bin/sh /etc/rc.shutdown"; # Stop command
}
Podemos arrancar nuestro jail con:
Listamos los jails:
JID IP Address Hostname Path
1 www.alfaexploit.com /var/jail/www
Entramos en el jail:
Habilitamos el servicio ssh en el arranque:
Generamos las keys ssh:
Reconfiguramos el puerto ssh ya que en esta configuración de red no se pueden solapar servicios con el host padre:
port 23
Reiniciamos el servicio:
Accedemos por ssh al jail:
kr0m@www:~ %
Varias ip con alias:
ifconfig_em0="inet 192.168.69.23 netmask 255.255.255.0"
defaultrouter="192.168.69.1"
ifconfig_em0_alias0="inet 192.168.69.24 netmask 255.255.255.0"
Reiniciamos los servicios netif y routing para aplicar los cambios:
service routing restart
Hay que tener en cuenta que si un servicio se bindea a 0.0.0.0 en el host padre tendrá preferencia sobre el jail, por este motivo bindeamos el ssh del host a la ip 192.168.69.23, asà el jail podrá hacerlo en la ip 192.168.69.24:
ListenAddress 192.168.69.23
Reiniciamos el servicio:
Configuramos el jail:
www {
host.hostname = www.alfaexploit.com; # Hostname
ip4.addr = "192.168.69.24"; # IP config
allow.raw_sockets = 1; # Needed for ping
path ="/var/jail/www"; # Path to the jail
mount.devfs; # Mount devfs inside the jail
exec.start = "/bin/sh /etc/rc"; # Start command
exec.stop = "/bin/sh /etc/rc.shutdown"; # Stop command
}
Reiniciamos el jail para aplicar la configuración nueva:
service jail start www
Accedemos al jail vÃa ssh:
kr0m@www:~ %
Utilizar una interfaz vnet:
NOTA: Hay que tener en cuenta que si se está configurando en una máquina virtual de VirtualBox habrá que configurar la VM con “Modo promiscuo: permitir todo” en caso contrario el tráfico será capaz de salir de la máquina virtual pero las respuestas de dicho tráfico serán bloqueadas porque la MAC del bridge no coincide con la MAC asignada a la tarjeta de red virtual de VirtualBox.
Creamos un bridge:
cloned_interfaces="bridge0"
ifconfig_em0="up"
ifconfig_bridge0="inet 192.168.69.23 netmask 255.255.255.0 addm em0 up"
defaultrouter="192.168.69.1"
Aplicamos la configuración:
service routing restart
Las interfaces vnet en jails funcionan a modo de túnel, es decir una interfaz epair0a equivale a epair0b en el otro extremo, asà que cuando el jail arranque crearemos epair0a y la meteremos en el bridge por otro lado el jail utilizará epair0b como interfaz de red:
www {
host.hostname = www.alfaexploit.com; # Hostname
vnet = "new"; # IP config
vnet.interface = "epair0b";
allow.raw_sockets = 1; # Needed for ping
path ="/var/jail/www"; # Path to the jail
mount.devfs; # Mount devfs inside the jail
exec.prestart += "ifconfig epair0 create up";
exec.prestart += "ifconfig bridge0 addm epair0a";
exec.poststop = "ifconfig bridge0 deletem epair0a";
exec.poststop += "ifconfig epair0a destroy";
exec.start = "/bin/sh /etc/rc"; # Start command
exec.stop = "/bin/sh /etc/rc.shutdown"; # Stop command
}
Reiniciamos el jail:
service jail start www
Entramos en el jail y configuramos la interfaz del extremo de la interfaz vnet:
vi /etc/rc.conf
ifconfig_epair0b="inet 192.168.69.24 netmask 255.255.255.0"
defaultrouter="192.168.69.1"
Salimos y reiniciamos el jail de nuevo:
service jail stop www
service jail start www
Comprobamos que ya tiene red:
root@www:/ # ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=118 time=12.068 ms
^C
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
Accedemos vÃa ssh:
kr0m@www:~ %
Los jails nos permiten ejecutar comandos adhoc:
jexec JID COMANDO
Una buena referencia en cuanto a documentación es el man del fichero de configuración de los jails:
NOTA: Puede que encontremos mucha documentación mencionando como configurar los jails editando el fichero /etc/rc.conf, se trata de documentación obsoleta. The jail.conf file was added in FreeBSD 9.1
Por último puntualizar ciertas restricciones presentes en los jails:
- No se pueden montar o desmontar sistemas de ficheros.
- No se pueden cargar/descargar reglas de devfs, reglas de firewall(excepto en modo bridge) o cualquier otra operación que modifique datos en espacio de kernel.