
Herramienta de sandboxing de bajo nivel sin privilegios utilizada por Flatpak y proyectos similares
Muchas herramientas de tiempo de ejecución de contenedores, como systemd-nspawn, docker,
etc., se centran en proporcionar infraestructura para administradores de sistemas y
herramientas de orquestación (p. ej. Kubernetes) para ejecutar contenedores.
Estas herramientas no son adecuadas para dárselas a usuarios sin privilegios, porque es trivial convertir dicho acceso en un shell root con privilegios completos en el host.
Existe una función en el kernel de Linux llamada espacios de nombres de usuario que permite a los usuarios sin privilegios usar funciones de contenedores. Bubblewrap las usa para construir la sandbox, lo que permite a cualquier usuario usar la herramienta.
Históricamente, bubblewrap también admitía un modo setuid para sistemas donde no se admitían los espacios de nombres de usuario sin privilegios. Sin embargo, esto se ha eliminado.
El código original de bubblewrap existía antes de los espacios de nombres de usuario; hereda código de xdg-app helper que a su vez deriva lejanamente de linux-user-chroot.
Los mantenedores de esta herramienta creen que no permite la escalada de privilegios, ni siquiera cuando se usa en combinación con el software típico instalado en esa distribución. Sin embargo, puede aumentar la capacidad de un usuario con sesión iniciada para realizar ataques de denegación de servicio.
En particular, bubblewrap usa PR_SET_NO_NEW_PRIVS para desactivar
los binarios setuid, que es la forma tradicional de salir de cosas
como los chroots.
bubblewrap es una herramienta para construir entornos sandbox. bubblewrap no es una sandbox completa y lista para usar con una política de seguridad específica.
Algunos de los casos de uso de bubblewrap quieren un límite de seguridad entre la sandbox y el sistema real; otros casos de uso quieren la capacidad de cambiar el diseño del sistema de archivos para los procesos dentro de la sandbox, pero no pretenden ser un límite de seguridad. Como resultado, el nivel de protección entre los procesos confinados en la sandbox y el sistema host está enteramente determinado por los argumentos pasados a bubblewrap.
Cualquier programa que construya los argumentos de línea de comandos para bubblewrap (a menudo un framework más grande como Flatpak, libgnome-desktop, sandwine o un script ad-hoc) es responsable de definir su propio modelo de seguridad, y de elegir los argumentos de línea de comandos de bubblewrap adecuados para implementar ese modelo de seguridad.
Algunos aspectos de la seguridad de la sandbox que requieren especial atención se describen en la sección Limitaciones a continuación.
Este programa puede ser compartido por todas las herramientas de contenedores que realizan operaciones sin root, como:
También nos gustaría que estuviera disponible en clústeres de Kubernetes/OpenShift. Tener la capacidad de que los usuarios sin privilegios usen funciones de contenedores haría significativamente más fáciles los escenarios de depuración interactiva y similares.
bubblewrap está disponible en los repositorios de paquetes de la mayoría de las distribuciones Linux y se puede instalar desde allí.
Si necesitas compilar bubblewrap desde el código fuente, puedes hacerlo con meson:
meson _builddir
meson compile -C _builddir
meson test -C _builddir
meson install -C _builddir
bubblewrap funciona creando un espacio de nombres de montaje nuevo y completamente vacío, donde la raíz está en un tmpfs que es invisible desde el host, y que se limpiará automáticamente cuando salga el último proceso. Luego puedes usar opciones de línea de comandos para construir el sistema de archivos raíz, el entorno del proceso y el comando a ejecutar en el espacio de nombres.
Hay un script de demostración más completo en el
código fuente, pero aquí hay una versión recortada que ejecuta
un nuevo shell reutilizando el /usr del host.
bwrap \
--ro-bind /usr /usr \
--symlink usr/lib64 /lib64 \
--proc /proc \
--dev /dev \
--unshare-pid \
--new-session \
bash
Este es un ejemplo incompleto, pero útil con fines ilustrativos.
Más a menudo, en lugar de crear un contenedor usando el árbol del sistema de archivos del
host, querrás apuntar a un chroot. Allí, en lugar de crear el enlace simbólico
lib64 -> usr/lib64 en el tmpfs, es posible que ya lo hayas creado en el rootfs de destino.
El objetivo de bubblewrap es ejecutar una aplicación en una sandbox, donde tenga acceso restringido a partes del sistema operativo o a datos de usuario, como el directorio personal.
bubblewrap siempre crea un nuevo espacio de nombres de montaje, y el usuario puede especificar
exactamente qué partes del sistema de archivos deben ser visibles en la sandbox.
Cualquier directorio de este tipo que especifiques se monta nodev por defecto, y puede hacerse de solo lectura.
Además, puedes usar estas funciones del kernel:
Espacios de nombres de usuario (CLONE_NEWUSER): Esto oculta todo excepto el uid y gid actuales de la sandbox. También puedes cambiar el valor que deben tener uid/gid dentro de la sandbox.
Espacios de nombres IPC (CLONE_NEWIPC): La sandbox obtendrá su propia copia de todas las diferentes formas de IPC, como la memoria compartida SysV y los semáforos.
Espacios de nombres PID (CLONE_NEWPID): La sandbox no verá ningún proceso fuera de ella. Además, bubblewrap ejecutará un pid1 trivial dentro de tu contenedor para manejar los requisitos de recolección de procesos hijos en la sandbox. Esto evita lo que ahora se conoce como el problema del pid 1 de Docker.
Espacios de nombres de red (CLONE_NEWNET): La sandbox no verá la red. En su lugar, tendrá su propio espacio de nombres de red con solo un dispositivo de loopback.
Espacio de nombres UTS (CLONE_NEWUTS): La sandbox tendrá su propio nombre de host.
Filtros seccomp: Puedes pasar filtros seccomp que limiten qué syscalls se pueden realizar en la sandbox. Para más información, consulta Seccomp.
Como se señaló en la sección Seguridad de la sandbox anterior, el nivel de protección entre los procesos confinados en la sandbox y el sistema host está enteramente determinado por los argumentos pasados a bubblewrap. Aquí se señalan algunos aspectos que requieren especial cuidado.
Si no estás filtrando los comandos TIOCSTI con filtros seccomp,
se necesita el argumento --new-session para proteger contra la ejecución de comandos
fuera de la sandbox
(véase CVE-2017-5226).
Todo lo montado dentro de la sandbox puede usarse potencialmente para escalar privilegios. Por ejemplo, si vinculas un socket D-Bus dentro de la sandbox, se puede usar para ejecutar comandos a través de systemd. Puedes usar xdg-dbus-proxy para filtrar la comunicación D-Bus.