Linux Hardening: Aislamiento de procesos (Sandboxing) con Firejail

Firejail SHL

Una cosa que me gusta del modelo de seguridad de Android es que, para una aplicación determinada, presenta los permisos para el usuario y el usuario debe aceptarlos. Esto es bueno porque el usuario tiene control sobre el software que ejecuta, y es una herramienta invaluable para poder usar una aplicación sin otorgarle demasiados accesos sin tener que renunciar para usarla por completo.

Afortunadamente, el mundo de Linux es un entorno mucho más amigable en términos de software malicioso. Una gran razón para esto es el hecho de que el software es auditado por los mantenedores de paquetes de una distribución.

Incluso el mejor software escrito puede contener vulnerabilidades que pueden ser explotadas. Con el advenimiento de las tecnologías de contenedores, como docker, flatpak o LXC, muchos han sugerido utilizarlos para aislar el software del resto del sistema y, al hacerlo, mitigar el daño de posibles incumplimientos.

Al hacer un sandboxing de esta manera, obtiene más control sobre lo que es capaz de hacer, acercándose efectivamente al modelo de seguridad de Android.

Algunas alternativas

Bueno, los contenedores son solo una palabra de moda, en el sentido de que realmente no son ciudadanos de primera clase en Linux. No hay concepto de contenedor en el kernel de Linux. Más bien, los contenedores son una combinación inteligente de las técnicas del kernel existentes que ayudan a aislar partes del sistema. La gran contribución de las tecnologías de contenedores es facilitar el uso de estas características de Linux. Hay otros que no he probado, como Sandstorm.io y runC.

· Docker

Docker es el actor más prominente en este escenario. Mientras que la seguridad de Docker ha mejorado enormemente en los últimos años, y puede usarla para ejecutar aplicaciones gráficas contenidas montando el socket del servidor X, parece una exageración requerir que un daemon docker ejecute Firefox de forma más segura.

Entre otras mejoras de seguridad recientes, Docker ahora admite espacios de nombres de usuario, lo que permite asignar el usuario root para que un proceso privilegiado dentro de los contenedores se ejecute con privilegios de un usuario normal fuera de él.

Además, como el daemon docker se ejecuta con privilegios de root, y es una pieza bastante grande de software, expande la superficie de ataque innecesariamente solo para proporcionar aislamiento de procesos.

· Bubblewrap

También podemos ver bubblewrap de ProjectAtomic. Se deriva del proyecto Flatpak, y en comparación con Docker, está diseñado para ser ejecutado por procesos de usuario sin privilegios, como las aplicaciones de escritorio.

Este tipo de software es el foco del proyecto Flatpak, mientras que Docker está diseñado para servidores, daemons, nubes y toda la cosa de IaaS .

Para un usuario regular y consciente de la seguridad, parece demasiado difícil de administrar y configurar. Solo eche un vistazo a la página (siempre impresionante) Arch Wiki y compruébelo usted mismo.

Es el más pequeño de los tres y es un beneficio en términos de superficie de ataque. El inconveniente es que no cubre y no trata de cubrir todos los escenarios, por lo que no funciona bien con pulseaudio, X11 o DBus. Los diseñadores de BubbleWrap argumentan que esto es más seguro.

En resumen, no funciona bien con todo el software.

· Firejail

Finalmente, recomiendo Firejail, que es el que uso personalmente. Es fácil de usar, fácil de instalar y configurar, y viene con un muy buen conjunto de archivos de configuración para el software común. Si usted quiere aprender firejail a modo avanzado, también tiene eso.

Intenta cubrir todo el software, por lo que es mucho más complejo. Esto es visto por muchos como algo malo porque es realmente difícil asegurar un programa SUID complejo. El beneficio es que funcionará fácilmente con todo su software actual.

SUID (Set owner User ID up on execution) es un tipo especial de permisos de archivos dados a un archivo. Normalmente en Linux/Unix cuando se ejecuta un programa, hereda los permisos de acceso del usuario conectado. SUID se define como otorgar permisos temporales a un usuario para ejecutar un programa/archivo con los permisos del propietario del archivo en lugar del usuario que lo ejecuta. En palabras simples, los usuarios obtendrán los permisos del propietario del archivo así como el UID del propietario y el GID cuando ejecuten un archivo/programa/comando.

Pero antes de aprender a usarlo, veamos cómo funcionan estos aisladores de procesos.

· Cómo funcionan los aisladores de procesos

Como mencionamos anteriormente, los llamados contenedores simplemente usan algunas características de Linux existentes. Todas las tecnologías de contenedores que conozco se basan en estas.

· Espacios de nombres de Linux (Linux namespaces)

El kernel de Linux tiene el concepto de espacios de nombres. Estos espacios de nombres representan diferentes vistas de diferentes partes del sistema.

