Cómo aislar procesos con Systemd en Ubuntu 20.04

Índice
  1. Introducción
  • Prerrequisitos
  • Paso 1: Instalación de lighttpd
  • Paso 2: preparación del sistema
  • Paso 3: Implementación de un usuario y un grupo
  • Paso 4: Gestión del archivo PID
  • Paso 5: Tomar prestadas las capacidades de la raíz
  • Paso 6: Bloqueo del sistema de archivos
  • Paso 7: Restricción de llamadas al sistema
  • Paso 8: Implementación de otras opciones
  • Conclusión
  • El autor seleccionó el Fondo de Código Libre y Abierto para recibir una donación como parte del programa Write for DOnations.

    Introducción

    El sandboxing es una técnica de seguridad informática que se centra en aislar un programa o proceso de las partes de un sistema con las que no necesita interactuar durante su funcionamiento normal. Cuando se inicia un programa nuevo, este tiene todas las capacidades del usuario con el que se ejecuta. Estas capacidades suelen ser mucho mayores que las que el programa necesita para realizar su función. Esto puede generar problemas de seguridad cuando un actor malintencionado manipula el programa para acceder a algunas de sus capacidades no utilizadas y hacer algo que el programa normalmente no haría.

    El propósito del sandbox es identificar exactamente qué habilidades y recursos necesita un programa y luego bloquear todo lo demás.

    El conjunto de herramientas de administración del sistema systemd se utiliza en casi todas las principales distribuciones de Linux para iniciar, detener y administrar programas y procesos. Tiene muchas opciones de sandbox que restringen la forma en que el proceso que inicia accede al sistema host, lo que lo hace más seguro.

    El objetivo de este tutorial no es crear el entorno sandbox más estricto posible, sino utilizar las configuraciones recomendadas y fácilmente habilitables para hacer que su sistema sea más seguro.

    En este tutorial, realizarás una demostración práctica de cómo usar las técnicas de sandbox de systemd en Ubuntu 20.04 para implementar y probar estas técnicas de manera eficiente. Cualquier proceso que se ejecute en un sistema Linux que use systemd puede volverse más seguro con estas técnicas.

    Prerrequisitos

    Necesitarás lo siguiente para comenzar esta guía:

    • Un sistema Ubuntu 20.04.
    • Un usuario no root con privilegios sudo. Siga la configuración inicial del servidor con Ubuntu 20.04 para obtener información sobre cómo hacer esto en Ubuntu 20.04.
    • Conocimientos básicos sobre la gestión de procesos con systemd. Consulta la guía Systemd Essentials: Working with Services, Units, and the Journal para conocer los conceptos básicos.
    • Será útil tener conocimientos básicos sobre los archivos de unidad de Systemd. Consulta la guía Comprensión de las unidades y los archivos de unidad de Systemd para obtener más información.

    Paso 1: Instalación de lighttpd

    En este tutorial, aislaremos el servidor web lighttpd. No elegimos lighttpd porque sea menos seguro que otro software, sino porque es un programa pequeño con una sola función que se puede aislar fácilmente. Esto lo convierte en una excelente opción para una aplicación de aprendizaje.

    Actualicemos el sistema para iniciar:

    1. sudo apt update

    Verifique los paquetes que se actualizarán en su sistema antes de escribir y:

    1. sudo apt upgrade

    Luego instala lighttpd:

    1. sudo apt install lighttpd

    Este proceso de instalación instalará y habilitará automáticamente un archivo de servicio systemd para lighttpd. Esto hará que lighttpd se inicie al reiniciar el sistema.

    Ahora que tenemos lighttpd instalado y ejecutándose en nuestro sistema, nos familiarizaremos con las herramientas systemd que usaremos cuando comencemos a crear un sandbox.

    Paso 2: preparación del sistema

    En este paso, se familiarizará con los comandos systemd que utilizará y preparará su sistema para permitirle aislar de manera eficiente un proceso.

    systemd es un nombre genérico para un conjunto de herramientas que tienen nombres diferentes. Las dos que usará son systemctly journalctl. systemctladministra procesos y sus archivos de servicio, mientras journalctlinteractúa con el registro del sistema.

    systemd utiliza archivos de servicio para definir cómo se gestionará un proceso. systemd carga estos archivos desde varias ubicaciones en el sistema de archivos. El siguiente comando le mostrará la ubicación del archivo de servicio activo y mostrará las modificaciones que se estén utilizando:

    1. sudo systemctl cat process.service

    Debes reemplazarlo processcon el proceso en el que estás trabajando. Aquí se utiliza lighttpd:

    1. sudo systemctl cat lighttpd.service

    Esta es la salida del comando anterior:

    Output# /lib/systemd/system/lighttpd.service[Unit]Description=Lighttpd DaemonAfter=network-online.target[Service]Type=simplePIDFile=/run/lighttpd.pidExecStartPre=/usr/sbin/lighttpd -tt -f /etc/lighttpd/lighttpd.confExecStart=/usr/sbin/lighttpd -D -f /etc/lighttpd/lighttpd.confExecReload=/bin/kill -USR1 $MAINPIDRestart=on-failure[Install]WantedBy=multi-user.target

    Esta salida muestra que el archivo de servicio se encuentra en /lib/systemd/system/lighttpd.servicey que no hay opciones de anulación en uso. Las opciones de anulación agregan o modifican el archivo de servicio base. Usará anulaciones para aislar lighttpd con un archivo de anulación dedicado.

    Los archivos de anulación se encuentran en . systemd tiene un comando dedicado que creará un archivo de anulación en la ubicación correcta y se ejecutará después de guardar y salir del editor. Le indica a systemd que use cualquier configuración nueva que haya escrito./etc/systemd/system/process.service.d/override.confeditsystemctl daemon-reloadsystemctl daemon-reload

    El comando de edición systemd tiene el siguiente formato:

    1. sudo systemctl edit process.service

    Cuando ejecutas este comando, systemd normalmente elegirá tu editor CLI predeterminado, pero no siempre es así y es posible que te encuentres en vi o incluso en ed. Puedes configurar qué editor usará systemd configurando la SYSTEMD_EDITORvariable de shell.

    Establezca esta variable de shell agregando una línea a su ~/.bashrcarchivo. Abra este archivo con un editor de texto:

    1. nano ~/.bashrc

    Y añade la siguiente línea:

    ~/.bashrc

    export SYSTEMD_EDITOR=editor

    Cambie editora su editor CLI preferido. Aquí está la línea configurada para usar el editor nano:

    ~/.bashrc

    export SYSTEMD_EDITOR=nano

    Confirme que esto esté configurado después de cerrar sesión y volver a iniciarla con el echocomando:

    1. echo $SYSTEMD_EDITOR

    Este comando imprimirá el nombre del editor que usted configure.

    La SYSTEMD_EDITORvariable shell solo se configura en el shell del usuario y no en el shell de root que se abre con sudo. Para pasar esta variable al shell de root, invoque systemctl editusando sudo -E:

    1. sudo -E systemctl edit process.service

    La recomendación final facilitará la depuración de su entorno aislado al mostrarle los errores que hayan causado sus cambios. Estos errores se registrarán en el registro del sistema, al que se accede con el journalctlcomando.

    Durante el sandbox, se realizarán muchos cambios que interrumpirán el proceso que se está intentando aislar. Por ese motivo, es una buena idea abrir una segunda terminal y dedicarla a seguir el registro del sistema. Esto ahorrará tiempo al volver a abrir el registro del sistema.

    Siga el registro del sistema en la segunda terminal ejecutando:

    1. sudo journalctl -f -u process.service
    • -f:Siga o siga el registro del sistema para que las nuevas líneas se muestren inmediatamente.
    • -u process.service:Muestra únicamente las líneas de registro de lo que processestás haciendo en el sandbox.

    Lo siguiente es lo que debe ejecutar para imprimir solo los errores de lighttpd:

    1. sudo journalctl -f -u lighttpd.service

    A continuación, comenzará a editar el override.confarchivo y comenzará a poner en sandbox lighttpd.

    Paso 3: Implementación de un usuario y un grupo

    En este paso, configurará el usuario no root con el que se ejecutará lighttpd.

    En su configuración predeterminada, lighttpd comienza a ejecutarse como usuario root y luego cambia al usuario y grupo www-data . Esto es un problema porque mientras lighttpd se ejecuta como root, puede hacer todo lo que root puede hacer, es decir, cualquier cosa.

    systemd proporciona la capacidad de iniciar y ejecutar el proceso como un usuario no root, evitando así este problema.

    Regrese a su primera sesión de terminal y comience a editar el archivo de anulación ejecutando:

    1. sudo -E systemctl edit lighttpd.service

    Ahora, agregue las siguientes líneas:

    archivo de anulación de lighttpd

    [Service]User=www-dataGroup=www-data
    • [Service]:Le dice a systemd que las siguientes opciones deben aplicarse a la [Service]sección.
    • User=www-data:Define el usuario con el que se iniciará el proceso.
    • Group=www-data:Define el grupo como el cual se iniciará el proceso.

    A continuación, guarde y salga del editor y reinicie lighttpd con el siguiente comando:

    1. sudo systemctl restart lighttpd.service

    lighttpd no podrá iniciarse porque estaba usando la rootautorización para escribir un archivo PID en una ubicación que pertenece a root . El usuario www-data no puede escribir en directorios que pertenecen a root . Este problema se indica en el registro del sistema que aparecerá en su segunda sesión de terminal:

    journalctl error messageAug 29 11:37:35 systemd lighttpd[7097]: 2020-08-29 11:37:35: (server.c.1233) opening pid-file failed: /run/lighttpd.pid Permission denied

    Para resolver este problema se sigue el proceso de sandbox que es:

    1. Implementar una restricción de espacio aislado.
    2. Reinicie el proceso y verifique si hay errores.
    3. Corrija cualquier error.

    A continuación, resolverá el problema del archivo PID mientras sigue aplicando las restricciones de usuario y grupo que estableció en esta sección.

    Paso 4: Gestión del archivo PID

    Un archivo PID es un archivo que contiene el PID o número de identificación de proceso de un proceso en ejecución. Los programas de larga duración como lighttpd los utilizan para gestionar sus propios procesos. El problema que encontró en la sección anterior fue que lighttpd no pudo escribir su archivo PID en /run/lighttpd.pid, porque /run/es propiedad de root .

    systemd tiene la RuntimeDirectoryopción para este problema, que utilizarás para darle a lighttpd una ubicación donde pueda escribir su archivo PID.

    La RuntimeDirectoryopción le permite especificar un directorio /run/que se creará con el usuario y el grupo que configuró en el Paso 3 cuando systemd inicie lighttpd. lighttpd podrá escribir su PID en este directorio sin necesidad de la autoridad de root .

    Primero, abra y edite el archivo de anulación con el mismo comando que utilizó en el Paso 3 :

    1. sudo -E systemctl edit lighttpd.service

    A continuación, agregue la siguiente línea debajo de las dos líneas que ya agregó al archivo de anulación:

    archivo de anulación de lighttpd

    RuntimeDirectory=lighttpd

    Guardar y salir del editor.

    No se agrega la ruta completa al directorio con RuntimeDirectory, solo el nombre del directorio bajo /run/. En este caso, el directorio que creará systemd es /run/lighttpd/.

    Ahora debe configurar lighttpd para escribir su archivo PID en el nuevo directorio /run/lighttpd/en lugar de /run/.

    Abra el archivo de configuración de lighttpd con un editor de texto:

    1. sudo nano /etc/lighttpd/lighttpd.conf

    Cambie la siguiente línea:

    /etc/lighthttpd/lighthttpd.conf

    server.pid-file             = "/run/lighttpd.pid"

    A:

    /etc/lighthttpd/lighthttpd.conf

    server.pid-file             = "/run/lighttpd/lighttpd.pid"

    Guardar y salir del editor.

    Ahora, reinicie lighttpd:

    1. sudo systemctl restart lighttpd.service

    No se inicia porque no puede hacer algo que requiere una de las capacidades del usuario root . A continuación, resolverá este nuevo problema.

    Paso 5: Tomar prestadas las capacidades de la raíz

    La siguiente línea en el registro del sistema explica el problema que detuvo el inicio de lighttpd:

    journalctl error messageAug 29 12:07:22 systemd lighttpd[7220]: 2020-08-29 12:07:22: (network.c.311) can't bind to socket: 0.0.0.0:80 Permission denied

    Sólo root puede abrir un puerto de red por debajo del número 1024. lighttpd está intentando abrir el puerto HTTP 80, pero se le niega porque el usuario www-data no puede hacerlo.

    El problema se resuelve dándole al proceso lighttpd una pequeña parte del poder de la raíz , es decir, abrir puertos por debajo de 1024.

    El “poder” de root se divide en habilidades llamadas “capacidades”. El usuario root tiene todas las capacidades y, por lo tanto, puede hacer cualquier cosa. Dividir el poder de root en capacidades significa que se pueden otorgar individualmente a procesos que no sean root. Esto permite que ese proceso haga algo que habría requerido un usuario root completo , pero que un usuario normal ahora puede hacer con una de las capacidades de root .

    La opción systemd para darle a un proceso una o más de las capacidades de la raíz es la AmbientCapabilitiesopción.

    Abra el archivo de anulación:

    1. sudo -E systemctl edit lighttpd.service

    Luego agrega la siguiente línea debajo de las líneas que ya agregaste:

    archivo de anulación de lighttpd

    AmbientCapabilities=CAP_NET_BIND_SERVICE

    La CAP_NET_BIND_SERVICEcapacidad permite que un proceso abra puertos bajo 1024.

    Guardar y salir del archivo.

    lighttpd ahora podrá iniciarse.

    Ahora tiene un servidor web lighttpd en funcionamiento que ha hecho más seguro que su configuración predeterminada. Hay más opciones de sandbox proporcionadas por systemd que puede usar para hacer que su proceso de destino sea aún más seguro. Exploraremos algunas de ellas en las siguientes secciones.

    En el siguiente paso, restringirá a qué puede acceder lighttpd en el sistema de archivos.

    Paso 6: Bloqueo del sistema de archivos

    El proceso lighttpd se ejecuta como el usuario www-data y, por lo tanto, puede acceder a cualquier archivo del sistema al que www-data tenga permiso de lectura y escritura. En el caso de www-data , no es mucho, pero aún así es más de lo que lighttpd necesita.

    La primera y más sencilla configuración de sandbox es la ProtectHomeopción. Esta opción impide que el proceso lea o escriba en cualquier cosa que se encuentre debajo de /home/. lighttpd no necesita acceder a nada que se encuentre debajo de , /home/por lo que implementar esto protegerá todos sus archivos privados sin afectar a lighttpd.

    Abra el archivo de anulación:

    1. sudo -E systemctl edit lighttpd.service

    Luego agregue la siguiente línea al final del archivo:

    archivo de anulación de lighttpd

    ProtectHome=true

    Guarde y salga del editor, luego reinicie lighttpd para verificar que esté funcionando como espera con el siguiente comando:

    1. sudo systemctl restart lighttpd.service

    Ha protegido /home/, pero aún queda el resto del sistema de archivos. Esto se soluciona con la ProtectSystemopción , que impide que un proceso escriba en partes del sistema de archivos.

    La ProtectSystemopción tiene tres configuraciones que ofrecen niveles de protección crecientes. Son las siguientes:

    • true:Establece los siguientes directorios como de solo lectura:
      • /usr/
      • /boot/
      • /efi/
    • full:Establece los siguientes directorios como de solo lectura:
      • /usr/
      • /boot/
      • /efi/
      • /etc/
    • strict:Establece los siguientes directorios como de solo lectura:
      • Todo el sistema de archivos

    Un nivel de protección más alto es más seguro, así que configure la ProtectSystemopción strictagregando la siguiente línea al archivo de anulación:

    archivo de anulación de lighttpd

    ProtectSystem=strict

    Guarde y salga del editor y reinicie lighttpd con el siguiente comando:

    1. sudo systemctl restart lighttpd.service

    lighttpd no podrá iniciarse porque necesita escribir sus archivos de registro /var/log/lighttpd/y la strictconfiguración no lo permite. La siguiente línea en el registro del sistema muestra el problema:

    journalctl error messageAug 29 12:44:41 systemd lighttpd[7417]: 2020-08-29 12:44:41: (server.c.752) opening errorlog '/var/log/lighttpd/error.log' failed: Read-only file system

    Este problema fue anticipado por systemd con la LogsDirectoryopción. Toma el nombre de un directorio en el /var/log/que el proceso tiene permiso para escribir sus registros.

    Abra el archivo de anulación nuevamente en su primera sesión de terminal:

    1. sudo -E systemctl edit lighttpd.service

    El directorio de registro de lighttpd es /var/log/lighttpd/así que agregue la siguiente línea al final del archivo de anulación:

    archivo de anulación de lighttpd

    LogsDirectory=lighttpd

    Guarde y salga del editor y reinicie lighttpd:

    1. sudo systemctl restart lighttpd.service

    lighttpd ahora podrá iniciarse y ejecutarse.

    Nota: Si está poniendo en aislamiento un proceso que no sea lighttpd y desea permitir que su proceso tenga acceso de escritura a un directorio específico fuera de él, /var/log/utilice la opción ReadWritePaths.

    En el siguiente paso, limitará la forma en que el proceso lighttpd puede interactuar con el resto del sistema restringiendo las llamadas al sistema que puede realizar.

    Paso 7: Restricción de llamadas al sistema

    Una llamada al sistema es la forma en que un programa solicita algo al núcleo. La cantidad de llamadas al sistema es bastante grande e incluye acciones como leer, escribir y eliminar archivos, tareas relacionadas con el hardware como montar un sistema de archivos, iniciar un proceso, reiniciar y muchas más.

    systemd ha creado grupos de llamadas del sistema que los procesos, como lighttpd, suelen utilizar y que excluyen las llamadas que no utilizan. Las llamadas del sistema bloqueadas son cosas como montar un sistema de archivos y reiniciar el sistema, que lighttpd nunca necesita hacer.

    Primero, abra el archivo de anulación:

    1. sudo -E systemctl edit lighttpd.service

    Agregue la siguiente línea al final del archivo para usar la SystemCallFilteropción para configurar el @system-servicegrupo:

    archivo de anulación de lighttpd

    SystemCallFilter=@system-service

    Guarde y salga del editor y reinicie lighttpd:

    1. sudo systemctl restart lighttpd.service

    En la siguiente sección, aplicará las opciones restantes de sandbox recomendadas.

    Paso 8: Implementación de otras opciones

    La documentación de systemd recomienda que se habiliten las siguientes opciones para procesos en red de larga ejecución como lighttpd. Todas estas configuraciones son opcionales, pero cada una de ellas hace que el proceso que estás poniendo en sandbox sea más seguro y deberías usarlas si puedes.

    Debes habilitar estas opciones una a la vez y reiniciar el proceso después de cada una. Si las agregas todas a la vez, será mucho más difícil depurar un problema.

    Las opciones recomendadas a continuación se acompañan de una breve descripción de lo que hacen. Agregue estas líneas a su archivo de anulación debajo de las líneas que ya agregó:

    archivo de anulación de lighttpd

    NoNewPrivileges=true

    Esta opción impide que el proceso aislado y cualquiera de sus secundarios obtengan nuevos privilegios.

    archivo de anulación de lighttpd

    ProtectKernelTunables=true

    Esta opción evita que el proceso cambie cualquier variable del kernel.

    archivo de anulación de lighttpd

    ProtectKernelModules=true

    Esta opción detiene el proceso de carga o descarga módulos del kernel.

    archivo de anulación de lighttpd

    ProtectKernelLogs=true

    Esta opción impide que el proceso lea y escriba directamente en el registro del núcleo. Debe utilizar la aplicación de registro del sistema para registrar los mensajes de registro.

    archivo de anulación de lighttpd

    ProtectControlGroups=true

    Esta opción impide que el proceso modifique los grupos de control del sistema.

    archivo de anulación de lighttpd

    MemoryDenyWriteExecute=true

    Esta opción impide que el proceso modifique cualquier código que se esté ejecutando en la memoria del sistema.

    archivo de anulación de lighttpd

    RestrictSUIDSGID=true

    Esta opción impide que el proceso establezca el ID de usuario (SUID) o el ID de grupo (SGID) en archivos o directorios. Esta capacidad se puede utilizar de forma abusiva para elevar privilegios.

    archivo de anulación de lighttpd

    KeyringMode=private

    Esta opción impide que el proceso acceda al conjunto de claves del kernel de otros procesos que se ejecutan como el mismo usuario.

    archivo de anulación de lighttpd

    ProtectClock=true

    Esta opción evita que el proceso cambie los relojes del sistema de hardware y software.

    archivo de anulación de lighttpd

    RestrictRealtime=true

    Esta opción impide que el proceso habilite la programación en tiempo real que puede usarse de forma abusiva para sobrecargar la CPU.

    archivo de anulación de lighttpd

    PrivateDevices=true

    Esta opción impide que el proceso acceda a los dispositivos físicos conectados al sistema, como dispositivos de almacenamiento o dispositivos USB.

    archivo de anulación de lighttpd

    PrivateTmp=true

    Esta opción obliga al proceso a utilizar directorios privados /tmp/. /var/tmp/Esto impide que el proceso pueda leer los archivos temporales de otros programas que se almacenan en esos directorios compartidos del sistema.

    archivo de anulación de lighttpd

    ProtectHostname=true

    Esta opción evita que el proceso cambie el nombre de host del sistema.

    El proceso que ha protegido ahora es mucho más seguro que en su configuración predeterminada. Ahora puede tomar estas técnicas y usarlas para cualquier otro proceso que necesite proteger en su sistema Linux.

    Conclusión

    En este artículo, hizo que el programa lighttpd fuera más seguro mediante el uso de las opciones de sandbox de systemd. Puede utilizar estas técnicas con cualquier proceso que administre systemd, lo que le permitirá seguir mejorando la seguridad de su sistema.

    La lista completa de opciones de seguridad y sandbox se encuentra en la documentación en línea de systemd. Además, consulte otros temas de seguridad en la Comunidad de DigitalOcean.

    SUSCRÍBETE A NUESTRO BOLETÍN 
    No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion