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


Para superar las limitaciones y aumentar los mecanismos de seguridad provistos por los permisos y las listas de control de acceso ugo/rwx estándar, la Agencia de Seguridad Nacional de los Estados Unidos (NSA) ideó un fuerte> Método 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 acceda o realice otras operaciones en objetos del sistema (como archivos, directorios, puertos de red, etc.) con el menor permiso posible, a la vez que permite modificaciones posteriores de 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 para establecer límites configurando perfiles para el uso seguro de la aplicación.

En CentOS 7 , SELinux está incorporado en el núcleo mismo y está habilitado en el modo Cumplimiento 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 elementos esenciales de SELinux y AppArmor y cómo utilizar una de estas herramientas para su beneficio en función de su distribución elegida.

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

Security Enhanced Linux puede operar de dos maneras diferentes:

  1. Enforcing: SELinux denies access based on SELinux policy rules, a set of guidelines that control the security engine.
  2. Permissive: SELinux does not deny access, but denials are logged for actions that would have been denied if running in enforcing mode.

SELinux también puede ser deshabilitado. Aunque no es un modo de operación en sí, sigue siendo una opción. Sin embargo, aprender a usar esta herramienta es mejor que ignorarlo. ¡Tenlo en mente!

Para mostrar el modo actual de SELinux , use getenforce . Si desea cambiar el modo de operación, use setenforce 0 (para configurarlo en Permisivo ) o setenforce 1 ( Cumplimiento ).

Como este cambio no sobrevivirá al reinicio , deberá editar el archivo /etc/selinux/config y configurar la variable SELINUX en imponente , permisivo o deshabilitado para lograr persistencia en los reinicios:

En una nota al margen, si getenforce devuelve Inhabilitado, 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 (desde hacer cumplir a permisivo o al revés) para solucionar problemas de una aplicación que se está portando mal o no está funcionando como se esperaba. Si funciona después de configurar SELinux en el 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 tratar con SELinux son:

  1. Changing the default port where a daemon listens on.
  2. Setting the DocumentRoot directive for a virtual host outside of /var/www/html.

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

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

Port 9999

Después de intentar reiniciar el servicio y verificar su estado, veremos que no se pudo iniciar:

# systemctl restart sshd
# systemctl status sshd

Si echamos un vistazo a /var/log/audit/audit.log , veremos que se impidió que sshd se inicie en el puerto 9999 por SELinux porque es un puerto reservado para el servicio JBoss Management (los mensajes de registro de SELinux incluyen la palabra "AVC" para que puedan ser fácilmente identificado a partir de 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 no lo haremos. Veremos que hay una manera para que SELinux y sshd escuchen en un puerto diferente, para vivir juntos en armonía. Asegúrese de tener instalado y ejecutado el paquete policycoreutils-python :

# yum install policycoreutils-python

Para ver una lista de los puertos donde 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 utilizar esta máquina específica para ningún servicio relacionado con JBoss, podemos modificar la regla existente de SELinux 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 se asignó correctamente o las opciones de -lC (abreviatura de lista personalizada):

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

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

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

DocumentRoot “/websrv/sites/gabriel/public_html”

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

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

Al igual que en el ejemplo anterior, puede usar el siguiente comando para verificar que este es realmente 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 recursivamente 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 entre en vigencia inmediatamente), haga lo siguiente:

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

Ahora deberías poder acceder al directorio:

# wget http://localhost/index.html

Para obtener más información sobre SELinux, consulte la Guía de administración y SELin de Fedora 22.