Por ejemplo, solo si se ejecutan dos procesos en el mismo espacio de nombre, podrán ver el mismo árbol de archivos y directorios y acceder a los mismos archivos. Los archivos en otros espacios de nombres serán invisibles e inaccesibles para ellos.

Hay 7 espacios de nombres en Linux, como el espacio de nombres de archivo, el espacio de nombres de red, el espacio de nombres de cgroup, el espacio de nombres de usuario, el espacio de nombres pid, etc. Por ejemplo, podemos hacer que dos procesos utilicen la misma interfaz de red sin poder verse (net namespace), o tener diferentes vistas del árbol pid o los id de usuario ( espacios de nombres pid y uid ) .

Podemos ver qué espacios de nombres están disponibles en nuestro sistema con:

 ➤➤➤➤ ▶ ls /proc/self/ns
cgroup  ipc  mnt  net  pid  pid_for_children  user  uts

· Capacidades de Linux (Linux capabilities)

Tradicionalmente, Linux ha tenido el concepto de un usuario privilegiado root todo poderoso. Ese usuario tiene poderes ilimitados y acceso a todas las partes del sistema. Los programas SUID tienen todos estos privilegios, incluso si los ejecuta un usuario sin privilegios.

Si bien existe una necesidad legítima de esto en algunas situaciones, también es peligroso e innecesario. Por ejemplo, muchos se sorprenderán al saber que el comando ping simple requiere acceso a sockets sin formato para enviar los paquetes ICMP.

Las capacidades de Linux nos permiten mejorar esta situación en blanco y negro. Podemos limitar lo que el usuario root puede realizar configurando sus capacidades de manera imparcial. Cosas tales como cambio de propietarios de archivos, ignorar permisos DAC, cambiar la configuración de red o eliminar procesos se pueden determinar individualmente para un proceso determinado.

Aquí está la lista completa de capacidades (puede accederla con el comando man 7 capabilities desde su sistema GNU/Linux). Por ejemplo, podemos verificar las capacidades predeterminadas del ejecutable ping con getcap.

 ➤➤➤➤ ▶ getcap /usr/bin/ping
/usr/bin/ping = cap_net_raw+ep

Los contenedores a menudo nos permiten decidir qué capacidades otorgamos a un proceso privilegiado, proporcionando un nivel extra de control.

· Filtros Seccomp

La mayoría de los procesos del espacio de usuario necesitan interactuar con el kernel, incluso si no nos damos cuenta. Hay muy pocas cosas interesantes que puede hacer un programa sin acceso a archivos, red o salida estándar.

Los programas de espacio de usuario utilizan las funciones del kernel a través de llamadas al sistema. Hay más de 300 llamadas al sistema en Linux. A menudo se usan para tratar de explotar errores del kernel y escalar privilegios, y ni que decir tiene, que la mayoría de las veces el software de usuario no los necesita a todos.

seccomp-bpf es una característica del kernel que nos permite usar filtros BPF, para especificar qué llamadas de sistema permitimos a nuestros procesos.

Si un programa es un procesador de texto, ¿por qué necesitaría acceder a la red? podemos controlar eso.

· Uso básico de Firejail

Ahora que entendemos los conceptos básicos, vamos a ver cómo utilizar Firejail.

Instale el paquete del repositorio de su distribución.

#ArchLinux y derivados
pacman -Syu firejail

#Debian, Ubuntu y derivados
apt install firejail

#Gentoo
emerge --ask sys-apps/firejail

Si desea ejecutar un programa en un espacio aislado, basta con ejecutar el binario después de firejail

firejail $nombre_del_programa

Este soporta parámetros de un tiempo, tales como --seccomp para filtrar llamadas del sistema, o --private para ocultar hasta la carpeta de inicio del proceso.

¿Quieres navegar de manera privada?

firejail --private firefox --private window

Para un control más detallado, puede utilizar un archivo de configuración de perfil, pero crear uno es raramente necesario. Firejail viene con un buen conjunto de perfiles preconfigurados que puedes encontrar en /etc/firejail

[email protected] ~ ->
 ➤➤➤➤ ▶ ls /etc/firejail/
0ad.profile                                ghb.profile                               pitivi.profile
2048-qt.profile                            gimp-2.10.profile                         pix.profile
7z.profile                                 gimp-2.8.profile                          playonlinux.profile
abrowser.profile                           gimp.profile                              pluma.profile
...

Se convierte en una molestia a anteponer siempre firejail a tus órdenes, por lo que se puede enlazar fácilmente a firejail todo lo que tenga un perfil con el comando:

sudo firecfg

El comando anterior crea enlaces simbólicos en /usr/local/bin para los programas que tienen un perfil en /etc/firejail.

