Implementación del control de acceso obligatorio con SELinux o AppArmor en Linux


Para superar las limitaciones y aumentar los mecanismos de seguridad proporcionados por los permisos estándar ugo/rwx y las listas de control de acceso, la Agencia de Seguridad Nacional de los Estados Unidos (NSA) ideó un método flexible de control de acceso obligatorio (MAC) conocido como SELinux (abreviatura de Security Enhanced Linux) para restringir, entre otras cosas, la capacidad de los procesos para acceder o realizar otras operaciones en los objetos del sistema (como archivos, directorios, puertos de red, etc.) al menor permiso posible, mientras todavía permitiendo modificaciones posteriores a este modelo.

Otro MAC popular y ampliamente utilizado es AppArmor, que además de las funciones proporcionadas por SELinux, incluye un modo de aprendizaje que permite al sistema "aprender" cómo se comporta una aplicación específica y establecer límites configurando perfiles para un uso seguro de la aplicación.

En CentOS 7, SELinux está incorporado en el propio kernel y está habilitado en el modo Enforcing de forma predeterminada (más sobre esto en la siguiente sección), a diferencia de openSUSE y Ubuntu que usan AppArmor.

En este artículo explicaremos los conceptos básicos de SELinux y AppArmor y cómo utilizar una de estas herramientas para su beneficio según la distribución que elija.

Introducción a SELinux y cómo usarlo en CentOS 7

Security Enhanced Linux puede funcionar de dos formas diferentes:

  1. Aplicación: SELinux niega el acceso según las reglas de política de SELinux, un conjunto de pautas que controlan el motor de seguridad.
  2. Permisivo: SELinux no niega el acceso, pero las denegaciones se registran para acciones que se habrían denegado si se ejecutaran en modo de aplicación.

SELinux también se puede desactivar. Aunque no es un modo de funcionamiento en sí mismo, sigue siendo una opción. Sin embargo, aprender a usar esta herramienta es mejor que simplemente ignorarla. ¡Tenlo en mente!

Para mostrar el modo actual de SELinux, use getenforce . Si desea alternar el modo de operación, use setenforce 0 (para establecerlo en Permissive) o setenforce 1 (Enforcing).

Dado que este cambio no sobrevivirá a un reinicio, deberá editar el archivo/etc/selinux/config y establecer la variable SELINUX en imponiendo , permissive o deshabilitado para lograr la persistencia en los reinicios:

En una nota al margen, si getenforce devuelve Disabled, tendrá que editar/etc/selinux/config con el modo de operación deseado y reiniciar. De lo contrario, no podrá establecer (o alternar) el modo de operación con setenforce .

Uno de los usos típicos de setenforce consiste en alternar entre los modos SELinux (de obligatorio a permisivo o al revés) para solucionar problemas de una aplicación que se está comportando mal o que no funciona como se esperaba. Si funciona después de configurar SELinux en modo permisivo, puede estar seguro de que está viendo un problema de permisos de SELinux.

Dos casos clásicos en los que probablemente tendremos que lidiar con SELinux son:

  1. Cambiar el puerto predeterminado donde escucha un demonio.
  2. Configuración de la directiva DocumentRoot para un host virtual fuera de/var/www/html.

Echemos un vistazo a estos dos casos utilizando los siguientes ejemplos.

Una de las primeras cosas que hacen la mayoría de los administradores de sistemas para proteger sus servidores es cambiar el puerto en el que escucha el demonio SSH, principalmente para desalentar a los escáneres de puertos y a los atacantes externos. Para hacer esto, usamos la directiva Port en/etc/ssh/sshd_config seguida del nuevo número de puerto de la siguiente manera (usaremos el puerto 9999 en este caso):

Port 9999

Después de intentar reiniciar el servicio y comprobar su estado veremos que no pudo iniciarse:

# systemctl restart sshd
# systemctl status sshd

Si echamos un vistazo a /var/log/audit/audit.log, veremos que SELinux impidió que sshd se iniciara en el puerto 9999 porque es un puerto reservado para el servicio de administración de JBoss (los mensajes de registro de SELinux incluyen la palabra “ AVC ”para que puedan identificarse fácilmente en otros mensajes):

# cat /var/log/audit/audit.log | grep AVC | tail -1

En este punto, la mayoría de la gente probablemente deshabilitaría SELinux, pero nosotros no lo haremos. Veremos que hay una manera de que SELinux, y sshd escuchando en un puerto diferente, vivan en armonía juntos. Asegúrese de tener el paquete policycoreutils-python instalado y ejecutado:

# yum install policycoreutils-python

Para ver una lista de los puertos en los que SELinux permite que sshd escuche. En la siguiente imagen también podemos ver que el puerto 9999 estaba reservado para otro servicio y, por lo tanto, no podemos usarlo para ejecutar otro servicio por el momento:

# semanage port -l | grep ssh

Por supuesto, podríamos elegir otro puerto para SSH, pero si estamos seguros de que no necesitaremos usar esta máquina específica para ningún servicio relacionado con JBoss, podemos modificar la regla SELinux existente y asignar ese puerto a SSH en su lugar:

# semanage port -m -t ssh_port_t -p tcp 9999

Después de eso, podemos usar el primer comando semanage para verificar si el puerto fue asignado correctamente, o las opciones -lC (abreviatura de list custom):

# semanage port -lC
# semanage port -l | grep ssh

Ahora podemos reiniciar SSH y conectarnos al servicio usando el puerto 9999. Tenga en cuenta que este cambio sobrevivirá al reinicio.

Si necesita configurar un servidor virtual Apache usando un directorio que no sea/var/www/html como DocumentRoot (digamos, por ejemplo,/websrv/sites/gabriel/public_html):

DocumentRoot “/websrv/sites/gabriel/public_html”

Apache se negará a entregar el contenido porque index.html ha sido etiquetado con el tipo SELinux default_t, al que Apache no puede acceder:

# wget http://localhost/index.html
# ls -lZ /websrv/sites/gabriel/public_html/index.html

Al igual que con el ejemplo anterior, puede utilizar el siguiente comando para verificar que se trata de un problema relacionado con SELinux:

# cat /var/log/audit/audit.log | grep AVC | tail -1

Para cambiar la etiqueta de/websrv/sites/gabriel/public_html de forma recursiva a httpd_sys_content_t , haga lo siguiente:

# semanage fcontext -a -t httpd_sys_content_t "/websrv/sites/gabriel/public_html(/.*)?"

El comando anterior otorgará a Apache acceso de solo lectura a ese directorio y su contenido.

Finalmente, para aplicar la política (y hacer que el cambio de etiqueta sea efectivo de inmediato), haga lo siguiente:

# restorecon -R -v /websrv/sites/gabriel/public_html

Ahora debería poder acceder al directorio:

# wget http://localhost/index.html

Para obtener más información sobre SELinux, consulte la guía del administrador y SELinux de Fedora 22.