Tenga en cuenta que después de ejecutar esta orden, el comando less también quedará aislado y puede generar ciertos problemas, en ese caso, elimine el archivo /usr/local/bin/less

Usted puede crear sus enlaces simbólicos para usar firejail con cualquier otro programa

sudo ln -s /usr/bin/firejail /usr/local/bin/<nombre_del_programa>

A veces, desea ejecutar el programa sin el entorno limitado de solamente una vez. Por ejemplo, puede utilizar firefox. En lugar de editar el perfil, sólo usted puede encontrar el binario

[email protected] ~ ->
 ➤➤➤➤ ▶ which -a firefox
/usr/local/bin/firefox #Este es el enlace a firejail, cómo vimos, los enlaza a /usr/local/bin
/usr/bin/firefox #Este es el binario propio, sin firejail
[email protected] ~ ->
 ➤➤➤➤ ▶ /usr/bin/firefox #Ejecutamos Firefox sin firejail

· Uso avanzado de Firejail

Puede comprobar qué aplicaciones tiene espacio aislado con:

 ➤➤➤➤ ▶ firejail --list
2059:sechacklabs::/usr/bin/firejail /usr/bin/telegram-desktop 
5338:sechacklabs::/usr/bin/firejail /usr/bin/firefox 
5903:sechacklabs::/usr/bin/firejail /usr/bin/signal-desktop 
10931:sechacklabs::/usr/bin/firejail /usr/bin/weechat 

Así mismo, puede inspeccionar los procesos dentro del contenedor con:

 ➤➤➤➤ ▶ firejail --tree
2059:sechacklabs::/usr/bin/firejail /usr/bin/telegram-desktop 
  2060:sechacklabs::/usr/bin/firejail /usr/bin/telegram-desktop 
    2063:sechacklabs::/usr/bin/telegram-desktop 
5338:sechacklabs::/usr/bin/firejail /usr/bin/firefox 
  5339:sechacklabs::/usr/bin/firejail /usr/bin/firefox 
    5348:sechacklabs::/usr/lib/firefox/firefox 
      5425:sechacklabs::/usr/lib/firefox/firefox -contentproc -childID 1 -isForBrowser -prefsLen 14404 -schedulerPrefs 0001,2 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 9 true tab 
      5504:sechacklabs::/usr/lib/firefox/firefox -contentproc -childID 2 -isForBrowser -prefsLen 18256 -schedulerPrefs 0001,2 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 9 true tab 
      5669:sechacklabs::/usr/lib/firefox/firefox -contentproc -childID 5 -isForBrowser -prefsLen 18265 -schedulerPrefs 0001,2 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 9 true tab 
      15453:sechacklabs::/usr/lib/firefox/firefox -contentproc -childID 9 -isForBrowser -prefsLen 18265 -schedulerPrefs 0001,2 -greomni /usr/lib/firefox/omni.ja -appomni /usr/lib/firefox/browser/omni.ja -appdir /usr/lib/firefox/browser 9 true tab 
5903:sechacklabs::/usr/bin/firejail /usr/bin/signal-desktop 
  5904:sechacklabs::/usr/bin/firejail /usr/bin/signal-desktop 
    5911:sechacklabs::/bin/sh /usr/bin/signal-desktop 
      5912:sechacklabs::/usr/lib/electron/electron /usr/lib/signal/resources/app.asar
        5914:sechacklabs::/usr/lib/electron/electron --type=zygote --no-sandbox 
          5952:sechacklabs::/usr/lib/electron/electron --type=renderer --no-sandbox --service-pipe-token=698A9297E1734C930A4ABFB202785D82 --lang=en-US --app-path=/usr/lib/signal/resources/app.asar --node-integration=false --webview-tag=false --no-sandbox --native-window-open --preload=/usr/lib/signal/resources/app.asar/preload.js --context-id=2 --enable-pinch --num-raster-threads=2 --enable-main-frame-before-activation --content-image-texture-target=0,0,3553;0,1,3553;0,2,3553;0,3,3553;0,4,3553;0,5,3553;0,6,3553;0,7,3553;0,8,3553;0,9,3553;0,10,3553;0,11,3553;0,12,3553;0,13,3553;0,14,3553;0,15,3553;0,16,3553;0,17,3553;1,0,3553;1,1,3553;1,2,3553;1,3,3553;1,4,3553;1,5,3553;1,6,3553;1,7,3553;1,8,3553;1,9,3553;1,10,3553;1,11,3553;1,12,3553;1,13,3553;1,14,3553;1,15,3553;1,16,3553;1,17,3553;2,0,3553;2,1,3553;2,2,3553;2,3,3553;2,4,3553;2,5,3553;2,6,3553;2,7,3553;2,8,3553;2,9,3553;2,10,3553;2,11,3553;2,12,3553;2,13,3553;2,14,3553;2,15,3553;2,16,3553;2,17,3553;3,0,3553;3,1,3553;3,2,3553;3,3,3553;3,4,3553;3,5,3553;3,6,3553;3,7,3553;3,8,3553;3,9,3553;3,10,3553;3,11,3553;3,12,3553;3,13,3553;3,14,3553;3,15,3553;3,16,3553;3,17,3553;4,0,3553;4,1,3553;4,2,3553;4,3,3553;4,4,3553;4,5,3553;4,6,3553;4,7,3553;4,8,3553;4,9,3553;4,10,3553;4,11,3553;4,12,3553;4,13,3553;4,14,3553;4,15,3553;4,16,3553;4,17,3553 --disable-accelerated-video-decode --enable-gpu-async-worker-context --service-request-channel-token
10931:sechacklabs::/usr/bin/firejail /usr/bin/weechat 
  10932:sechacklabs::/usr/bin/firejail /usr/bin/weechat 
    10935:sechacklabs::/usr/bin/weechat 

O monitorear los recursos con --top o --netstats:

 ➤➤➤➤ ▶ firejail --top
PID   User      RES(KiB) SHR(KiB) CPU%  Prcs Uptime    Command
5338  sechackla 3425200  653896   15.0  7    15:54:54  firejail /usr/bin/firefox 
2059  sechackla 178160   87096    2.0   3    16:39:18  firejail /usr/bin/telegram-desktop 
5903  sechackla 750484   373064   1.0   6    15:27:58  firejail /usr/bin/signal-desktop 
10931 sechackla 43320    20552    0.0   3    03:26:33  firejail /usr/bin/weechat 

 ➤➤➤➤ ▶ firejail --netstats
Displaying network statistics only for sandboxes using a new network namespace.
PID   User      RX(KB/s)   TX(KB/s)   Command
...

Usted también puede copiar archivos dentro y fuera del contenedor con --ls, --put y --get

➤➤➤➤ ▶ firejail --name=mybrowser --private firefox

➤➤➤➤ ▶ firejail --ls=mybrowser ~/Downloads

➤➤➤➤ ▶ firejail --get=mybrowser ~/Downloads/Nombre_del_archivo

➤➤➤➤ ▶ firejail --put=mybrowser Nombre_del_archivo ~/Downloads/Nombre_del_archivo

Usted puede ajustar la velocidad máxima del tráfico con --bandwith, por ejemplo, para una descarga a 80KBps y una subida a 20KBps, debe usar:

firejail --bandwidth=mybrowser set $InterfazDeRed 80 20

Otras opciones interesantes son --disable-mnt que es auto-explicativo (deshabilita el montaje de sistemas de archivos) y --chroot=Nombre_Del_Directorio que monta Nombre_Del_Directorio en solo lectura.

El manual de firejail contiene mucha información al respecto https://firejail.wordpress.com/features-3/man-firejail/

Otros apuntes

Un ejemplo práctico es: podemos ejecutar wireshark con sudo para poder tener acceso a las interfaces de red. Esto es una mala idea: los permisos se deben establecer correctamente para evitar esto, pero vamos a hacerlo.

[email protected] ~ -> 
 ➤➤➤➤ ▶ sudo /usr/bin/wireshark-gtk

[email protected] ~ ->
 ➤➤➤➤ ▶ pscap | grep wireshark
17149 17150 root        wireshark-gtk     full

Podemos comparar esto con la ejecución dentro del contenedor, donde han caído todas las funciones que no necesita

[email protected] ~ ->
 ➤➤➤➤ ▶ sudo firejail /usr/bin/wireshark-gtk

[email protected] ~ ->
 ➤➤➤➤ ▶ pscap | grep wireshark
17213 17215 root        wireshark-gtk     dac_override, net_admin, net_raw

En resumidas cuentas, si un usuario compromete una aplicación (cómo firefox por ejemplo) que solo tiene acceso a sus perfiles, no podrá ir a ningún otro directorio más allá de los explícitamente habilitados en /etc/firejail/firefox.profile

Para opciones más avanzadas y un mejor entendimiento de firejail, le recomiendo que lea:

ArchWiki: https://wiki.archlinux.org/index.php/Firejail

Sitio web de firejail:  https://firejail.wordpress.com

Síguenos en FacebookTwitterunete a nuestra charla en Riotúnete a IRC o únete a Telegram y no olvides compartirnos en las redes sociales. También puede hacernos una donación o comprar nuestros servicios.

Acerca del autor

Especialista en Seguridad Informática bajo certificación OSCP, especialista en técnicas de privacidad y seguridad en la red, desarrollador back-end, miembro de la FSF y Fundador de Security Hack Labs. Entusiasta de la tecnología y amante de GNU/Linux. Twitter: @edu4rdshl XMPP/Email: [email protected]