Gentoo Logo

Manual de SELinux para Gentoo

Contenido:

  • Introducción a Gentoo/Hardened SELinux
    Esta parte cubre SELinux y cómo está posicionado en el proyecto Gentoo/Hardened.
    1. Mejorando la seguridad en Linux
      La seguridad consiste en algo más que habilitar un cierto marco de trabajo o instalar un núcleo Linux diferente. Es una forma de trabajar y administrar su sistema Gentoo Linux. Aquí cubrimos algunas buenas prácticas (genéricas), y entonces trabajamos en el llamado Control de Acceso Obligatorio (MAC) y cómo SELinux cubre este hueco.
    2. Conceptos detrás de SELinux
      Para poder trabajar correctamente con SELinux, es vital que comprenda algunos conceptos como dominios, transiciones de dominios y contextos de ficheros. Sin una comprensión básica de estos aspectos, será dificil comprender cómo funcionan las directrices de SELinux y cómo actuar en caso de que las cosas no vayan bien.
    3. Recursos de SELinux
      Para familiarizarse mejor con SELinux, existen muchos recursos en Internet. En este capítulo ofreceremos una vista rápida de los variados recursos así como lugares donde se puede obtener más ayuda en la lucha contra SELinux.
  • Usando SELinux Gentoo/Hardened
    Dejando atrás las cuestiones teóricas, abordamos ahora la instalación de Gentoo/Hardened con un núcleo SELinux así como las herramientas SELinux tools.
    1. Instalación de Gentoo SELinux / Conversión
      Para poner en marcha SELinux en Gentoo/Hardened, necesitará en primer lugar instalar Gentoo con el perfil Hardened apropiado (o convertir su perfil actual al perfil Hardened), a continuación puede actualizar su sistema para convertirlo en uno gestionado por SELinux. En este capítulo le guiaremos a través de este proceso.
    2. Configurar SELinux para adaptarlo a sus necesidades
      Con SELinux ahora "instalado" y habilitado (aunque funcionando en modo permisivo), podemos configurarlo para que se adapte a nuestra necesidades particulares. Después de todo, SELinux es un sistema de Control de Acceso Obligatorio en el cual, como administrador de seguridad, pude definir lo que está permitido y lo que no.
    3. Órdenes en SELinux
      Demos un paso atrás y conozcamos algunas otras órdenes. Cubrimos la mayoría de ellas en la sección previa y ahora profundizaremos un poco más en su sintaxis, características y faltas más potenciales.
    4. Permisivo, no confinado, deshabilitado o lo que no...
      Su sistema puede encontrarse en muchos estados SELinux. En este capítulo, el ayudaremos a cambiar entre varios estados y directrices.
    5. Modificar la directriz de SELinux en Gentoo Hardened
      Gentoo Hardened ofrece un directriz por defecto, sin embargo, puede que ésta no le permita hacer lo que desea (o permita demasiado). En este capítulo le contaremos como puede ajustar la directriz de Gentoo e incluso crear la suya.
    6. Solucionando problemas con SELinux
      Todo lo que haga un humano puede y de hecho, fallará. En este capítulo intentaremos mostrar todos los problemas potenciales con los que se puede encontrar y cómo resolverlos.
    7. Historial de cambios
      A medida que la documentación evoluciona con la tecnología, este manual sufrirá sus cambios correspondientes. Para permitir a los usuarios que ya utilizand SELinux, verificar si hay cambios de los que necesitan tener conocimiento, este capítulo muestra la lista de cambios en orden cronológico.

A. Introducción a Gentoo/Hardened SELinux

1. Mejorando la seguridad en Linux

1.a. Introducción

Una bienvenida amigable

Bienvenido al manual de SELinux para Gentoo. Con este recurso queremos presentarle rápidamente la implementación de SELinux y las directrices implicadas. Parte de esta presentación consiste en ayudarle a comprender porqué se creó SELinux y qué conceptos se esconden detrás de los parches de SELinux. Cubriremos los conceptos más importantes de SELinux, las directrices de referencia que utiliza Gentoo Hardened y desarrollaremos el trabajo con algunas herramientas de SELinux.

El propósito de este libro no es explicar en detalle el funcionamiento del propio SELinux. Existen muchas referencias disponibles en Internet y en muchos libros que le ayudarán con SELinux. En lugar de esto, nos centraremos en la integración de SELinux en Gentoo Hardened. Desde luego, le ofreceremos una rápida introducción a SELinux para que pueda comprender cómo trabaja, lo que es, y le ayudaremos a identificar las acciones que necesita realizar para asegurar su sistema usando las herramientas de SELinux.

1.b. Asegurando Linux

Seguridad en general

La seguridad se ve a menudo como un concepto vago. ¿Qué es la seguridad en general? ¿Cómo se mide? ¿Qué beneficio se obtiene y cómo asegurarse de no poner demasiado esfuerzo en asegurar su sistema?

Bien, los fanáticos de la seguridad le contarán que no existe otra cosa salvo el exceso de seguridad. Si se implementa de forma correcta, la seguridad no restrige la funcionalidad o el rendimiento. No le da demasiado trabajo para realizar sus tareas. Pero implementar la seguridad de forma apropiada es una tarea diferente y que conlleva mucho tiempo. Esta es la razón por la que en muchas ocasiones se escucha que la seguridad es tan buena como su administrador.

Entonces, ¿Cómo puedo velar por la seguridad?. Una buena práctica consiste en definir sus metas en lo que a seguridad se refiere. Haga una lista de que lo que quiere conseguir y porqué lo quiere hacer. Haciendo un seguimiento de las amenazas que quiere minimizar, podrá construir un modelo de seguridad que es el adecuado para su entorno. Estas amenazas pueden ser muy pretenciosas, como por ejemplo "Asegurarse de que nadie pueda violar nuestras medidas de seguridad".

En el caso de un sistema Linux funcionando con SELinux, esto podría significar que desea que nadie o nada, salvo los procesos de confianza, puedan escribir en ficheros críticos del sistema, como por ejemplo, la(s) imagen(es) del núcleo, configuración del gestor de arranque, las contraseñas y el propio binario de SELinux con las directrices.

Control de acceso

Un control de acceso decente de un sistema (o grupo de sistemas), asegura que únicamente se permite acceso a las personas o procesos autorizados a los recursos con los que quieren trabajar.

Antes de que pueda implementar un control de acceso al sistema, necesitará obtener la autorización adecuada. Si sus esquemas de autenticación fallan, su sistema de control de acceso al sistema podría no diferenciar a los usuarios legítimos de los maliciosos.

La autenticación de los usuarios en los sistemas Linux se realiza a través de PAM (Módulos de Autenticación Enchufables), un potente mecanismo para integrar esquemas múltiples de autenticación de bajo nivel en una interfaz de alto nivel.

Sin embargo, la autorización para el uso de los recursos, se realiza a veces a través de un esquema simple de permisos. La mayoría de los recursos no están ocultos por defecto, aunque existen parches y actualizaciones (tales como las ofrecidas por las fuentes del núcleo Gentoo Hardened con parches grSecurity que incluyen soporte para este tipo de medidas). Puede ocultar la existencia de archivos en todo el sistema de ficheros asegurándose de que el directorio en el que residen no es legible ni "ejecutable" por cuentas no autorizadas.

Este esquema de permisos por defecto tiene algunos inconvenientes importantes. No le permite definir autorizaciones flexibles (únicamente permite autorizaciones a tres niveles: propietario, grupo propietario y cualquier otra cuenta) y además está limitada a los permisos lectura/escritura/ejecución (aunque algunos atributos adicionales están disponibles hoy en día).

Otro problema es que el esquema de permisos es discrecional, lo que significa que los usuarios y procesos pueden cambiar las directrices de seguridad.

Este esquema de permisos es suficiente Para la mayoría de usuarios y ha demostrado ofrecer un método adecuado para gestionar las autorizaciones de acceso. Si embargo, los inconvenientes que presenta han resultado ser un agujero importante en lo que Linux ofrece.

1.c. Control de acceso obligatorio

Entre en SELinux

Si el control de acceso discrecional, abreviado DAC, mencionado arriba no es suficiente (y si es riguroso con la seguridad, no lo encontrará suficiente), entonces necesitará un sistema Control de Acceso Obligatorio o MAC.

Cuando se usa un sistema MAC, se necesita permitir explícitamente las actividades que un proceso quiere realizar en un recurso. Esto ofrece mayor granularidad con los permisos y los recursos. A menudo ofrecen no sólo soporte para ficheros, sino también para zócalos (sockets), puertos, segmentos de memoria, colas, procesos, servicios del núcleo, llamadas al sistema, dispositivos, sistemas de ficheros y mucho más. La granularidad de las actividades soportadas es también muy grande. Para los ficheros, esto incluye: añadir, crear, ejecutar, escribir, enlazar, llamadas ioctl, obtener atributos (getattr), dar valor a atributos (setattr), lectura, renombrado, bloqueo,... mientras que para los zócalos (sockets) estos pueden ser: añadir, asociar (bind), conectar, crear, escribir, enviar a, aceptar,... También, cuando se utiliza un sistema MAC, ningún usuario ni proceso puede manipular las directrices de seguridad por sí mismo: lo que el administrador ha concedido no puede ser revocado.

Aquí es donde SELinux entra en juego. SELinux es una característica del núcleo Linux que implementa, entre otras cosas, un sistema MAC para controlar y gobernar el acceso a varios recursos. Usa un esquema de permisos de denegación por defecto, de forma que se necesita conceder explícitamente el acceso que ha solicitado un proceso.

SELinux permite igualmente un modelo de permisos más fino encima del sistema tradicional DAC (el cual se usa también mientras SELinux está en funcionamiento; en otras palabras: si el sistema tradicional no permite ciertas actividades, éstas no serán permitidas incluso si las directrices de SELinux permiten la acción).

¿Qué es SELinux?

Para dar soporte a este modelo fino de permisos, es lógico pensar que se deben realizar cambios al núcleo Linux. Sí, gracias a la interfaz del núcleo Linux LSM (Módulos de Seguridad de Linux), el soporte para SELinux se añadió de forma muy sencilla desde el comienzo de las series 2.6 del núcleo. SELinux se ha integrado en el árbol principal del núcleo. Sin embargo, el soporte de SELinux y su utilización son dos cosas muy diferentes.

Para identificar adecuadamente los recursos, SELinux necesita asignar etiquetas a estos recursos. Cuando los recursos están en memoria, se realiza principalmente en el núcleo Linux, sin embargo, para recursos persistentes como ficheros, estas etiquetas deben localizarse en algún lugar. En SELinux, se ha elegido usar atributos extendidos del fichero (que son almacenados en el propio sistema de ficheros). La ventaja de este enfoque es que la etiqueta permanece junto al fichero incluso si éste cambia de nombre. Por el contrario, una desventaja de este enfoque es que el sistema de ficheros debe soportar estos atributos extendidos, los cuales no todos los sistemas de ficheros poseen (o tienen activados).

SELinux también utiliza roles para gestionar el acceso a los recursos. A un usuario que no tiene el rol de acceso a la administración del sistema no se le debe permitir ejecutar cualquier actividad de administración del sistema incluso si es capaz de escalar sus privilegios (por ejemplo usando una aplicación con la capacidad set-uid). Para el soporte de roles, SELinux requiere cambios en los servicios de autenticación (PAM) y necesita almacenar en algún lugar las definiciones de los roles y las autorizaciones.

Aparte del soporte en el núcleo y las etiquetas asignadas a los recursos en el sistema de autorización, SELinux requiere también herramientas específicas para consultar y manipular las etiquetas, gestión de privilegios (por ejemplo la herramienta sudo), servicios del sistema (como SysVInit) etc. Esto se traduce en un conjunto de parches que se aplican a estas herramientas (y más) los cuales no son siempre parte del código fuente principal de la aplicación.

Gentoo Hardened y SELinux

Gentoo Hardened ofrece SELinux integrado en la distribución. Cuando se selecciona soporte para SELinux, Gentoo Hardened aplicará los parches necesarios a las aplicaciones y le ayudará a (re)etiquetar sus ficheros y otros recursos para que puedan ser gestionados por SELinux. Gentoo Hardened también integra soporte SELinux en Portage, permitiendo que los nuevos ficheros que se instalen sean etiquetados automáticamente y que se utilice un entorno inofensivo (sandbox) para la construcción segura de los paquetes.

Aparte del soporte tecnológico puro, esperamos que encuentre los documentos de soporte, guías, experiencia y soporte en línea necesarios para usar SELinux en Gentoo. No dude en entrar y decir ¡hola! en el canal de chat #gentoo-hardened de la red IRC en Freenode o en nuestra lista de correo.

Si piensa que SELinux es apropiado para sus pretensiones y quiere probarlo usando Gentoo Hardened, por favor, continúe leyendo. En el próximo capítulo le informaremos de como se ha "diseñado" la seguridad en SELinux y cómo está estructurada conceptualmente. En capítulos posteriores le ayudaremos con el lenguaje de autorización y las directrices "base" con las que la mayoría de las distribuciones comienzan y finalmente le ayudaremos a instalar, ejecutar y gestionar un sistema SELinux con Gentoo Hardened.

2. Conceptos detrás de SELinux

2.a. Introducción

Conceptos detrás de SELinux

Debido a que SELinux es un sistema MAC, probablemente se habrá dado cuenta de que la gestión de los permisos y privilegios basados en SELinux va a ser un poco más complicada que la gestión de privilegios en un control de acceso discrecional que es el que se utiliza generalmente en un sistema Linux. Algo importante a tener en cuenta es que SELinux trabaja encima del sistema DAC que es el que utiliza todo el mundo en Linux. Siendo un administrador de sistemas, necesitará familiarizarse con algunos conceptos y estructuras que SELinux ha colocado para gestionar el acceso a estos sistemas.

El propósito de este capítulo es La descripción de estos conceptos. Daremos ejemplos de estos conceptos en un sistema Gentoo Hardened con SELinux habilitado. Sin embargo, no se preocupe si el uso de algunas órdenes en particular no se detalla suficientemente. Se muestran únicamente como ejemplos (lo que se aprenda de esto es más importante) y será discutido más abajo en este documento.

Directrices de SELinux

Dentro de Gentoo (y también dentro de otras distribuciones), SELinux es soportado por varios niveles de directriz. Estos son, en orden ascendente en complejidad (significando que pueden ofrecer mayor seguridad pero que son más difíciles de gestionar):

  1. targeted es una directriz en la que los servicios que utilizan la red (demonios) están confinados (los procesos solo pueden ejecutar aquellas acciones que estén definidas en la directriz). Sin embargo, otras aplicaciones corren en el llamado unconfined (no confinado), lo que indica que hay muy pocas restricciones para estos procesos.
  2. strict es una directriz en la que todos los procesos están confinados. No existen dominios no confinados. En otras distribuciones, esta es considerada la directriz targeted pero sin la definición de dominio no confinado.
  3. multi-category security es una directriz en la que los dominios (confinados) pueden ser categorizados (clasificados), permitiendo que múltiples procesos corran en diferentes instancias de un dominio confinado.
  4. multi-level security es una directriz en la que existen reglas relativas a la sensibilidad de dominios y recursos. Esto permite una directriz de flujo de información "adecuada" (asegurándose de que la información sensible no se filtra a través de dominios con menores privilegios). Conceptualmente, esto se puede comprender mejor si se consideran los niveles de sensibilidad Público, Interno, Confidencial, Estrictamente confidencial, etc.

Cuando se utiliza Gentoo Hardened, todas estas directrices están disponibles. Sin embargo el desarrollo se centra principalmente en strict y mcs (multi-category security). Se asume que la directriz targeted funciona si funciona la directriz strict aunque sabemos que la directriz mls (multi-level security) no está preparada para el uso en producción.

Nota: Para aclarar posibles confusiones, especialmente cuando se intenta buscar soporte fuera de Gentoo: nuestra implementación "strict" no es la implementación que era "strict" hasta el año 2008. El antiguo significado de "strict" involucraba una implementación diferente de la directriz.

2.b. Contextos de seguridad

Usuarios, Roles y Dominios

Uno de los primeros conceptos con los que debe familiarizarse es el de contexto de seguridad. Se trata de un estado que se asigna a un recurso de modo que identifica únicamente qué concesiones (permisos) se dan al recurso. Este contexto es extremadamente importante para SELinux ya que es la definición en la cual basa sus permisos (concesiones o revocaciones). Cuando un recurso no tiene un contexto asignado, SELinux intentará darle un contexto de seguridad por defecto, el cual, considerando la filosofía del menor privilegio posible, tiene pocos permisos para realizar cualquier acción.

En el marco de SELinux, este contexto de seguridad se muestra usando de tres a cinco definiciones, dependiendo del tipo de directriz que se esté utilizando:

user
El usuario SELinux (no el mismo que el usuario técnico de Linux/Unix) asignado al recurso.
role
El rol SELinux en el que el recurso trabaja actualmente.
type
El tipo asignado al recurso, la clave para las reglas de reforzamiento de SELinux.
sensitivity
Este es un nivel dado a un recurso informado al sistema sobre la sensibilidad de este recurso. La sensibilidad es algo relacionado con Publico, Interno, Restringido, Confidencial, Estrictamente confidencial, ... Los niveles de sensibilidad están soportados únicamente por las directrices MLS.
category
Se trata de una instanciación específica de un recurso. Permite la segregación de recursos incluso si son del mismo tipo. Se hablará más acerca de las categorías más adelante. Las categorías están soportadas únicamente por las directrices MLS y MCS.

Se dará más información sobre estas definiciones en particular a lo largo de este capítulo.

Como ejemplo, echemos un vistazo al contexto de seguridad de un usuario que ha ingresado en el sistema:

Listado de Código 2.1: Obtener el contexto de seguridad de un usuario que ha ingresado en el sistema

~$ id -Z
staff_u:staff_r:staff_t

En este caso, el usuario está identificado como el usuario SELinux staff_u, que actualmente tiene el rol staff_r y está asignado al tipo staff_t. Las acciones que se permiten a este usuario están basadas en este contexto de seguridad. También, observará que únicamente se muestran tres identificadores. Esto es debido a que se ha tomado el ejemplo de un sistema con directriz strict (o targeted). El siguiente ejemplo da el mismo resultado pero para una sistema con directriz MCS.

Listado de Código 2.2: Obteniendo el contexto de seguridad de un usuario que ha ingresado en un sistema con directriz MCS

~$ id -Z
staff_u:staff_r:staff_t:s0-s0:c0.c1023

Aquí, el usuario está corriendo con el nivel de sensibilidad s0 (el cual, en un sistema con directriz MCS, el el único disponible) y con una categoría c0 hasta c1023 (inclusive). Sin embargo, observe que en un sistema con directriz MCS, las categorías son opcionales, por lo que deberá ver una salida del tipo: staff_u:staff_r:staff_t:s0.

Directrices de control de acceso

Como ya se ha mencionado, estos contextos de seguridad se usan como base de las reglas de permisos. Lo que hace SELinux es comprobar el contexto de seguridad de la fuente (por ejemplo un proceso) y del destino (por ejemplo un fichero que el proceso necesita leer). Entonces se comprueba si la operación solicitada (lectura) está permitida entre estos dos contextos. Recuerde que SELinux trabaja encima del sistema de permisos estándar usados en Linux. Si un proceso no puede, en principio, leer un fichero, ni siquiera se consulta a SELinux.

Hasta ahora, el contexto de seguridad define el estado de un recurso, sin embargo, no hemos hablado de los recursos en sí. En el marco de SELinux, los tipos de recursos están definidos como clases de objetos. Ejemplos muy comunes son file o dir. SELinux también gestiona clases como filesystem, tcp_socket, process, sem (semáforos) y mucho más.

En cada clase de objeto, se declara un conjunto de permisos, los cuales son aplicables a un recurso de esta clase de objeto. Por ejemplo, la clase de objeto process soporta cuanto menos los siguientes permisos:

Listado de Código 2.3: Permisos soportados para un recurso 'process'

~# ls /selinux/class/process/perms
dyntransition  getcap      rlimitinh     setpgid        siginh
execheap       getpgid     setcap        setrlimit      sigkill
execmem        getsched    setcurrent    setsched       signal
execstack      getsession  setexec       setsockcreate  signull
fork           noatsecure  setfscreate   share          sigstop
getattr        ptrace      setkeycreate  sigchld        transition

La regla más común de SELinux para el control de acceso (allow) se describe de la siguiente forma:

Listado de Código 2.4: La sentencia SELinux allow

allow ACTOR  TARGET:CLASS PRIVILEGE;
      +-+-+  +-+--+ +-+-+ +---+---+
        |      |      |       `- Permiso a conceder (como "write")
       |      |      `- Clase a la que se da el permiso (como "file")
       |      `- Recurso (etiqueta) en la que el permiso es válido (como "portage_conf_t")
       `- Actor (dominio) que obtiene el privilegio (como "sysadm_t")

Echemos un vistazo a un pequeño ejemplo que explica las reglas de permisos y cómo las utiliza SELinux. El usuario ejemplo está en el contexto staff_u:staff_r:staff_t y desea escribir en su propio directorio. Lo lógico sería que se le permitiera esta acción. No se preocupe por las órdenes mostradas aquí, las discutiremos en detalle más abajo en este mismo documento.

Listado de Código 2.5: Comprobar si un usuario puede escribir en su propio directorio home

(Muestra el contexto de seguridad para el directorio home del usuario)
~$ ls -dZ ${HOME}
staff_u:object_r:user_home_dir_t  /home/swift

(Busca la regla que permite al tipo staff_t escribir en un directorio con el tipo user_home_dir_t type)
~$ sesearch -s staff_t -t user_home_dir_t -c dir -p write -A
Found 1 semantic av rules:
  allow staff_t user_home_dir_t : dir { ioctl read write create ... };

Como era de esperar, el contexto de seguridad del usuario (para ser más específico, el dominio en el que reside) tiene acceso de escritura al dominio de los directorios destino. La noción de dominio aparece frecuentemente en la documentación de SELinux y se refiere al tipo asignado a un proceso. Por cierto, como los ficheros no tienen ningún rol, SELinux les asigna el rol por defecto object_r.

Ahora echemos un vistazo al siguiente ejemplo. Nuestro usuario, que pertenece al grupo portage, quiere escribir en el directorio /var/tmp/portage:

Listado de Código 2.6: Comprobar si un usuario puede escribir en el directorio /var/tmp/portage

~$ id -a
uid=1001(swift) gid=100(users) groups=100(users),...,250(portage),...
~$ ls -ldZ /var/tmp/portage
drwxrwxr-x. 3 portage portage  system_u:object_r:portage_tmp_t 4096 Dec  6 21:08 /var/tmp/portage

Desde le punto de vista de los permisos estándar de Linux, el usuario tiene permiso para escribir. Pero, ¿Le permitirá SELinux hacerlo?

Listado de Código 2.7: Intentar escribir en /var/tmp/portage

~$ sesearch -s staff_t -t portage_tmp_t -c dir -p write -A
~$
(Observe que no se obtiene ninguna información)
~$ touch /var/tmp/portage/foo
touch: no se puede efectuar `touch' sobre «/var/tmp/portage/foo»: Permiso denegado

Como SELinux no pudo encontrar una regla que permitiera al dominio staff_t escribir en cualquier directorio etiquetado con el tipo portage_tmp_t type, se denegó el acceso.

2.c. Forzado de tipos / Tipos de dominio

Tipos y dominios

Para explicar como funcionan las reglas de permisos y como se fuerzan mediante los contextos de seguridad, comencemos con la última definición en el contexto (el tipo) y trabajemos hacia los roles y usuarios.

  • Un tipo SELinux es una etiqueta en particular que se asigna a un recurso. Por ejemplo, la orden passwd está etiquetada con el tipo passwd_exec_t.
  • Un dominio SELinux es el estado de seguridad de un proceso e identifica los derechos y permisos que posee. Normalmente, nos referiremos a él por su declaración de tipo. Por ejemplo, el dominio para una orden passwd es passwd_t.

Las reglas que identifican las acciones permitidas para un dominio ya se han descrito anteriormente, las citamos de nuevo:

Listado de Código 3.1: Reglas estándar de las directrices SELinux

allow <src_domain> <dst_type> : <class> { permiso [ permiso [ ... ] ] } ;

Un ejemplo del dominio passwd_t podrían ser los permisos concedidos entre el dominio passwd_t y el tipo shadow_t (usado por el fichero /etc/shadow).

Listado de Código 3.2: Concesiones entre passwd_t y shadow_t

allow passwd_t shadow_t : file { ioctl read write create ... } ;

Esta sintaxis de permisos es muy potente, pero también complicada. Para tener un sistema seguro en el que se permite un comportamiento normal, necesitará ajustar finamente estas reglas para todas y cada una de las aplicaciones (y de igual forma para los dominios) que desea albergar en su sistema. Dar permisos de forma extensiva a un dominio en un tipo en particular, puede resultar en la pérdida de eficiencia e incluso de efectividad.

Para soportar reglas de concesión de forma más sencilla, SELinux permite el agrupamiento de tipos usando los atributos de tipos. Por ejemplo, el atributo exec_type agrupa todos los tipos que se asignan a los ficheros ejecutables (como bin_t, ssh_exec_t, ...), mientras que el atributo file_type agrupa todos los tipos que se asignan a ficheros regulares. Aunque esto pueda simplificar la gestión de las reglas, puede resultar en que se asignen sin quererlo más permisos de los que se desean asignar.

Transiciones de dominio

Hasta aquí hemos hablado de tipos, definiciones de dominios y sus permisos. Hemos comentado previamente que los permisos están basados en el dominio en el que reside un proceso. Pero, ¿cómo llega un proceso a ser parte de un dominio? Podrá pensar que esto ocurre de una forma prefijada (ejecutar la orden passwd conllevaría que el proceso se asociara al dominio passwd_t), de hecho, esto se realiza mediante la combinación de tres privilegios muy específicos que deben ser concedidos:

  1. Se debe permitir al dominio actual la transición a otro dominio.
  2. El dominio destino debe tener un punto de entrada, que es un ejecutable, al cual se le permite arrancar en el dominio.
  3. El dominio fuente debe tener permisos de ejecución (en el dominio) sobre ese ejecutable.

Importante: El hecho de que no se permita la transición, no significa que no se pueda ejecutar el binario. El binario puede ser ejecutado, pero no lo hará dentro del dominio destino. En lugar de eso, heredará el dominio del ejecutor y por lo tanto los permisos y derechos de ese dominio.

Usando estas reglas, el administrador de la seguridad de un sistema puede controlar de forma más específica quién y bajo qué condiciones se pueden realizar acciones particulares.

2.d. Roles y derechos

El rol de un rol

Los dominios y las reglas de dominio expuestas anteriormente son bastante potentes. Sin embargo, SELinux ofrece mucho más. Después de todo, debe ser posible denegar el acceso a dominios particulares a usuarios no autorizados. Un requisito es, desde luego, no permitir transiciones desde el dominio del usuario a un dominio restringido, pero, ¿cómo se permite a un conjunto de usuarios mientras que se deniega a otro?

Presentaremos los roles. Usando roles, puede indicarle a SELinux qué dominios se permiten para un rol y cuales no. Un ejemplo podría ser el dominio ifconfig_t. Este dominio tiene los derechos para cambiar las definiciones de las interfaces de red, lo cual es algo que no debe permitir a sus usuarios. Y, de hecho, si pudiera verificarlo, SELinux no permite asignar el rol de usuario user_r al dominio ifconfig_t.

Listado de Código 4.1: Comparación de user_r y sysadm_r para el dominio ifconfig_t

~$ seinfo -ruser_r -x
  user_r
    Dominated Roles:
      user_r
    Types:
      ...
~$ seinfo -rsysadm_r -x
  sysadm_r
    Dominated Roles:
      sysadm_r
    Types:
      ...
      ifconfig_t
      ...

Importante: De nuevo, el hecho de no poder asociar un dominio, no significa que el rol user_r no pueda ejecutar el binario ifconfig. Puede, pero ejecutará este binario en su propio dominio (user_t). Este dominio no tiene derechos para manipular la interfaces de red (sin embargo puede leer información del interfaz aunque con información limitada).

Los roles se usan a menudo en sistemas de control de acceso para agrupar permisos en un solo conjunto funcional (el rol), el cual se puede asignar a individuos (cuentas). Por ejemplo, estos sistemas de control de acceso crean roles para contables, operadores, administradores,... y conceden los privilegios apropiados a estos roles. Entonces, a estos usuarios se les asigna uno (o a veces varios) roles y los usuarios heredan los permisos asignados a estos roles.

En SELinux, se usa esta idea (se usan roles para diferenciar privilegios de forma funcional), sin embargo se implementa de forma distinta: a los roles se le asignan dominios destino en los que se permite que un rol "pueda entrar". Los permisos permanecen asignados a los dominios.

Transiciones de rol

Los usuarios (y los procesos) pueden cambiar de rol. En SELinux se permite, pero únicamente cuando se concede la posibilidad de cambiar. Por defecto, las directrices de SELinux usadas en Gentoo Hardened ofrecen cinco roles en un sistema SELinux:

object_r
El rol object_r es el único rol disponible por defecto en SELinux. Normalmente solo se asigna a recursos en los que no se puede obtener ningún valor o rendimiento del sistema de roles (como en ficheros y directorios).
system_r
El rol system_r se usa para servicios del sistema con muchos privilegios. Se permite al rol system_r cambiar a cualquier otro rol definido por "defecto". Ningún rol excepto sysadm_r puede cambiar al rol system_r.
sysadm_r
El rol sysadm_r se usa para actividades de administración del sistema. Se permite al rol sysadm_r cambiar a cualquier otro rol definido por "defecto". Únicamente se permite a los roles system_r y staff_r cambiar al rol sysadm_r.
staff_r
El rol staff_r se asigna a los operadores del sistema que deberían tener derechos para realizar tareas de administración. Al rol staff_r se le permite cambiar únicamente al rol sysadm_r. Solo sysadm_r y system_r pueden cambiar al rol staff_r.
user_r
El rol user_r se asigna a usuarios estándar y sin muchos privilegios. No se permite la transición a ningún otro rol; únicamente se permite a los roles sysadm_r y system_r cambiar al rol user_r.

Nota: Los roles por "defecto" son: user_r, staff_r, sysadm_r y system_r. Si se crean roles adicionales, éstos no serán parte del los roles por "defecto".

Usando estas definiciones, un usuario dentro del rol user_r nunca podrá ejecutar ifconfig en el dominio ifconfig_t. El uso de la palabra nunca es importante: no podrá, incluso si el usuario puede usar la cuenta root mediante sudo o cualquier otra orden que permita ejecutar ifconfig en el dominio ifconfig_t, porque, a pesar de que ha ejecutado sudo, el usuario está utilizando el rol user_r.

Usuarios de SELinux

Un usuario de SELinux no es lo mismo que un usuario Linux. Mientras que se puede cambiar de una cuenta de usuario estándar de Linux a otra usando órdenes como su o sudo, un usuario SELinux no se puede cambiar. Incluso cuando ejecute con éxito sudo, su usuario SELinux seguirá siendo el mismo.

Cuando observe un sistema gestionado con SELinux, podrá ver que ese sistema no tiene muchos usuarios SELinux. Por ejemplo, la configuración por defecto de Gentoo Hardened define los usuarios root, user_u, staff_u, sysadm_u y system_u y en muchos sistemas nunca se crea ningún usuario SELinux más. En este caso, ¿la ventaja mencionada arriba sobre usuarios SELinux (una vez que el usuario ingresa en el sistema, éste no puede cambiar a otro usuario SELinux) es la única?

Bien, no. Los usuarios SELinux también se usan para categorizar las cuentas que tienen el permiso de usar un rol en particular.

Listado de Código 4.2: Usuarios SELinux y sus roles asociados

~# semanage user -l
SELinux User    SELinux Roles

root            staff_r sysadm_r
staff_u         staff_r sysadm_r
sysadm_u        sysadm_r
system_u        system_r
user_u          user_r

Los usuarios Linux estándar están vinculados a estos usuarios SELinux:

Listado de Código 4.3: Usuarios Linux y sus vínculos con usuarios SELinux

~# semanage login -l
Login Name          SELinux User

__default__         user_u
root                root
swift               staff_u

En este ejemplo, únicamente el nombre de los usuarios Linux swift (a través de staff_u) y root (a través del usuario SELinux root) podrán eventualmente trabajar en el rol sysadm_r. El resto de cuentas serán vinculadas por defecto al usuario user_u (y al rol user_r).

Esto se aplica únicamente a los usuarios interactivos. Los procesos que se lanzan mediante un guión de inicio o de cualquier otra forma no se asocian con el usuarios SELinux user_u: dependiendo del contexto de seguridad de los procesos que los lancen, podrán cambiar a cualquier otro. Desde luego, si el contexto de seguridad del proceso que los está lanzando es user_u:user_r:user_t entonces no podrán transformarse en otro más que user_u:user_r:* con * un dominio soportado por el rol user_r.

Los usuarios SELinux se utilizan también para implementar el Control de Acceso Basado en Usuario o UBAC. Esta funcionalidad de SELinux permite a los dominios conocer a los usuarios: un proceso corriendo en el contexto de un usuario SELinux en particular puede, por ejemplo, únicamente trabajar con ficheros del mismo usuario SELinux. Esto ofrece un método de acceso más fino ya que ese proceso podrá correr en un dominio que tenga acceso al dominio del fichero, pero no podrá escribir en el fichero ya que el usuario SELinux es distinto.

Actualmente SELinux en Gentoo Hardened soporta ambas directrices y también el soporte sin UBAC, aunque se recomienda encarecidamente el uso de UBAC. Esto se controla usando el ajuste USE ubac.

2.e. Seguridad multinivel / Seguridad multicategoría

Introducción

Además de la característica para forzar los tipos, SELinux también ofrece soporte MLS (seguridad multinivel) y MCS (seguridad multicategoría). Esto permite a los administradores definir una directriz de confidencialidad jerárquica. Por ejemplo, puede asegurarse de que un proceso o usuario en un determinado dominio de seguridad y nivel, pueda escribir en ficheros del mismo nivel (o superior), o leer ficheros del mismo nivel (o inferior), pero no puede escribir en ficheros de un nivel inferior. Esto permite a los administradores implementar un nivel de seguridad jerárquica pública/interna/confidencial/estrictamente confidencial para los ficheros.

Aunque la implementación de MLS podría realizarse usando las reglas de forzado de tipos que hemos explicado previamente, hacerlo así podría desembocar en una colección inmanejable de tipos y permisos. La implementación MLS facilita esto.

Seguridad Multinivel

Es la más flexible, pero la más complicada de gestionar. El método que ofrece SELinux es MLS, o Seguridad Multinivel (Multi-Level Security). Cuando se utiliza este tipo de directriz, los administradores de seguridad pueden asignar etiquetas de sensibilidad a los recursos y definir qué dominios (y qué niveles de seguridad) pueden leer o escribir en qué nivel. Un nivel se da siempre como un rango, mostrando el menor y mayor nivel en el que un dominio en particular está corriendo.

Además del nivel de sensibilidad, la directriz MLS soporta categorías por cada nivel. Estas categorías permiten que el administrador de seguridad pueda hacer distintos "contenedores" probablemente independientes para los recursos que sean sensibles. Para dar un ejemplo, el administrador puede soportar los niveles desde Público hasta Estrictamente confidencial y categorías como "Finanzas", "Análisis de Riesgo", "Adquisiciones", "Sistemas TIC", ...

Con estas categorías, uno puede permitir que un rol tenga acceso a todos los niveles de sensibilidad para una categoría en particular (digamos "Sistemas TIC") pero que tenga acceso únicamente a los documentos Públicos e Internos del resto de categorías.

Seguridad Multicategoría

La directriz MCS o Seguridad Multicategoría (Multi-Category Security) es un subconjunto de la directriz MLS. Soporta las distintas categorías, pero sin usar los múltiples niveles de seguridad para los recursos.

El uso de la directriz MCS se ha hecho popular debido aq que es bastante más fácil de gestionar mientras que conserva algo de la flexibilidad presente en la directriz MLS. La directriz MLS se utiliza más para propósitos de negocio (y así, tiene alguna influencia en la propia organización de ese negocio). La directriz MCS es más utilizada en arquitecturas multipropiedad. En una arquitectura multipropiedad, los sistemas son procesos en ejecución para varios clientes a la vez. La categorización permite la separación de estos privilegios a través de estos procesos sin introducir dominios múltiples (los cuáles requerirían el desarrollo de nuevas directrices para cada nuevo cliente al que se quisiera servir).

2.f. Directriz de referencia

Acerca de refpolicy

Como se ha descrito previamente, SELinux utiliza forzado de tipos para describir el estado de su sistema. Esto se realiza dando a cada recurso del sistema (sea un proceso, un puerto de red, un fichero o directorio) un tipo específico y describiendo las reglas de cómo cada tipo puede trabajar con otros tipos.

La gestión de esta directriz no es fácil. Al contrario que otros sistemas MAC, los cuales confían en un modo de aprendizaje y no utilizan definiciones de dominio (éstos en su lugar registran qué órdenes tiene permitidas ejecutar un proceso), una definición correcta SELinux requiere muchas (miles y miles) líneas de permisos.

Para asegurarse de que no se realizan esfuerzos duplicados, y para ayudar a las distribuciones como Gentoo, Fedora, RedHat, Debian, ... en sus esfuerzo de integración de SELinux, se ha lanzado un proyecto denominado The Reference Policy (La directriz de referencia).

Este proyecto, gestionado por Tresys, se usa en la mayoría de las distribuciones que soportan SELinux, incluyendo Gentoo Hardened, Fedora, RedHat Enterprise Linux, Debian, Ubuntu y más. Esta implementación no solo ofrece las directrices modulares que los usuarios están buscando, sino que mejora la experiencia con SELinux añadiendo herramientas de desarrollo adicionales que hacen más fácil trabajar con las directrices de SELinux en su sistema. Las actualizaciones en la directriz de referencia se realizan eventualmente en todas las distribuciones soportadas. Lo mismo sucede con Gentoo Hardened, que trata de utilizar una directriz los más cercana a la de referencia, y envía sus propios parches a la directriz de referencia, lo cual beneficia a toda la comunidad.

El API de la directriz de referencia

Una de las mayores ventajas de la directriz de referencia es su API. Para ayudar a los autores de las directrices, la directriz de referencia utiliza un lenguaje de macros que genera las reglas necesarias de permisión así como otras reglas. Este lenguaje de macros, hace muy fácil añadir derechos a dominios en particular. El API documentado se encuentra en línea, sin embargo, si tiene ajustado USE="doc", se almacenará en su sistema en el momento en que instale y configure SELinux.

Enfoque modular

Otra característica de la directriz de referencia es el uso de modulos. Si quisiera construir todas las reglas en una única directriz (un fichero binario legible por el núcleo Linux, permitieńdole interpretar y forzar las reglas SELinux rules), el fichero enseguida crecería demasiado y se mostraría ineficiente.

En lugar de esto, la directriz de referencia define las reglas en los llamados módulos, los cuales a su vez definen un dominio (por ejemplo portage_t) o más (si están fuertemente relacionados) y los derechos y privilegios que ese dominio necesitaría para funcionar de forma correcta. Cualquier derecho que necesita el dominio respecto a otro dominio debe definirse en las interfaces de ese dominio (mire más arriba), forzando que los módulos sean específicos y manejables.

Listado de Código 6.1: Vista rápida de ejemplo de módulos SELinux instalados

# semodule -l
alsa    1.11.0
apache  2.3.0
audioentropy    1.6.0
dbus    1.15.0
dmidecode       1.4.0
(...)

Al utilizar un enfoque modular, únicamente se necesita cargar la directriz base (la capa del núcleo, así como otras definiciones fundamentales) y los módulos relacionados con ese sistema. Podrá entonces ignorar de forma segura los demás módulos. Esto mejora el rendimiento (directrices más cortas, lo cual conlleva que las reconstrucciones sean un poco menos penosas) y la manejabilidad (definiendo de forma adecuada los límites de las reglas de la directriz).

Configuraciones y condicionales

Pero, ¡un momento!, aún hay más. La directriz de referencia también soporta el uso de booleanos. Éstos son ajustes que un administrador de la seguridad puede habilitar o deshabilitar para cambiar la directriz activa. Los booleanos definidos de forma correcta permiten a los administradores de seguridad ajustar finamente la directriz para sus sistemas.

Listado de Código 6.2: Vista rápida de los booleanos disponibles

# getsebool -a
allow_execheap --> off
allow_execmem --> off
allow_execmod --> off
allow_execstack --> off
allow_gssd_read_tmp --> on
allow_httpd_anon_write --> off

Los booleanos son una parte importante para construir una directriz de referencia genérica que sea utilizable por la mayoría de los usuarios de SELinux. Aunque tiene requisitos específicos (como el hecho de permitir ptrace o deshabilitar execmem) aún pueden utilizar la misma directriz de referencia y definir únicamente aquellos booleanos que se necesiten.

Ficheros de directriz y versiones

La infraestructura de directriz SELinux utilizada (por ejemplo, las capacidades y funcionalidades que ésta ofrece) no se incluyen en su primera versión. Actualmente, las entregas de SELinux utilizan un versión del binario 24 o 26 (dependiendo de la versión del núcleo utilizada).

Listado de Código 6.3: Obtener la versión del binario de la directriz

# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        strict

Cada vez que se añaden funcionalidades o capacidades que requieren cambios a la estructura interna de la directriz compilada, se incrementa este número de versión. A continuación se muestra una vista rápida del histórico de versiones de la directriz, básicamente es una traducción del fichero security/selinux/include/security.h perteneciente al núcleo Linux.

Versión 12
"Antigua API" para SELinux, la cual es ahora obsoleta
Versión 15
"Nueva API" para SELinux, integrada en el núcleo Linux 2.6.0 (hasta la versión 2.6.5)
Versión 16
Añadidas extensiones condicionales a la directriz (2.6.5)
Versión 17
Añadido soporte para IPV6 (2.6.6 - 2.6.7)
Versión 18
Añadido soporte para zócalos (sockets) de enlace de red con ajuste fino (2.6.8 - 2.6.11)
Versión 19
Mejorada la seguridad multinivel (2.6.12 - 2.6.13)
Versión 20
Optimizaciones en el acceso al tamaño de la tabla de vectores (2.6.14 - 2.6.18)
Versión 21
Transiciones en rango de clases de objetos (2.6.19 - 2.6.24)
Versión 22
Capacidades de la directriz (características) (2.6.25)
Versión 23
Modo permisivo para cada dominio (2.6.26 - 2.6.27)
Versión 24
Jerarquía explícita (limites de tipos) (2.6.28 - 2.6.38)
Versión 25
Soporte de transiciones basadas en nombres de fichero (2.6.39)
Versión 26
Soporte de transición de roles para clases no-proceso (3.0)
Versión 27
Soporte para la herencia flexible de los usuarios y roles de los objetos creados (3.5)
Versión 28
Soporte para la herencia flexible del tipo de los objetos creados (3.5)
Versión 29
Soporte al nombrado de restricciones (3.13)

2.g. Siguientes pasos

Qué es lo siguiente

Puede que sea difícil comprenderlos ahora, pero estos conceptos son importantes ya que si algo va mal en su sistema cuando habilite SELinux, pero todo funciona bien cuando se deshabilita, entonces necesitará estudiar más a fondo los contextos de seguridad, las reglas, los tipos y transiciones de dominio para averiguar el motivo del fallo.

En el siguiente capítulo, le ofrecemos información sobre recursos (recursos en línea, libros, preguntas frecuentes, etc.). A continuación, nos sumergeremos en la instalación y configuración de SELinux en su sistema Gentoo Hardened system. Entonces, configuraremos y ajustaremos la directriz SELinux a nuestro antojo.

3. Recursos de SELinux

3.a. Conceptos previos

Introducción a SELinux

3.b. Directriz de SELinux

Referencias relacionadas con la directriz

3.c. Libros

Libros en papel

  • SELinux mediante ejemplos: Usando la seguridad mejorada de SELinux, por Frank Mayer, Karl MacMillan y David Caplan. Prentice Hall, 2006; ISBN 0131963694
  • SELinux: Linux con la seguridad mejorada de código abierto de NSA, por Bill McCarty. O'Reilly Media, 2004; ISBN 0596007167

3.d. Recursos específicos de Gentoo

Gentoo Hardened

Los siguientes recursos son específicos de la implementación de SELinux en Gentoo Hardened.

B. Usando SELinux Gentoo/Hardened

1. Instalación de Gentoo SELinux / Conversión

1.a. Instalar Gentoo (Hardened)

Introducción

Instalar el sistema Gentoo con SELinux no requiere acciones extrañas. Lo que se necesita es instalar Gentoo Linux con el perfil correcto, la configuración del núcleo correcta y etiquetar algunos sistemas de ficheros. Recomendamos seriamente usar SELinux junto con otras mejoras que hagan más robusto nuestro sistema (como PaX / grSecurity).

Este capítulo describe los pasos para instalar Gentoo con SELinux. Asumimos que tiene un sistema Gentoo Linux ya funcionando que quiere convertir a Gentoo con SELinux. Si no es éste el caso, puede igualmente continuar leyendo: podrá instalar Gentoo con SELinux de forma directa si toma las decisiones correctas, basadas en la información contenida en este capítulo, durante el proceso de instalación.

Realizar una instalación estándar

Instale Gentoo Linux siguiendo las instrucciones del manual de Gentoo. Recomendamos usar los ficheros tarball hardened de stage3 y el núcleo hardened-sources en lugar de los ficheros estándar, sin embargo, las instalaciones con stages estándar se permiten también en SELinux. Haga una instalación completa hasta el punto en el que debe reiniciar su sistema para obtener una instalación base (primitiva) de Gentoo.

Cambiar a Python 2

Hasta la fecha, no todas las utilidades de gestión de SELinux son compatibles con Python 3 por lo que le recomendamos cambiar a Python 2 hasta que los paquetes sean actualizados y corregidos.

Listado de Código 1.1: Cambiar a python 2

~# emerge '<=dev-lang/python-3.0'
~# eselect python list
Available Python interpreters:
  [1]   python2.7
  [2]   python3.1 *

~# eselect python set 1
~# source /etc/profile

Elegir un tipo de directriz SELinux

Gentoo ofrece soporte a cuatro tipos de directriz en SELinux: strict, targeted, mcs y mls.

La diferencia entre strict y targeted es debida al dominio no confinado. Cuando se carga la directriz, los procesos en su sistema que no están confinados específicamente en un módulo de directriz en particular formarán parte de los dominios no confinados cuyo propósito es permitir por defecto la mayoría de las actividades (en lugar de prohibirlas por defecto). Como resultado, los procesos que corren dentro de dominios no confinados no tienen restricciones aparte de aquéllas ya forzadas por la seguridad estándar de Linux. A pesar de que el hecho de trabajar sin dominios no confinados está considerado más seguro, también será un más complicado para el administrador tener la certeza de que el sistema funciona correctamente ya que no hay módulos de directriz para cada una de las aplicaciones "ahí fuera".

Aparte de targeted y strict, puede optar por mcs para permitir la categorización de los dominios de los procesos. Esto es útil en sistemas gestionados por múltiples propietarios como servidores Web, equipos de virtualización, etc. en los que muchos procesos están corriendo, la mayoría de ellos en el mismo dominio de seguridad, pero en diferentes categorías. Observe, sin embargo, que para para poder utilizar el soporte de categorías adicionales, bien las propias aplicaciones (como el servidor Web o las herramientas de supervisión) necesitan configurar las categorías SELinux (por lo que deben ofrecer soporte a SELinux), bien se necesitará un guión para arrancar las instancias individuales en categorías diferentes. De lo contrario, mcs es simplemente lo mismo que targeted o strict.

Para terminar, puede también elegir mls para diferenciar los dominios de seguridad a un nivel sensible. Sin embargo, MLS aún está considerado experimental en Gentoo y por lo tanto no lo recomendamos.

En el caso de mcs o mls, necesitará utilizar el ajuste USE unconfined para habilitar o deshabilitar los dominios no confinados en estos tipos de directriz. El tipo strict (sin dominios no confinados) no ofrece este ajuste USE, y el tipo targeted (dominios no confinados) requiere que el ajuste USE esté habilitado.

Cuando haya elegido los tipos de directriz, guárdelos también en su fichero /etc/portage/make.conf. De esta forma, Portage instalará únicamente los módulos SELinux para ese tipo de directriz. Por defecto, los perfile SELinux habilitan strict y targeted (siendo strict el tipo activo por defecto).

Listado de Código 1.2: Ajustar el tipo de directriz en make.conf

~# nano /etc/portage/make.conf
POLICY_TYPES="strict"

Ajustar los contextos del sistema de ficheros

Si su directorio /tmp está en un sistema de ficheros tmpfs montado, entonces necesitará indicarle al núcleo que el contexto raíz de esta localización es tmp_t en lugar de tmpfs_t. Muchos objetos en la directriz de SELinux (incluyendo algunas directrices al nivel de servidor) asumen que /tmp es tmp_t.

Para configurar el montaje de /tmp, edite su fichero /etc/fstab:

Listado de Código 1.3: Actualizar /etc/fstab para /tmp

# Para un tipo de directriz "targeted" o "strict":
tmpfs  /tmp  tmpfs  defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t  0 0

# Para un tipo de directriz "mls" o "mcs":
tmpfs  /tmp  tmpfs  defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t:s0  0 0

A continuación, ajuste la siguiente línea en su /etc/fstab para configurar el contexto para la localización /run.

Listado de Código 1.4: Actualizar /etc/fstab para /run

# Para un tipo de directriz "targeted" o "strict":
tmpfs  /run   tmpfs  mode=0755,nosuid,nodev,rootcontext=system_u:object_r:var_run_t  0 0

# Para un tipo de directriz "mls" o "mcs":
tmpfs  /run   tmpfs  mode=0755,nosuid,nodev,rootcontext=system_u:object_r:var_run_t:s0  0 0

Cambie el perfil de Gentoo

Ahora que tiene una instalación de Gentoo Linux funcionando, cambie el perfil de Gentoo al perfil SELinux adecuado (por ejemplo, hardened/linux/amd64/no-multilib/selinux). Observe que los perfiles antiguos (como selinux/v2refpolicy/amd64/hardened) todavía están soportados.

Listado de Código 1.5: Cambiar el perfil de Gentoo

~# eselect profile list
Available profile symlink targets:
  [1]   default/linux/amd64/10.0
  [2]   default/linux/amd64/10.0/selinux
  [3]   default/linux/amd64/10.0/desktop
  [4]   default/linux/amd64/10.0/desktop/gnome
  [5]   default/linux/amd64/10.0/desktop/kde
  [6]   default/linux/amd64/10.0/developer
  [7]   default/linux/amd64/10.0/no-multilib
  [8]   default/linux/amd64/10.0/server
  [9]   hardened/linux/amd64
  [10]  hardened/linux/amd64/selinux
  [11]  hardened/linux/amd64/no-multilib *
  [12]  hardened/linux/amd64/no-multilib/selinux

~# eselect profile set 12

Aviso: No construya su sistema aún, espere hasta que se lo indiquemos en este documento más adelante. Si reconstruye su sistema ahora, se tomarán directrices SELinux que podrían hacer que el sistema sea inaccesible si lo reinicia a continuación.

Nota: A partir del momento en que cambie su perfil, Portage le advertirá después de cada instalación que "No pudo ajustar las etiquetas de seguridad de SELinux". Esto es lo esperado, ya que las herramientas y capacidades que requiere Portage para ajustar las etiquetas de seguridad todavía no están disponibles. Esta advertencia desaparecerá en el momento en que se complete la instalación de SELinux.

No actualice su sistema aún. Necesitaremos instalar un par de paquetes en las siguientes dos secciones en un orden en particular para el que Portage no está preparado.

Actualice make.conf

A continuación, eche un vistazo a los siguientes ajustes USE y decida si quiere habilitarlos o deshabilitarlos.

Ajuste USE Valor por defecto Descripción
peer_perms Habilitado La capacidad peer_perms gestiona los controles de la directriz de SELinux para los principales (peers) de red. Si está habilitada, los mecanismos de control de acceso que utiliza SELinux para el etiquetado basado en red, se consolidan. Se recomienda este ajuste ya que la directriz también se actualiza para reflejar este hecho. Si no se habilita, los mecanismos antiguos (NetLabel y Labeled IPsec) se usan en cada lado.
open_perms Habilitado La capacidad open_perms habilita el permiso "open" para las clases de fichero y relacionadas con los ficheros. El soporte para la llamada "open" se añadió poco después que otros por lo que el soporte al principio fue opcional. Sin embargo, las directrices han madurado lo suficiente para tener los permisos abiertos habilitados.
ubac Habilitado Cuando está deshabilitado, la directriz SELinux se construye sin el control de acceso basado en usuario.
unconfined Deshabilitado Cuando está habilitado, la construcción de la directriz (excepto para la directriz "strict") incluirán el módulo no confinado (permitiendo así que existand dominios no confinados en el sistema).

Elija sus opciones y actualice la variable USE en /etc/portage/make.conf o en una localización apropiada /etc/portage/package.use para el paquete sec-policy/selinux-base.

Cambios manuales en el sistema

Aviso: La mayoría, o todos los cambios que se comentan a continuación se resolverán automáticamente en los paquetes en cuanto sea posible. Estos cambios, sin embargo, tienen un impacto más allá de las instalaciones de Gentoo Hardened. Por lo tanto, serán incorporados a un ritmo más bajo que las actualizaciones específicas de SELinux. Actualmente, es suficiente con realizar la corrección manual de estas situaciones (además se trata de una operación que se realiza una única vez).

Los siguientes cambios pueden ser necesarios en su sistema dependiendo de las configuraciones o herramientas implicadas.

  • Compruebe si tiene los ficheros *.old en /bin. Si es así, puede eliminarlos o hacer una copia de los mismos de forma que tengan su propio contexto de seguridad. Los ficheros .old son enlaces duros que pueden interferir con el etiquetado de ficheros. Por ejemplo, puede hacer cp /bin/hostname /bin/hostname.old.

Instalar un núcleo SELinux

Aunque los núcleos Linux por defecto ofrecen soporte SELinux, recomendamos el uso del paquete sys-kernel/hardened-sources.

Listado de Código 1.6: Instalar hardened-sources

(Desde luego, debe hacer esto si no lo ha instalado previamente)
~# emerge hardened-sources

A continuación, reconfigure su núcleo con los ajustes apropiados de seguridad. Esto incluye (pero no está limitado a):

  • Soporte de los atributos extendidos en los distintos sistemas de ficheros
  • Soporte de la auditoría de llamadas al sistema
  • Soporte de SELinux

Debajo encontrará una lista rápida de los ajustes recomendados.

Listado de Código 1.7: Ajustes recomendados para la configuración del núcleo Linux

En "General setup"
[*] Prompt for development and/or incomplete code/drivers
[*] Auditing support
[*]   Enable system-call auditing support

En "File systems"
(Para cada sistema de ficheros que utilice, asegúrese de que el soporte de atributos extendidos está habilitado)
<*> Second extended fs support
[*]   Ext2 extended attributes
[ ]     Ext2 POSIX Access Control Lists
[*]     Ext2 Security Labels
[ ]   Ext2 execute in place support

<*> Ext3 journalling file system support
[ ]   Default to 'data=ordered' in ext3
[*]   Ext3 extended attributes
[ ]     Ext3 POSIX Access Control Lists
[*]     Ext3 Security Labels

<*> The Extended 4 (ext4) filesystem
[*]   Ext4 extended attributes
[ ]     Ext4 POSIX Access Control Lists
[*]     Ext4 Security Labels

<*> JFS filesystem support
[ ]   JFS POSIX Access Control Lists
[*]   JFS Security Labels
[ ]   JFS debugging
[ ]   JFS statistics

<*> XFS filesystem support
[ ]   XFS Quota support
[ ]   XFS POSIX ACL support
[ ]   XFS Realtime subvolume support (EXPERIMENTAL)
[ ]   XFS Debugging Support

<*> Btrfs filesystem (EXPERIMENTAL)
[ ]   Btrfs POSIX Access Control Lists

En "Security options"
[*] Enable different security models
[*] Socket and Networking Security Hooks
[*] NSA SELinux Support
[ ]   NSA SELinux boot parameter
[ ]   NSA SELinux runtime disable
[*]   NSA SELinux Development Support
[ ]   NSA SELinux AVC Statistics
(1)   NSA SELinux checkreqprot default value
[ ]   NSA SELinux maximum supported policy format version
    Default security module (SELinux) --->

Recomendamos igualmente el uso de PaX. Puede encontrar más información sobre PaX en el contexto Gentoo Hardened en Guía de inicio rápido para usar PaX con Gentoo Hardened.

Construya e instale el nuevo núcleo Linux y sus módulos.

Actualice fstab

A continuación, edite /etc/fstab y añada la siguiente línea:

Listado de Código 1.8: Habilitar las opciones del sistema de ficheros específicas de selinux

none   /selinux         selinuxfs    defaults    0 0

También deberá crear el punto de montaje

Listado de Código 1.9: Crear el punto de montaje /selinux

# mkdir /selinux

Reinicie

Una vez realizados los cambios mencionados arriba, reinicie su sistema. Asegúrese de que ahora está corriendo un núcleo Linux con SELinux habilitado (el sistema de ficheros /selinux deberá estar montado). No se preocupe, todavía no está activado SELinux.

1.b. Configure SELinux

Introducción

Ahora necesitaremos configurar SELinux, para ello, deberemos instalar las utilidades apropiadas, etiquetar nuestro sistema de ficheros y configurar la directriz.

Instalar directrices y utilidades. Primera Parte

En primer lugar, instale los paquetes sys-apps/checkpolicy y sys-apps/policycoreutils. Aunque éstos serán instalados obligatoriamente debido a las dependencias con los paquetes de directriz SELinux, necesitaremos instalarlos en primer lugar, por ello se utiliza la opción -1.

Listado de Código 2.1: Instalar la directriz y utlidades principales de SELinux

~# emerge -1 checkpolicy policycoreutils

A continuación instalamos el paquete base de la directriz SELinux. Este paquete ofrece el fichero de configuración que necesitaremos ajustar antes de construir el resto de paquetes SELinux.

Listado de Código 2.2: Instalar el paquete base de la directriz SELinux

~# FEATURES="-selinux" emerge -1 selinux-base

Configure la directriz de SELinux

Dentro de /etc/selinux/config puede ahora definir cómo se va a configurar SELinux en el momento en que se inicie el sistema.

Listado de Código 2.3: Editar el fichero /etc/selinux/config

# This file controls the state of SELinux on the system on boot.

# SELINUX can take one of these three values:
#       enforcing - SELinux security policy is enforced.
#       permissive - SELinux prints warnings instead of enforcing.
#       disabled - No SELinux policy is loaded.
SELINUX=permissive

# SELINUXTYPE can take one of these four values:
#       targeted - Only targeted network daemons are protected.
#       strict   - Full SELinux protection.
#       mls      - Full SELinux protection with Multi-Level Security
#       mcs      - Full SELinux protection with Multi-Category Security
#                  (mls, but only one sensitivity level)
SELINUXTYPE=strict

En este fichero de configuración se pueden definir dos variables:

  • SELINUX indica cómo se debe comportar SELinux:
    • enforcing (forzado) habilitará el cumplimiento de las directrices. Esto es precisamente lo que queremos, sin embargo, probablemente quiera comenzar con el modo permisivo (permissive).
    • permissive (permisivo) habilitará las directrices pero no obligará a su cumplimiento. Se le notificará cualquier violación de las directrices pero no se denegará. Es recomendable comenzar trabajando con este modo de forma que no tenga impacto en su sistema hasta que no esté más familiarizado con SELinux. Deberá validar las advertencias recibidas para ver si puede cambiar al modo forzado (enforcing) o no.
    • disabled (deshabilitado) desactivará completamente las directrices. Debido a que en esta situación no se muestran las violaciones de las directrices, no es la situación recomendada.
  • SELINUXTYPE define el tipo de directriz SELinux que se debe cargar. La mayor parte del desarrollo se realiza usando el tipo strict (ya que ofrece confinamiento completo), aunque también se ofrece soporte para los otros.

Asegúrese ahora de que la variable SELINUX está definida como permissive. La cambiaremos a enforcing más tarde.

Instalar directrices y utilidades. Segunda Parte

Ahora podemos continuar con la instalación de las directrices de SELinux. Reconstruya el paquete selinux-base si cambió SELINUXTYPE a algo distinto a strict y a continuación instale las directrices principales de SELinux mediante el paquete sec-policy/selinux-base-policy. Este paquete contiene las directrices principales para poner su sistema en funcionamiento y usando SELinux. Debido a que Portage intentará etiquetar y recargar las directrices (desde la instalación de sys-apps/policycoreutils), necesitamos deshabilitar de nuevo tpoemporalmente el soporte de SELinux (ya que Portage no podría etiquetar nada debido a que todavía no lo comprende).

Listado de Código 2.4: Instalar los paquetes de directriz SELinux

~# FEATURES="-selinux" emerge -1 selinux-base
~# FEATURES="-selinux" emerge selinux-base-policy

A continuación, reconstruya aquellos paquetes afectados por el cambio que hicimos previamente usando una actualización estándar de "world" que tendrá en cuenta los cambios en los ajustes USE (ya que el nuevo perfil cambiará muchos ajustes USE por defecto, incluyendo el ajuste USE selinux). No olvide utilizar después etc-update o dispatch-conf ya que se necesitarán realizar algunos cambios a los ficheros de configuración.

Listado de Código 2.5: Actualice su sistema Gentoo Linux

~# emerge -uDN world

Ahora, instale las herramientas adicionales de SELinux que necesitará en el futuro para depurar o ayudarle con su instalación de SELinux. Estos paquetes son opcionales, pero recomendamos su instalación.

Listado de Código 2.6: Instalar paquetes adicionales de SELinux

~# emerge setools sepolgen checkpolicy

Para terminar, instale los módulos de directrices para aquellas utilidades en las que crea que va a necesitarlas. En un futuro no muy lejano, esta acción se realizará de forma automática (los paquetes tendrán una dependencia opcional producida por el ajustes USE selinux), pero hasta ese momento, necesitará hacer este trabajo manualmente.

Listado de Código 2.7: Instalar los módulos SELinux

~# emerge --search selinux-
[...]
(Select the modules you want to install)
(Seleccione los módulos que desea instalar)
~# emerge selinux-screen selinux-gnupg selinux-sudo selinux-ntp selinux-networkmanager ...
~# emerge selinux-screen selinux-gnupg selinux-sudo selinux-ntp selinux-networkmanager ...

Reinicie y etiquete el sistema de ficheros

Importante: Repita estos pasos cada vez que haya reiniciado desde un núcleo que no tenga SELinux habilitado a un núcleo que sí lo tenga, ya que ejecutar un núcleo con SELinux deshabilitado no actualizará los atributos de los ficheros que se creen o manipulen en las actividades diarias en su sistema.

En primer lugar, reinicie su sistema de modo que se carguen las directrices instaladas. Ahora, necesitaremos reetiquetar sus dispositivos y sus ficheros relacionados con openrc. Esto aplicará los contextos de seguridad adecuados (etiquetas) en los ficheros necesarios.

Listado de Código 2.8: Reetiquetar la estrucura /dev

~# mkdir /mnt/gentoo
~# mount -o bind / /mnt/gentoo

(Sustituya "strict" en la orden de abajo por "targeted" si es ésta su elección para SELINUXTYPE, y utilice "lib" en lugar de "lib64" si tiene un sistema de 32 bits)
~# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/dev
~# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/lib64
~# umount /mnt/gentoo

A continuación, si tiene un fichero de intercambio en lugar de una partición, etiquételo de la forma adecuada:

Listado de Código 2.9: Etiquetar el fichero de intercambio

~# semanage fcontext -a -t swapfile_t "/swapfile"
~# restorecon /swapfile

Ahora reetiquete completamente su sistema de ficheros. La orden de abajo aplicará el contexto de seguridad adecuado a los ficheros de su sistema de ficheros basándose en la información de contexto de seguridad que ofrecen los módulos de directrices de SELinux instalados.

Listado de Código 2.10: Reetiquetar completamente el sistema de ficheros

~# rlpkg -a -r

Si alguna vez tiene que instalar una directriz de SELinux para un paquete después de haberlo instalado, necesitará ejecutar rlpkg para ese paquete de forma que tenga la certeza de que los contextos de seguridad para los ficheros del paquete se ajustan adecuadamente. Por ejemplo, si ha instalado sec-policy/selinux-screen después de darse cuenta de que tiene instalado screen en su sistema:

Listado de Código 2.11: Etiquetar de nuevo los ficheros de un único paquete

(Asegúrese de que no tiene sesiones de screen corriendo ya que los contextos de seguridad no serán adaptados)
~# rlpkg -t screen

Habilitar el servicio selinux_gentoo

Gentoo ofrece un guión llamado selinux_gentoo que restaura los contextos de los ficheros y dispositivos creados dinámicamente así como los pseudo sistemas de ficheros (/dev (opcionalmente) y /sys) ya que estos sistemas de ficheros nos pueden persistir en los cambios de contexto que suceden entre reinicios.

El guión de inicio también ofrece soporte para iniciar en modo permisivo en primer lugar (por ejemplo si tiene un initramfs creado que no funciona en modo forzado) y cambiar a modo forzado a continuación.

Habilite este guión utilizando rc-update add selinux_gentoo boot y actualice la configuración de su gestor de arranque con las siguientes opciones de inicio:

  • nosetenforce si inicia con enforcing=0 y no quiere que el guión de inicio vuelva a cambiar a modo forzado (si fue configurado en /etc/selinux/config). Si su fichero /etc/selinux/config está configurado para iniciar en modo permisivo, este guión de inicio no alterará este comportamiento.
  • norestorecon si no quiere restaurar los contextos de /dev.

Listado de Código 2.12: Configuración GRUB ejemplo

# Arrancar en SELinux permisivo y cambiar a forzado posteriormente
# Requiere que /etc/selinux/config tenga definido SELINUX=enforcing
title Gentoo Hardened/SELinux
root (hd0,0)
kernel /boot/kernel root=/dev/vg/root ... enforcing=0 ...

# Arrancar en SELinux permisivo y permanecer en ese mod, incluso si
# /etc/selinux:config tiene definido SELINUX=encorcing
title Gentoo Hardened/SELinux
root (hd0,0)
kernel /boot/kernel root=/dev/vg/root ... enforcing=0 nosetenforce ...

Reinicie y ajuste los booleanos de SELinux

Reinicie su sistema. Así, se utilizarán los nuevos contextos de fichero que se aplicaron. Ingrese en el sistema, y, si ha instalado Gentoo usando los fuentes hardened (como hemos recomendado), habilite el booleano SSP de SELinux, permitiendo a cada dominio acceso de lectura al dispositivo /dev/urandom:

Listado de Código 2.13: Habilitar el booleano global_ssp

~# setsebool -P global_ssp on

Defina las cuentas de administrador

Si SELINUXTYPE está definido a strict, entonces necesitamos mapear la(s) cuenta(s) que utiliza para gestionar su sistema (aquéllas que necesitan acceso a Portage) al usuario de SELinux staff_u. Si no, no podrá gestionar correctamente el sistema con ninguna de las cuentas (aparte de root, pero entonces necesitará entrar en el sistema como root directamente y no a través de sudo o su). Por defecto, los usuarios se mapean al usuario SELinux user_u, el cual no tiene los privilegios adecuados (tampoco los roles apropiados de acceso) para gestionar un sistema. Las cuentas que son mapeadas a staff_u pueden hacerlo, pero podrían necesitar cambiar del rol staff_r al rol sysadm_r antes de que se les concedan los privilegios apropiados.

Asumiendo que su nombre de cuenta es juan:

Listado de Código 2.14: Mapear la cuenta Linux juan al usuario SELinux staff_u

~# semanage login -a -s staff_u juan
~# restorecon -R -F /home/juan

Si más tarde ingresa en el sistema como juan y quiere gestionar su sistema, probablemente necesitará cambiar su rol. Puede usar newrole para hacer esto:

Listado de Código 2.15: Cambiar de rol

~$ id -Z
staff_u:staff_r:staff_t
~$ newrole -r sysadm_r
Password: (Introduzca su contraseña)
~$ id -Z
staff_u:sysadm_r:sysadm_t

Si, por el contrario, utiliza una directriz targeted, entonces el usuario con el que trabaja será de tipo unconfined_t y ya dispondrá de los privilegios necesarios para realizar tareas administrativas del sistema.

Cuando haya terminado, disfrute de su trabajo. Acaba de dar sus primeros pasos por el mundo SELinux.

Soporte del servicio de administración

Por defecto, las directrices de SELinux en Gentoo Hardened permiten al dominio sysadm_t el acceso a todos los servicios. Sin embargo, algunos de estos servicios tienen directrices que les permiten se asignados a usuarios individuales diferentes de root. Esto requiere que se conceda al usuario el rol system_r (lo que implica que el usuario puede, en ciertos casos, obtener este cambio de rol hacia el rol de sistema).

Por tanto, se recomienda conceder el rol system_r al usuario SELinux administrador que va a utilizar en mayor medida. Estos son, en la mayoría de los casos, los usuarios root y staff_u.

Listado de Código 2.16: Conceder el rol system_r al usuario staff y root

# semanage user -m -R "staff_r sysadm_r system_r" root
# semanage user -m -R "staff_r sysadm_r system_r" staff_u

2. Configurar SELinux para adaptarlo a sus necesidades

2.a. Administrando usuarios

Introducción

A lo largo de la instalación, hemos hablado de como mapear un usuario Linux a uno SELinux. En el ejemplo, hemos utilizado un usuario hipotético llamado "juan" y lo hemos mapeado al usuario SELinux "staff_u". Si está corriendo un sistema multiusuario, la gestión de los mapeos de derechos es importante. Un usuario que se mapea al usuario "user_u" no obtendrá ningún derecho adicional. Incluso si le concediera derechos adicionales a través de órdenes como sudo, la directriz de SELinux no le permitiría a este usuario hacer nada que esté relacionado con la administración.

Por esta razón, es importante tratar los mapeos de usuarios en SELinux y los usuarios Linux de su sistema.

Mapeos de usuario

Ejecute semanage login -l para mostrar los mapeos actuales entre las cuentas de usuario Linux y los usuarios SELinux.

Listado de Código 1.1: Ejecutar semanage login -l

# semanage login -l

Login Name                SELinux User

__default__               user_u
root                      root
juan                      staff_u
system_u                  system_u

El usuario SELinux "user_u" se utiliza para las cuentas normales. De esta forma, el mapeo especial __default__ se define en SELinux para notar que esa cuenta no está definida de otra forma. Esto nos asegura que una cuenta nueva nos obtiene privilegios elevados por defecto.

La siguiente tabla ofrece una vista rápida de los usuarios estándar SELinux disponibles después de la instalación.

Usuario SELinux Descripción
user_u Usuario normal por defecto de SELinux, el cual se debe utilizar para las cuentas de usuario final que no van a ser empleadas para administrar ningún servicio del sistema.
staff_u Usuario SELinux para administradores. Este usuario tiene derechos para conmutar roles y así ganar privilegios elevados.
root Usuario SELinux para la cuenta root. Se diferencia ligeramente de la cuenta staff_u aparte de tener un identificador diferente. Esto nos asegura que los ficheros protegidos por el control de acceso basado en usuario para root no puede ser gestionado por los usuarios staff_u (y otros).
sysadm_u Usuario SELinux para la administración del sistema. Por defecto, esta cuenta no se utiliza inmediatamente ya que este usuario obtiene de forma inmediata el rol administrativo (por lo que staff_u y root todavía necesitarán conmutar roles).
system_u Usuario SELinux para administrar servicios. Nunca se debe utilizar para usuarios finales ya que ofrece acceso directo al rol del sistema (y sus privilegios).
unconfined_u Usado cuando la directriz es targeted, este usuario SELinux tiene muchos privilegios (esencialmente no está limitado en sus acciones, aunque todavía se gestiona través de SELinux con una directriz "muy abierta").

Para mapear una cuenta a un usuario especifico de SELinux, utilice la orden semanage login -a:

Listado de Código 1.2: Mapera la cuenta 'sofia' al usuario staff_u

# semanage login -a -s staff_u sofia

Sin embargo, cuando se actualiza este mapeo, los ficheros en el directorio de inicio (home) del usuario serán propiedad de un usuario SELinux incorrecto. Por ello, es importante etiquetar de nuevo los ficheros de ese usuario:

Listado de Código 1.3: Etiquetar de nuevo los ficheros de sofia

# restorecon -R -F /home/sofia

Cuentas adicionales de SELinux

Es perfectamente posible crear usuarios SELinux adicionales, y mapear las cuentas Linux a esos nuevos usuarios. Esto se puede necesitar cuando desee una auditoría más profunda (al nivel del usuario final) o cuando esté mejorando la directriz con roles adicionales. También, si quiere utilizar la característica de Control de Acceso Basada en Usuario (UBAC), el hecho de usar diferentes usuarios SELinux es importante para reforzar el control de los distintos usuarios (si todos ellos utilizan el mismo usuario SELinux, el UBAC tendrá poco efecto).

La gestión de los usuarios SELinux se realiza usando semanage user:

Listado de Código 1.4: Crear un usuario SELinux

# semanage user -a -R "staff_r sysadm_r" sofia

Verifiquemos como los usuarios SELinux están configurados actualmente:

Listado de Código 1.5: Comprobar las identidades de los usuarios SELinux

# semanage user -l
SELinux User    SELinux Roles

root            staff_r sysadm_r
sofia           staff_r sysadm_r
staff_u         staff_r sysadm_r
sysadm_u        sysadm_r
system_u        system_r
unconfined_u    unconfined_r
user_u          user_r

# semanage login -l
Login Name                SELinux User

__default__               user_u
root                      root
sofia                     staff_u
swift                     staff_u
system_u                  system_u

Ahora que hemos creado un nuevo usuario llamado "sofia", podemos actualizar el mapeo de la cuenta Linux "sofia" hacia el nuevo usuario SELinux "sofia":

Listado de Código 1.6: Actualizar el mapeo del usuario Linux

# semanage login -m -s sofia sofia
# semanage login -l
Login Name                SELinux User

__default__               user_u
root                      root
sofia                     sofia
swift                     staff_u
system_u                  system_u

No olvide etiquetar de nuevo los ficheros de este usuario.

Como puede ver, la gestión de los usuarios SELinux implica definer el rol al cual tiene acceso cada usuario. Hemos dado una introducción de alto nivel a los roles por defecto en Conceptos detrás de SELinux, sin embargo ya que los roles son importantes cuando usamos un sistema de Control de Acceso Obligatorio, refresquémos la memoria de nuevo:

Rol SELinux Descripción
user_r Rol por defecto para el usuario final. Este rol ofrece acceso a las aplicaciones y actividades comunes, sin embargo, no permite la administración del sistema ni de ningún servicio más allá de lo esperado para un usuario normal.
staff_r Rol de administración por defecto para las actividades diarias. Este rol posee privilegios adicionales más allá de los ofrecidos a user_r, sin embargo, no es un rol de administración del sistema completo. Está pensado para las actividades que no sean de administración realizadas por operadores y administradores.
sysadm_r Rol de administración del sistema. Este role tiene privilegios muy elevados (ya que contiene aquellos privilegios necesarios para actualizar la directriz) y debería asignarse únicamente a administradores en los que se confíe plenamente. En casi ninguna situación es asignado a usuarios de forma inmediata (deben en primer lugar conmutar entre roles) excepto para el acceso directo de root (por ejemplo a través de la consola).
system_r Rol de servicio del sistema, el cual se utiliza para los servicios que están corriendo (procesos). Se asigna únicamente a los usuarios cuando estos obtienen derechos específicos y limitados de administración (por ejemplo, derechos de administración sobre un único dominio de un demonio).
unconfined_r El rol no confinado se utiliza cuando la directriz targeted está soportada. Este rol se asigna a usuarios no confinados (por ejemplo el usuario SELinux unconfined_u) los cuales tienen muchos privilegios (éstos trabajan prácticamente sin limitaciones).

Se debe observar que estos roles son los que existen por defecto, sin embargo, el administrador de seguridad puede crear roles adicionales y añadir privilegios particulares. Hablaremos sobre esto más adelante en este manual ya que implica que se debe actualizar la directriz SELinux de Gentoo Hardened.

2.b. Leyendo el registro de auditoría

Introducción

Cuando trabaje con un sistema que tiene habilitado SELinux, se dará cuenta de que las cosas se comportan de forma diferente pero sin indicar ningún mensaje de error con sentido. Normalmente, cuando SELinux "deniega" un acceso en particular, lo almacena en el registro de auditoría del sistema, aunque para la aplicación en si misma, es perfectamente posible que muera de forma silenciosa. En caso contrario, lo más seguro es que obtenga un mensaje de error permiso denegado.

Inicialmente, SELinux se ejecuta en modo permisivo, lo cual significa que SELinux registrará lo que denegaría aunque nos deje continuar. Este modo es perfecto para poner al sistema en forma sin tener demasiados problemas mientras se hace esto. Una vez que crea que sus ajustes de seguridad son correctos, se puede cambiar el modo de permisivo a forzado. Hablaremos de esto más adelante.

En primer lugar, echemos un vistazo al registro de auditoría y veamos lo que se dice allí...

Ubicación(es) del registro de auditoría

El código del núcleo SELinux escribe las denegaciones de acceso (y en alguna ocasión incluso las actividades que se permiten pero que están siendo auditadas) en el registro de auditoría. Si está corriendo una instalación Gentoo Hardened con el registrador del sistema syslog-ng, entonces, el registrador ya está configurado para colocar las líneas de auditoría en /var/log/avc.log. Sin embargo, otros registradores de sistema podrían colocar estas entradas en una ubicación diferente (por ejemplo /var/log/audit.log).

Abajo encontrará las líneas para la configuración apropiada del registrador del sistema syslog-ng de modo que escriba los eventos en el fichero /var/log/avc.log.

Listado de Código 2.1: Extracto de syslog-ng.conf para las entradas AVC de SELinux

# ¡Las siguientes líneas son solo una parte del fichero de configuración!
source kernsrc  { file("/proc/kmsg");       };
destination avc { file("/var/log/avc.log"); };
filter f_avc    { message(".*avc: .*");     };

log {
  source(kernsrc);
  filter(f_avc);
  destination(avc);
};

¿Qué es AVC?

Como ya hemos mencionado, SELinux escribe sus entradas en el registro de auditoría. Estas entradas se llaman mensajes avc o entradas de registro avc. El acrónimo AVC significa Access Vector Cache (Caché de Acceso Vectorial), tal y como indica su nombre, se trata de un sistema caché.

Utilizar un sistema cache de acceso vectorial mejora el rendimiento cuando se trata con (y se fuerzan) actividades y privilegios. Ya que SELinux ofrece un enfoque muy detallado sobre privilegios y permisos, sería tremendamente penoso (en lo que se refiere a rendimiento) si cada llamada supusiera buscar el dominio, el recurso destino, el privilegio y si está permitido o no, esto una y otra vez. En lugar de esto, SELinux utiliza la Caché de Acceso Vectorial para almacenar las solicitudes y respuestas pasadas. Es es sistema AVC el responsable de comprobar los accesos y (si es necesario) registrarlos.

Leyendo un mensaje de denegación en la AVC

Abajo encontrará un mensaje típico de denegación en la AVC.

Listado de Código 2.2: Ejemplo de mensaje de denegación en la AVC

Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
  avc:  denied  { module_request } for  pid=14561 comm="firefox" kmod="net-pf-10"
  scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system

Analicemos cada una de las partes de este mensaje una a una.

Listado de Código 2.3: Denegación AVC: Fecha, hora e información de la ubicación

Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
  avc:  denied  { module_request } for  pid=14561 comm="firefox" kmod="net-pf-10"
  scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system

La primera parte del mensaje le informa del momento en el que se escribió el mensaje (Oct 15 13:04:54), en qué equipo (hpl) y cuántos segundos transcurrieron desde que se inició el sistema (963185.177043).

Listado de Código 2.4: Denegación AVC: información fuente

Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
  avc:  denied  { module_request } for  pid=14561 comm="firefox" kmod="net-pf-10"
  scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system

La información que aparece después es el origen de la denegación, es decir, qué proceso está intentando hacer qué cosa. En este caso, el proceso es firefox, con identificador de proceso (PID) 14561, el cual está corriendo en el dominio fuente staff_u:staff_r:mozilla_t.

Listado de Código 2.5: Denegación AVC: recurso destino

Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
  avc:  denied  { module_request } for  pid=14561 comm="firefox" kmod="net-pf-10"
  scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system

El destino de la actividad es un módulo del núcleo (net-pf-10, el cual es el nombre interno que se le da a IPv6), etiquetado system_u:system_r:kernel_t

Listado de Código 2.6: Denegación AVC: acción denegada

Oct 15 13:04:54 hpl kernel: [963185.177043] type=1400 audit(1318676694.660:2472):
  avc:  denied  { module_request } for  pid=14561 comm="firefox" kmod="net-pf-10"
  scontext=staff_u:staff_r:mozilla_t tcontext=system_u:system_r:kernel_t tclass=system

Por último, aparece la acción que ha sido denegada (module_request) y su clase (system). Estas clases le ayudan a identificar qué es lo que se ha denegado, ya que leer un fichero no el lo mismo que leer un directorio.

Por ejemplo, en el siguiente caso, un proceso gorg con identificador (PID) 13935 está intentando leer un fichero llamado localtime con inodo 130867 el cual se encuentra en el dispositivo /dev/md3:

Listado de Código 2.7: Ejemplo de denegación AVC

Oct 15 14:40:30 hpl kernel: [968909.807802] type=1400 audit(1318682430.323:2614):
  avc:  denied  { read } for  pid=13935 comm="gorg" name="localtime" dev=md3 ino=130867
  scontext=staff_u:sysadm_r:gorg_t tcontext=system_u:object_r:locale_t tclass=file

En este caso debería ser obvio que el fichero es /etc/localtime, sin embargo, cuando este no es el caso, las dos órdenes siguiente pueden ser útiles:

Listado de Código 2.8: Encontrar el recurso destino basándose en el inodo y dispositivo

(Encontrar el dispositivo /dev/md3)
# mount | grep /dev/md3
/dev/md3 on / type ext4 (rw,seclabel,noatime,barrier=1,nodelalloc,data=journal)

(Encontrar qué fichero tiene el inodo 130867)
# find / -xdev -inum 130867
/etc/localtime

Gestionar las denegaciones AVC

La mayor parte del trabajo para configurar SELinux es la lectura de las denegaciones y encontrar lo que debe ser corregido (o ignorado), corregirlo y repetir el proceso. Con un poco de suerte, el resto de este manual le ayudará a averiguar lo que está causando la denegación.

Las denegaciones pueden ser cosméticas (una actividad que se deniega pero que no tiene impacto en el comportamiento funcional de la aplicación). Si este es el caso, se puede marcar la denegación como dontaudit, (no auditar) indicando que, por defecto, la denegación ya no será registrada. Si cree que se está denegando algo pero no lo ve en el registro, intente deshabilitar las reglas dontaudit:

Listado de Código 2.9: Deshabilitar dontaudit

(Esta orden también se puede abreviar como "semodule -DB")
# semodule --build --disable_dontaudit

En la mayoría de los casos, se debe actuar sobre las denegaciones. Las acciones que entonces necesitará realizar son:

  • Etiquetar de nuevo el recurso destino (las etiquetas erróneas pueden causar que acciones legítimas sean denegadas)
  • Etiquetar de nuevo el origen (el fichero binario del proceso) ya que una etiqueta errónea puede causar que la aplicación se ejecute en el dominio incorrecto.
  • Cargar el módulo SELinux necesario, ya que los módulos contienen reglas para permitir (y etiquetar) recursos. Sin el módulo correcto cargado, observará algunas denegaciones ya que no hay ningún módulo que realice las concesiones necesarios (sentencias para permitir las acciones).
  • Conceder el rol adecuado al usuario que ejecuta la aplicación. Hemos cubierto los usuarios y sus roles inicialmente, sin embargo, profundizaremos en esto más adelante en este manual.
  • Añadir sus propias sentencias de directriz SELinux, principalmente porque no existen módulos de directriz SELinux para la aplicación que está intentando ejecutar.

2.c. Utilizar etiquetas (de fichero)

Introducción

Dentro de SELinux, los privilegios de acceso se basan en la etiqueta que se da a la parte original (llamada domain) y a su recurso destino. Por ejemplo, un proceso que corre en el dominio passwd_t quiere leer (tener privilegio) el fichero /etc/shadow que está marcado shadow_t (el recurso destino). No es sorprendente que la mayoría de la administración de SELinux consiste en (re)etiquetar los recursos de forma adecuada (y asegurarse que su etiqueta permanece correcta).

Obtener etiqueta(s) de fichero

Existen varias formas de etiquetar de nuevo las órdenes y muchas de ellas son iguales. Pero, antes de explicar esto más en detalle, echaremos un vistazo a algunas etiquetas de fichero (y a cómo puede consultarlas).

En SELinux, las etiquetas se asignan al nivel del fichero a través de la capacidad del sistema de mantener atributos extendidos. Para SELinux, los atributos se llaman security.selinux y se pueden obtener usando getfattr:

Listado de Código 3.1: Obtener el atributo extendido de un fichero en SELinux

$ getfattr -n security.selinux /etc/hosts
# file: etc/hosts
security.selinux="system_u:object_r:net_conf_t"

Desde luego, obtener el atributo del fichero de esta forma, requiere mucho tiempo y no es flexible. Para este propósito, la aplicaciones más importante (incluyendo coreutils) se hacen compatibles con SELinux. Estas aplicaciones en la mayoría de las ocasiones utilizan la opción -Z para mostrar la información de contexto de SELinux. En el caso de ficheros, esto implica el contenido de los atributos extendidos.

Listado de Código 3.2: Obtener el contexto de un fichero

$ ls -Z /etc/hosts
system_u:object_r:net_conf_t   /etc/hosts

Existen otras órdenes como matchpathcon que muestran el contexto tal como debería ser. Sin embargo, su propósito es consultar la directriz SELinux en su sistema para averiguar la directriz que debería usarse, no la que se utiliza:

Listado de Código 3.3: Diferencia entre resultados de contexto y resultados de matchpathcon

$ ls -Z /etc/portage/make.conf
staff_u:object_r:etc_t    /etc/portage/make.conf
$ matchpathcon /etc/portage/make.conf
/etc/portage/make.conf            system_u:object_r:portage_conf_t

Ajustando la(s) etiqueta(s) de fichero

Y ahora, ¿Cómo podemos manipular las etiquetas de fichero?. Bien, en primer lugar: no se le permitirá cambiar las etiquetas de un fichero (incluso si es el propietario del mismo) a menos que la directriz SELinux se lo permita. Estas reglas de concesión se realizan sobre dos tipos de privilegios: Las etiquetas que puede cambiar (relabelfrom) y a qué etiquetas puede cambiar (relabelto). Puede consultar estar regals usando sesearch:

Listado de Código 3.4: Consultar los tipos relabelto y relabelfrom

# Desde qué etiqueta en los ficheros (-c) se permite (-A) a user_t (-s) etiquetar de nuevo (-p)?
$ sesearch -s user_t -c file -p relabelfrom -A
[...]
allow user_t mozilla_home_t : file { ... relabelfrom relabelto } ;

Si tiene permiso, entonces puede utilizar chcon para cambiar (ch) el contexto de un fichero:

Listado de Código 3.5: Cambiar el contexto de un fichero

$ ls -Z strace.log
staff_u:object_r:user_home_t  strace.log
$ chcon -t mutt_home_t strace.log
$ ls -Z strace.log
staff_u:object_r:mutt_home_t  strace.log

Si no posee los privilegios adecuados, obtendrá un mensaje de error descriptivo:

Listado de Código 3.6: Intentar cambiar el contexto de un fichero

$ chcon -t shadow_t strace.log
chcon: failed to change context of `strace.log' to `staff_u:object_r:shadow_t': Permission denied

Ahora, si cree que todo lo que necesita es la orden chcon, no está en lo cierto. La orden chcon no hace nada más que lo que dice: cambiar el contexto. Cuando el sistema etiqueta de nuevo los ficheros, los cambios se van. El reetiquetado de los ficheros se realiza a menudo para asegurarse de que las etiquetas son las correctas (es decir, las etiquetas concuerdan con lo que la directriz SELinux dice que debería ser). La directriz SELinux contiene, para cada módulo de directriz, la lista de ficheros, directorios, zócalos (sockets), ... y sus contextos de fichero apropiados (etiqueta).

Echaremos un vistazo a los módulos de directriz de SELinux más adelante. Abajo puede encontrar un extracto de esta definición para el módulo mozilla:

Listado de Código 3.7: Extracto de los contextos de fichero del módulo mozilla

/usr/bin/firefox-bin                            -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/bin/mozilla-[0-9].*                        -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/bin/mozilla-bin-[0-9].*                    -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib(64)?/galeon/galeon                     -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib(64)?/netscape/.+/communicator/communicator-smotif\.real -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib(64)?/netscape/base-4/wrapper           -- gen_context(system_u:object_r:mozilla_exec_t,s0)
/usr/lib/[^/]*firefox[^/]*/plugin-container     -- gen_context(system_u:object_r:mozilla_plugin_exec_t,s0)
/usr/lib64/[^/]*firefox[^/]*/plugin-container   -- gen_context(system_u:object_r:mozilla_plugin_exec_t,s0)

Para poner la etiqueta adecuada a un fichero, puede utilizar las órdenes setfiles o restorecon. Debido a que ambas son la misma orden (pero con una forma ligeramente diferente de utilización), ahora hablaremos solo de restorecon. Se puede encontrar más información acerca de la orden setfiles en su página del manual.

Cuando utilice restorecon, la aplicación consultará la directriz SELinux para averiguar qué etiqueta debería ser la correcta para el fichero. Si ésta es diferente, cambiará la etiqueta para que sea la adecuada. Esto significa que no necesita ofrecer la etiqueta a un fichero para que funcione la orden correspondiente. También, restorecon soporta recursión, por lo que no necesita etiquetar de nuevo los ficheros uno a uno.

Listado de Código 3.8: Usar restorecon

$ ls -Z /etc/portage/make.conf
staff_u:object_r:etc_t            /etc/portage/make.conf
$ restorecon /etc/portage/make.conf
$ ls -Z /etc/portage/make.conf
system_u:object_r:portage_conf_t  /etc/portage/make.conf

Por último, Gentoo también ofrece una aplicación muy útil: rlpkg. Este guión etiqueta de nuevo los ficheros de un paquete Gentoo package (rlpkg <nombredepaquete>) o, dando los argumentos adecuados, todos los ficheros del sistema.

Listado de Código 3.9: Usar rlpkg

# Etiquetar de nuevo los ficheros del paquete firefox-bin:
# rlpkg firefox

# Etiquetar de nuevo todos los ficheros del sistema:
# rlpkg -a -r

Saltándose las etiquetas de fichero de la directriz de SELinux

Puede que no esté siempre de acuerdo con la etiqueta que la directriz de SELinux fuerza a los ficheros: puede que tenga sus ficheros ubicados en otro lugar (una localización diferente de su árbol Portage es un buen ejemplo) o quizá necesite etiquetarlos de forma diferente para que funcionen otras aplicaciones. Para no tener que chcon estos ficheros una y otra vez, puede mejorar la directriz SELinux en su sistema con reglas adicionales de contextos de fichero. Estas reglas también se utilizan cuando llama a restorecon y se salta las reglas ofrecidas por la directriz SELinux.

Para añadir reglas de contexto de fichero adicionales, necesitará usar la orden semanage. Esta orden se utiliza para manipular y actualizar la directriz local de SELinux en su sistema. En este caso en particular, utilizaremos la orden semanage fcontext:

Listado de Código 3.10: Usar semanage para añadir una regla de contexto de fichero

# Marcar /mnt/gentoo/etc/portage/make.conf como un tipo portage_conf_t
# semanage fcontext -a -t portage_conf_t /mnt/gentoo/etc/portage/make.conf

# Marcar /mnt/gentoo/usr/portage como portage_ebuild_t
# semanage fcontext -a -t portage_ebuild_t "/mnt/gentoo/usr/portage(/.*)?"

Como puede observar en el ejemplo, puede utilizar caracteres comodín: cuando una regla tiene caracteres comodín, tiene menor prioridad que una regla que no los tiene. La prioridad de las reglas con caracteres comodín se basa en lo "bajo" que está la cadena con la primera ocurrencia del carácter comodín. Para más información, por favor, consulte nuestras Preguntas Frecuentes: ¿Cómo averiguo qué regla de contexto de fichero se está utilizando para un fichero en particular?.

Si quiere eliminar una definición de contexto de fichero, puede utilizar semanage fcontext -d:

Listado de Código 3.11: Eliminar una definición de contexto de fichero

# semanage fcontext -d -t portage_ebuild_t /mnt/gentoo/etc/portage/make.conf

Por último, para ver todas las definiciones de contexto de fichero (tanto las definidas por el usuario como las ofrecidas por la directriz SELinux), puede utilizar semanage fcontext -l. Para ver únicamente el conjunto local, añada -C:

Listado de Código 3.12: Ver las mejoras en el contexto de ficheros definidas por el usuario

# semanage fcontext -C -l
SELinux fcontext                          type             Context
/opt/xxe/bin/.*\.jar                      all files        system_u:object_r:lib_t
/srv/virt/gentoo(/.*)?                    all files        system_u:object_r:qemu_image_t

Tipos personalizables

No es muy difícil comprender cómo funcionan las etiquetas sobre los ficheros, sin embargo, puede encontrarse alguna sorpresa si no conoce los tipos personalizables.

Un tipo personalizable es un tipo específico que por defecto no es modificado por las herramientas de administración de SELinux. Si quiere etiquetar de nuevo un fichero que actualmente posee un tipo personalizable, necesitará forzarlo usando algunas órdenes (por ejemplo restorecon -F).

No existe muchos tipos personalizables por defecto. La lista de tipos que SELinux considera personalizables se indican en el fichero customizable_types en la ubicación /etc/selinux/*/contexts:

Listado de Código 3.13: Listar los tipos personalizables

# cat /etc/selinux/strict/contexts/customizable_types
mount_loopback_t
public_content_rw_t
public_content_t
swapfile_t
textrel_shlib_t

Estos tipos existen porque se utilizan para los ficheros cuya ubicación no es fija (y por lo tanto, la directriz de SELinux no puede asegurar si la etiqueta de los ficheros es correcta o no). El tipo public_content_t, que se utiliza para ficheros que se van a leer por varios servicios (por ejemplo, FTP, servidor web, ...) debería darle una idea de este tipo de ficheros.

Si mira en la página del manual de restorecon, se mencionan tanto los tipos personalizables como la sección de usuario. Esta última es para las reglas que se identifican en la directriz de SELinux para ficheros de un usuario final, como las siguientes definiciones en el módulo de directriz mozilla:

Listado de Código 3.14: Definición de sección de usuario dentro del módulo mozilla

HOME_DIR/\.mozilla(/.*)?      gen_context(system_u:object_r:mozilla_home_t,s0)
HOME_DIR/\.netscape(/.*)?     gen_context(system_u:object_r:mozilla_home_t,s0)
HOME_DIR/\.phoenix(/.*)?      gen_context(system_u:object_r:mozilla_home_t,s0)

Aunque en el ejemplo de arriba, forzar restorecon en los ficheros es probablemente correcto, se pueden dar ejemplos en los que ésto no se desea. Por ejemplo, la directriz firefox por defecto únicamente permite a la aplicación escribir en los directorios etiquetados con mozilla_home_t. Si se quiere descargar algo, esto es imposible (a menos que lo haga en ~/.mozilla). La solución para esto es etiquetar un directorio (digamos ~/Descargas) con mozilla_home_t.

2.d. Directriz SELinux y Booleanos

Introducción

Hemos tratado con usuarios y etiquetas, pero todavía tenemos que tratar con un tercer aspecto que no hemos tocado: La propia directriz SELinux.

La directriz SELinux tal y como se ofrece en Gentoo Hardened es una directriz cuidadosamente ajustada y basada en la directriz de referencia (una directriz SELinux independiente de toda distribución) con cambios menores. Con suerte, no necesitará escribir de nuevo la directriz para adaptarla a sus necesidades, sin embargo, de vez en cuando son necesarios algunos cambios.

Cambiar el comportamiento de la directriz SELinux: Booleanos

Una forma común y agradable de ajustar la directriz SELinux es mediante el uso de un booleano. Un booleano SELinux, también llamado condicional, modifica el comportamiento de la directriz SELinux basándose en los ajustes que realiza el usuario. Para clarificar esto un poco, echemos un vistazo a algunos de los booleanos disponibles:

Listado de Código 4.1: Obtener los booleanos SELinux

# getsebool -a | grep ^user
user_direct_mouse --> off
user_dmesg --> off
user_ping --> on
user_rw_noexattrfile --> off
user_tcp_server --> off
user_ttyfile_stat --> off

Aunque parece que no hay mucho que decir a primera vista, estos booleanos alteran el modo en que la directriz SELinux fuerza la actividad de los usuarios (de ahí que los booleanos comiencen con user_). Por ejemplo, user_ping esta definido a on, por lo que se permite al usuario utilizar la orden ping. Si se define a off, la directriz SELinux no permitiría al usuario utilizar ping.

Se puede cambiar el valor de un booleanos entre on y off utilizando setsebool o togglesebool. Con setsebool necesitará indicar el valor (on u off), mientras que togglesebool conmuta el valor.

Listado de Código 4.2: Deshabilitar el uso de ping por parte de los usuarios

# setsebool user_ping off

Por defecto, setsebool no almacena los valores booleanos, por lo que después de un reinicio los antiguos valores se cargarán. Para hacer estos cambios persistentes, necesitará añadir la opción -P:

Listado de Código 4.3: Permitir a los usuarios ejecutar dmesg de forma persistente

# setsebool -P user_dmesg on

Los booleanos permiten a los administradores ajustar la directriz, y a los administradores de seguridad escribir directrices que sean los suficientemente flexibles para que su uso se extienda. En términos de la flexibilidad de Gentoo, estos booleanos no deberían usarse demasiado (sería deseable asociar estos booleanos con ajustes USE, de modo que un servidor instalado con USE="ldap" obtenga la directriz SELinux para utilizar, mientras que USE="-ldap" la deshabilita). Aún así, el uso de booleanos es una forma popular para hacer más flexible una directriz SELinux.

Gestionar los módulos de directriz SELinux

En esta última parte, cubriremos los módulos de reglas de la directriz SELinux. Mencionamos anteriormente que la directriz SELinux que usa Gentoo Hardened se basa en la directriz de referencia, la cual ofrece un enfoque modular a las directrices de SELinux. Existe una directriz base que es obligatoria en todos los sistemas y se trata de que sea lo más pequeña posible. El resto son módulos de la directriz SELinux, que normalmente ofrecen las declaraciones, reglas y los contextos de ficheros para una sola aplicación (o tipo de aplicación).

Con semodule -l puede ver la lista de módulos de directriz SELinux que están cargados:

Listado de Código 4.4: Listar los módulos cargados por SELinux

# semodule -l
alsa       1.11.0
apache     2.3.0
entropyd   1.6.0
dbus       1.15.0
dnsmasq    1.9.0
(...)

En Gentoo Hardened, cada módulo se ofrece mediante el paquete sec-policy/selinux-<nombredemódulo>. Por ejemplo, el primer módulo que vemos en el ejemplo de arriba lo ofrece el paquete selinux-alsa:

Listado de Código 4.5: Paquete de módulo de directriz SELinux en Gentoo

$ emerge --search selinux-alsa
Searching...
[ Results for search key : selinux-alsa ]
[ Applications found : 1]

* sec-policy/selinux-alsa
    Latest version available: 2.20110726
    Latest version installed: 2.20110726
    Size of files: 574 kB
    Homepage:      http://www.gentoo.org/proj/en/hardened/selinux/
    Description:   SELinux policy for alsa
    License:       GPL-2

Cuando se necesita un módulo que no está instalado en su sistema, se considera un fallo (los paquetes que lo necesitan deben depender del paquete de la directriz SELinux si se ha definido el ajuste USE selinux). Por esto, una vez que instale el paquete, el módulo se cargará automáticamente:

Listado de Código 4.6: Instalar un paquete de directriz SELinux

# emerge selinux-screen

Si necesita eliminar un módulo de su sistema, desinstalar el paquete no será suficiente: el propio módulo directriz SELinux se copia antes al almacén de directrices (como parte del proceso de instalación) y Portage no lo eliminará de este almacén. Por lo tanto, deberá eliminarlo manualmente:

Listado de Código 4.7: Desinstalar un módulo de directriz SELinux

# emerge -C selinux-screen
# semodule -r screen

2.e. Siguientes pasos

¿Qué hacer ahora?

Hasta ahora, su sistema ha estado corriendo en modo permisivo. Necesitará habilitar el modo forzado antes de estar protegido adecuadamente mediante SELinux. Discutiremos cómo cambiar al modo forzado en Permisivo, no confinado, deshabilitado o lo que no..., pero antes de eso, necesitará tener en cuenta algunas cosas...

Usuarios de Initramfs

Si su sistema utiliza un initramfs para arrancar, no podrá iniciar el sistema directamente en modo forzado (debido a la incidencia #397597). Para evitar esta cuestión, puede crear el siguiente guión de inicio que cambiará de modo permisivo a modo forzado de una forma razonablemente rápida dentro del proceso de inicio (y antes de arrancar los servicios de red):

Listado de Código 5.1: Contenido de /etc/init.d/selinux_enforce

#!/sbin/runscript
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo/xml/htdocs/proj/es/hardened/selinux/hb-using-configuring.xml,v 1.7 2013/08/13 14:26:42 nimiux Exp $
description="Switch into SELinux enforcing mode"

depend() {
        need sysfs
}

start() {
       if get_bootparam "norestorecon" ; then
               ewarn "Skipping restoring file contexts in /dev as requested"
       else
               ebegin "Restoring file contexts in /dev"
                       restorecon -R /dev
               eend 0
       fi


       if get_bootparam "nosetenforce" ; then
               ewarn "Skipping switching to enforcing mode as requested by kernel cmdline"
       else
               . /etc/selinux/config
               CURRENTMODE=$(cat /sys/fs/selinux/enforce)

               if [ "${SELINUX}" = "enforcing" ] && [ "${CURRENTMODE}" = "0" ];
               then
                       ebegin "Switching to enforcing mode"
                       echo 1 > /sys/fs/selinux/enforce
                       eend $?
                else
                       ewarn "Not switching to enforcing mode, or enforcing mode already enabled"
                fi
        fi
}

Añada el guión de inicio al nivel de ejecución boot, y edite la configuración de su gestor de arranque para arrancar siempre con la definición enforcing=0. El guión de inicio actualizará los contextos de fichero en /dev y a continuación, si su sistema está configurado para arrancar en modo forzado, cambiará a ese modo.

Si necesita permanecer en modo permisivo de forma temporal, puede añadir nosetenforce como parámetro de inicio (después de enforcing=0) lo cual evitará el paso setenforce).

Usuarios de entornos gráficos

Si arranca en un entorno gráfico (es decir, si utiliza GDM, KDM u otro gestor gráfico de acceso al sistema), necesitará actualizar el(los) fichero(s) de configuración PAM de los gestores mediante las siguientes indicaciones:

Listado de Código 5.2: Ejemplo de actualización del fichero de configuración LXDM PAM

# /etc/pam.d/lxdm
# [...]
session    required     pam_loginuid.so
session    optional     pam_gnome_keyring.so auto_start
session optional     pam_selinux.so

Esto asegurará que el contexto de seguridad en el que ha accedido al sistema está definido correctamente. Actualizaremos los paquetes que definen esos ficheros PAM de forma adecuada, pero esto nos llevará algún tiempo.

3. Órdenes en SELinux

3.a. Información sobre las órdenes en SELinux

Introducción

A estas alturas, debería tener un sistema con SELinux habilitado (pero corriendo en modo permisivo (permissive) de modo que no obliga a cumplir las reglas de la directriz). Por lo que antes de introducirle en el mundo de SELinux y describir la forma de añadir más reglas sin perder la funcionalidad cuando cambie al modo forzado (enforcing), echaremos un vistazo rápido a algunas de las órdenes relacionadas con SELinux.

Comenzaremos con las órdenes de estado con las cuales puede obtener información global sobre el estado de SELinux (si está corriendo en modo forzado o no, conocer las versiones, etc).

Obteniendo el estado de SELinux

La primera orden de la que hablaremos es sestatus.

Listado de Código 1.1: Ejecutar sestatus

# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   permissive
Mode from config file:          permissive
Policy version:                 24
Policy from config file:        strict

La salida de esta orden indica que SELinux está habilitado y está trabajando actualmente en modo permisivo (permissive). También nos indica que el sistema está configurado para correr en modo estricto (strict) por lo que no existe el dominio unconfined_t.

La orden sestatus también ofrece una salida extendida si la ejecuta con la opción -v option. Cuando se indica esta opción, la orden devuelve los contextos de ficheros y procesos importantes:

Listado de Código 1.2: Correr sestatus -v

# sestatus -v
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        strict

Process contexts:
Current context:                staff_u:sysadm_r:sysadm_t
Init context:                   system_u:system_r:init_t
/sbin/agetty                    system_u:system_r:getty_t
/usr/sbin/sshd                  system_u:system_r:sshd_t

File contexts:
Controlling term:               staff_u:object_r:user_devpts_t
/sbin/init                      system_u:object_r:init_exec_t
/sbin/agetty                    system_u:object_r:getty_exec_t
/bin/login                      system_u:object_r:login_exec_t
/sbin/rc                        system_u:object_r:rc_exec_t
/usr/sbin/sshd                  system_u:object_r:sshd_exec_t
/sbin/unix_chkpwd               system_u:object_r:chkpwd_exec_t
/etc/passwd                     system_u:object_r:etc_t
/etc/shadow                     system_u:object_r:shadow_t
/bin/sh                         system_u:object_r:bin_t -> system_u:object_r:sh
ll_exec_t
/bin/bash                       system_u:object_r:shell_exec_t
/usr/bin/newrole                system_u:object_r:newrole_exec_t
/lib/libc.so.6                  system_u:object_r:lib_t -> system_u:object_r:li
b_t
/lib/ld-linux.so.2              system_u:object_r:lib_t -> system_u:object_r:ld
_so_t

Otra orden de estado general de SELinux es getenforce, el cual le permite ver rápidamente si su SELinux está corriendo en modo forzado (las directrices de SELinux se fuerzan), permisivo (las directrices de SELinux policies se comprueban y registran pero no se fuerzan) o deshabilitado (la directriz de SELinux no se carga y por lo tanto no se comprueba).

Listado de Código 1.3: Usar la orden getenforce

# getenforce
Enforcing

Obteniendo información de los objetos de SELinux

En la siguiente tabla se muestra la orden seinfo. Esta orden le permite consultar la directriz en ejecución definida para todos los objetos (tipos, roles, atributos, usuarios, booleanos,...).

Algunos usos comunes son los siguientes:

  • Comprobar si un dominio en particular se ha definido en su sistema (para el caso en que se esté preguntando si necesita cargar algún módulo adicional de directriz de SELinux o no).
  • Comprobar en qué dominios en particular puede estar un rol (para el caso en que se esté preguntando si las directrices SELinux permiten a sus usuarios normales cambiar a otro dominio).
  • Comprobar qué atributos están asignados a un dominio específico (o viceversa, qué dominios tienen activado un atributo en particular) ya que algunas reglas de directriz trabajan sobre atributos en lugar de dominios.

Como ejemplo, consultaremos si se conoce el dominio crontab_t, si el rol user_r puede usar el dominio contab_t y finalmente qué dominios tienen el atributo cron_spool_type activado.

Listado de Código 1.4: Usar seinfo

# seinfo -tcrontab_t
  crontab_t
# seinfo -ruser_r -x
  user_r
    Dominated Roles:
      user_r
    Types:
      [...]
      crontab_t
      [...]
# seinfo -acron_spool_type -x
  cron_spool_type
    user_cron_spool_t
    system_cron_spool_t

Consultando las reglas de directriz de SELinux

Una orden que se usa menudo es sesearch. Esta orden le permite consultar las reglas usadas en la directriz actual y es de gran ayuda cuando queremos averiguar si algo está permitido (o porqué no está permitido).

La orden sesearch se usa frecuentemente con un dominio origen (-s), dominio destino (-t) o ambos, la clase sobre la que quiere hacer la consulta permite reglas para: fichero, directorio, zócalo (socket), proceso,... y el privilegio que quiere consultar: lectura, escritura, transición, ejecución...

Por ejemplo, para averiguar qué dominios pueden escribir en los ficheros que tienen el dominio shadow_t:

Listado de Código 1.5: Consultar las reglas de concesión con sesearch

# sesearch -t shadow_t -c file -p write -A
Found 8 semantic av rules:
  [...]
  allow portage_t shadow_t : file { ioctl read write ... };
  allow useradd_t shadow_t : file { ioctl read write ... };
  ...

Observará que en algunas ocasiones los resultados están basados en los atributos en lugar de los dominios:

Listado de Código 1.6: Regla de permisión basada en atributo

  allow portage_t file_type : file { ioctl read write ... };

En este caso, al dominio origen (portage_t) se le permite escribir en los ficheros cuyo dominio tengan el atributo file_type activado. Si ya le va cogiendo el tacto a todo esto, se preguntará si la regla de arriba no es un fallo flagrante en la seguridad ya que todos los dominios de los ficheros tienen el atributo file_type activado. Sí y no, si echamos un vistazo a los dominios que tienen privilegios para escribir en los dominios file_type domains, se dará cuenta de que el único es portage:

Listado de Código 1.7: Consultar los dominios que tienen privilegios de escritura en fichero en dominios file_type

# sesearch -t file_type -c file -p write -A -d
Found 1 semantic av rules:
  allow portage_t file_type : file { ioctl read write ... };

Observe que tenemos una orden sin la opción -d y otra que usa esta opción. Cuando se indica -d, la búsqueda será realizada de forma exacta sin resolver los atributos. Cuando no se indica -d, entonces se resolverá el atributo. En el último ejemplo, el hecho de no indicar -d podría resultar en cientos de reglas de permisión: para cada dominio que tenga file_type activado, la búsqueda intenta encontrar reglas que permiten acceso de escritura al fichero en ese dominio en particular.

Otra interesante funcionalidad de la orden sesearch es mostrarle las reglas que se aplican dependiendo del estado de un booleano. Si quiere consultar un booleano en particular, utilice -b. Si quiere ver la lógica que usa la directriz, utilice, -C (y, sí, ambas opciones se pueden combinar).

A modo de ejemplo, comprobaremos qué permitimos (o denegamos) cuando el booleano global_ssp está habilitado.

Listado de Código 1.8: Comprobar la directriz respecto al booleano global_ssp

# sesearch -b global_ssp -A -C -d
Found 2 semantic av rules:
ET allow domain device_t : dir { getattr search open } ; [ global_ssp ]
ET allow domain urandom_device_t : chr_file { ioctl read getattr lock open } ; [ global_ssp ]

El prefijo que se muestra al comienzo de las líneas consiste en dos letras, las cuales están relacionadas con dos definiciones importantes:

  • ¿Está la regla habilitada (Enabled) o deshabilitada ( Disabled)?
  • ¿Necesita el booleano definirse a cierto (True) o falso (or False para habilitar la regla?

Obteniendo información del contexto de seguridad

Mientras esté realizando labores de administración y especialmente cuando esté comprobando si se está produciendo una denegación SELinux, es importante averiguar qué contexto de seguridad se está empleando para un recurso en particular. Afortunadamente, si se instala adecuadamente, Gentoo Hardened ha modificado algunas herramientas para obtener esta información usando sus herramientas estándar.

Para consultar el contexto de seguridad de un fichero, utilice ls -Z:

Listado de Código 1.9: Obtener el contexto de seguridad de un fichero

~$ ls -Z /etc/portage/make.conf
system_u:object_r:portage_conf_t /etc/portage/make.conf

Para obtener el contexto de seguridad de un proceso, utilice ps -Z:

Listado de Código 1.10: Obtener el contexto de seguridad de un proceso

# ps -Z $(pidof init)
LABEL                             PID TTY      STAT   TIME COMMAND
system_u:system_r:init_t            1 ?        Ss     0:00 init [3]

Para obtener el contexto de seguridad del usuario actual, utilice id -Z:

Listado de Código 1.11: Obtener el contexto de seguridad de un usuario

~$ id -Z
staff_u:staff_r:staff_t

3.b. Gestionar SELinux

Introducción

La gestión de los objetos de SELinux (booleanos, usuarios, puertos, contextos ...) se realiza en la mayoría de las ocasiones usando semanage. Debido a que esta aplicación ofrece la interfaz para varias configuraciones de SELinux, le dedicaremos una sección completa, aunque cubriremos también las órdenes que ofrecen una funcionalidad parecida (y que en algunas ocasiones son más fáciles de recordar).

Booleanos

Hemos hablado de los booleanos de SELinux anteriormente en este libro así como de las órdenes getsebool and setsebool. Con semanage puede también gestionar los booleanos y, como valor añadido, al listar los booleanos también se mostrará su descripción (aunque queda aún trabajo por realizar en este área).

Listado de Código 2.1: Listar los booleanos de SELinux disponibles

# semanage boolean -l
SELinux boolean                 Description

allow_ptrace            -> off  allow_ptrace
rsync_export_all_ro     -> off  rsync_export_all_ro

Nota: Como habrá notado, la mayor parte de las descripciones consisten únicamente en el nombre del booleano, sin embargo encontrará booleano con una mejor descripción cuando se haya familiarizado y/o instale más módulos de directriz de SELinux.

Puede definir el valor de un booleano con setsebool y semanage:

Listado de Código 2.2: Definir el valor de un booleano de SELinux

# semanage boolean -m --on -F user_dmesg

Usuarios y cuentas de SELinux

Los usuarios y cuentas de SELinux son diferentes de las de Unix. Las cuentas de SELinux le permiten asociar una cuenta Unix a un usuario SELinux:

Listado de Código 2.3: Listar las cuentas de SELinux

# semanage login -l
Login Name          SELinux User

__default__         user_u
root                root
swift               staff_u
system_u            system_u

El comportamiento por defecto es que los usuarios ingresan en el sistema como el usuario user_u de SELinux. Este usuario de SELinux es un usuario no administrador: no tiene privilegios específicos y se debe usar para para cada cuenta que nunca requiera elevar sus privilegios (por lo que no tendrá privilegios su o sudo para nada).

La cuenta que use para administrar su sistema debe ser mapeada al usuario SELinux staff_u (o su propio usuario con los roles apropiados). Esto se puede conseguir de la siguiente forma (ejemplo con la cuenta Unix ana):

Listado de Código 2.4: Permitir que 'ana' ingrese en el sistema como 'staff_u'

# semanage login -a -s staff_u ana

Importante: Asegúrese de que sea cual sea la cuenta que utilice para administrar su sistema, está mapeada al usuario staff_u o tiene la capacidad de cambiar al rol sysadm_r. Portage únicamente trabaja desde el rol sysadm_r.

Como se ha mencionado, los usuarios SELinux están configurados para que puedan unirse a uno o más roles. Para listar los roles disponibles, puede usar semanage user -l:

Listado de Código 2.5: Listar las asociaciones de cuentas a roles

# semanage user -l
SELinux User        SELinux Roles

root                staff_r sysadm_r
staff_u             staff_r sysadm_r
[...]

Gestionando puertos

Incluso los puertos (como el puerto 22 para SSH) están 'protegidos' por SELinux. Para echar un vistazo rápido de qué dominios están asignados a qué puertos (o rangos de puertos) utilice semanage port -l.

Listado de Código 2.6: Listar los puestos gestionados por SELinux

# semanage port -l | grep '22$'
ssh_port_t             tcp     22

3.c. Usar SELinux

Introducción

Hasta ahora hemos visto cómo obtener información relacionada con SELinux así como la gestión de los ajustes de SELinux. Sin embargo los usuarios de un sistema reforzado con SELinux necesitarán también saber algunas cosas acerca de cómo trabajar con SELinux, incluyendo (pero no limitándose a) roles y transiciones entre roles.

Cambiando de roles

Como una forma más del reforzamiento de un sistema de control de acceso, SELinux permite que algunos roles en particular estén en un conjunto de dominios. Si está utilizando un rol que no está permitido en un dominio en particular, no podrá usar ese dominio y se le denegará el acceso a las acciones asignadas a ese dominio.

Si sus usuarios estándar son todos usuarios user_u de SELinux (soportándose únicamente el rol user_r), entonces estos usuarios nunca necesitarán cambiar a otro rol (aunque tampoco se les permitiría). Sin embargo, se tiene que dejar bien claro como cambian entre roles los usuarios que son staff_u (u otros usuarios que tienen múltiples roles). Hemos visto cómo asociar estos usuarios al usuario correcto SELinux (mire Usuarios y cuentas de SELinux).

La orden que permite cambiar entre roles es newrole. Su uso es bastante lógico.

Listado de Código 3.1: Usar newrole

~$ newrole -r sysadm_r
Password: (Introduzca la contraseña del usuario)

Cuando se realiza una transición de rol, SELinux pedirá que el usuario vuelva a autenticarse usando su contraseña.

4. Permisivo, no confinado, deshabilitado o lo que no...

4.a. Estados de SELinux

Introducción

Cuando SELinux está disponible, normalmente se encontrará en uno de los tres estados de su sistema: deshabilitado, permisivo o forzado.

Deshabilitado

Cuando la orden getenforce devuelve "Disabled", entonces SELinux no está corriendo en su sistema. Incluso aunque está construido en su núcleo, definitivamente está deshabilitado. Su sistema correrá con los controles de acceso discrecionales normales (las reglas de permiso usuales para los entornos Linux estándar), sin embargo, los controles de acceso obligatorio no estarán activos.

Cuando SELinux está deshabilitado, esto significa que los ficheros, directorios, etc que se modifican o crean no obtendrán el contexto SELinux correcto que se les debe asignar. Cuando, más adelante, arranque su sistema con SELinux habilitado (permisivo o forzado), algunos problemas podrán surgir ya que el subsistema SELinux no conoce qué etiquetas tienen los ficheros (se usará una etiqueta por defecto que no es accesible por la mayoría de los dominios).

La mejor forma de continuar en este caso es iniciar en modo permisivo y etiquetar de nuevo todo el sistema de ficheros:

Listado de Código 1.1: Etiquetar de nuevo todo el sistema de ficheros

# rlpkg -a -r

Permisivo

Cuando se activa SELinux en modo permisivo (getenforce devuelve "Permissive"), entonces SELinux está habilitado y tiene cargada una directriz. Cada acceso que realiza un proceso se comprueba en las reglas de la directriz y, en caso de que un acceso no esté permitido, éste se registrará (a menos que la denegación esté marcada como dontaudit) pero no se prohibirá.

El modo permisivo es perfecto para familiarizarse con SELinux y preparar el sistema para el modo "forzado" que se empleará en el futuro. Mientras se trabaja en modo permisivo, las aplicaciones que no están integradas con SELinux funcionará como si SELinux no estuviera instalado. Esta situación es perfecta para validar si un problema es causado por SELinux o no: si estando en modo permisivo el problema aún persiste, entonces el problema no lo está causando SELinux.

Sin embargo, hay una salvedad: si la aplicación está integrada con SELinux (es decir, sabe que está corriendo en un entorno con SELinux activado y es capaz de hacer llamadas específicas de SELinux) puede que reaccione de forma diferente. Aunque esto es a menudo (pero no siempre) debido a unas malas prácticas en la programación, algunas aplicaciones comprueban si SELinux está activado y basan su flujo funcional en este resultado, independientemente si el estado es permisivo o forzado.

Para averiguar si una aplicación está integrada o no con SELinux, simplemente compruebe si está enlazada con libselinux (haciendo ldd o scanelf, esto es parte del paquete app-misc/pax-utils):

Listado de Código 1.2: Comprobar si /bin/ls está integrada con SELinux

# scanelf -n /bin/ls
 TYPE     NEEDED FILE
ET_DYN   libselinux.so.1,librt.so.1,libc.so.6   /bin/ls

Forzado

Si la orden getenforce devuelve "Enforcing", entonces SELinux esta cargado y actuará en base a la directriz. Cuando un proceso intenta realizar alguna actividad que no está permitida por la directriz, esta actividad será registrada (a menos que se defina un dontaudit) y no se permitirá la continuidad de la actividad. Este es el único modo en el que puede decir que SELinux está verdaderamente activo, ya que es el único momento en que la directriz está actuando.

Cambiando entre estados

Dependiendo de su configuración del núcleo Linux, puede conmutar entre estados utilizando los siguientes métodos. La configuración del núcleo puede, sin embargo, hacer que alguna de estas opciones estén deshabilitadas (por ejemplo, un sistema hardened que no permita deshabilitar SELinux de ningún modo).

Usar la orden setenforce:

Listado de Código 1.3: Conmutar entre forzado y permisivo

(Cambiar al modo permisivo)
# setenforce 0

(Cambiar al modo forzado)
# setenforce 1

Usar la opción de inicio enforcing del núcleo:

Listado de Código 1.4: Conmutar entre forzado y permisivo a través de opciones de inicio

(La siguiente línea del cargador del núcleo GRUB, permitiría iniciar en modo permisivo)
kernel /kernel-2.6.39-hardened-r8 root=/dev/md3 rootflags=data=journal enforcing=0

Usar la variable SELINUX /etc/selinux/config:

Listado de Código 1.5: Ajuste SELinux /etc/selinux/config

# cat /etc/selinux/config
# This file controls the state of SELinux on the system on boot.

# SELINUX can take one of these three values:
#       enforcing - SELinux security policy is enforced.
#       permissive - SELinux prints warnings instead of enforcing.
#       disabled - No SELinux policy is loaded.
SELINUX=enforcing

# SELINUXTYPE can take one of these four values:
#       targeted - Only targeted network daemons are protected.
#       strict   - Full SELinux protection.
#       mls      - Full SELinux protection with Multi-Level Security
#       mcs      - Full SELinux protection with Multi-Category Security
#                  (mls, but only one sensitivity level)
SELINUXTYPE=strict

Cuando quiera cambiar del modo permisivo al forzado, se recomienda hacerlo en el orden descrito arriba:

  1. En primer lugar inicie el sistema en modo permisivo, entre en él y verifique que su contexto es correcto (id -Z), luego conmute a forzado (setenforce 1). Puede comprobar ahora si su sistema está funcionado correctamente.
  2. A continuación, inicie el sistema con el parámetro del núcleo enforcing=1 (a menos que inicie con un initramfs, lea más arriba en este mismo manual). De esta forma, sus sistema se iniciará en modo forzado, si las cosas van mal, simplemente reinicie, elimine la opción y volverá al modo permisivo.
  3. Finalmente, edite /etc/selinux/config para que los cambios sean persistentes.

Modo Dominio permisivo

Puede también optar por marcar un solo dominio permisivo mientras ejecuta el resto del sistema en modo forzado. Por ejemplo, para marcar mplayer_t como un dominio permisivo (lo que implica que SELinux no forzará nada):

Listado de Código 1.6: Marcar mplayer_t como permisivo

# semanage permissive -a mplayer_t

Con la opción -d, puede eliminar la marca permisiva de nuevo.

4.b. Tipos de directriz SELinux

Introducción

Aparte del estado de SELinux, también se ofrecen distintos tipos de directriz. Estos tipos se diferencian entre ellos en que tienen características específicas de SELinux habilitadas o deshabilitadas. Dentro de Gentoo, se soportan tres (una cuarta también está disponible, como veremos): targeted, strict, mcs (y mls).

El tipo utilizado en un sistema se declara en /etc/selinux/config:

Listado de Código 2.1: La información SELINUXTYPE en /etc/selinux/config

# cat /etc/selinux/config
# This file controls the state of SELinux on the system on boot.

# SELINUX can take one of these three values:
#       enforcing - SELinux security policy is enforced.
#       permissive - SELinux prints warnings instead of enforcing.
#       disabled - No SELinux policy is loaded.
SELINUX=enforcing

# SELINUXTYPE can take one of these four values:
#       targeted - Only targeted network daemons are protected.
#       strict   - Full SELinux protection.
#       mls      - Full SELinux protection with Multi-Level Security
#       mcs      - Full SELinux protection with Multi-Category Security
#                  (mls, but only one sensitivity level)
SELINUXTYPE=strict

strict (sin dominios no confinados)

El tipo de directriz strict es aquél que se describió en capítulos anteriores y casualmente se trata del tipo más fácil de comprender. Con el tipo de directriz strict, todas y cada una de las aplicaciones que se ejecutan lo hacen en un dominio que tiene privilegios limitados. Aunque hay dominios altamente privilegiados, nunca son ilimitados en sus privilegios.

targeted (utilizando dominios no confinados)

El tipo de directriz targeted es similar al strict con un añadido importante: el soporte para dominios no confinados. Las aplicaciones (o usuarios) que corren en un dominio no confinado prácticamente no tienen límite en sus privilegios. Los dominios no confinados se utilizan normalmente para los usuarios y las aplicaciones de usuario, sin embargo, el inicio del sistema y otros dominios se marcan también como "no confinados".

La idea detrás de la directriz targeted es que los servicios orientados a red que están corriendo en dominios (confinados) regulares mientras que el resto utiliza el control de acceso discrecional estándar que ofrece Linux. Estos otros dominios corren como "no confinados".

mcs (utiliza categorías múltiples)

La introducción de mls y mcs ofrece la capacidad multi-tenancy: varias instancias de la misma aplicación pueden ejecutarse, pero cada instancia se debe confinar respecto a las otras (en lugar de tener todos los procesos en el mismo dominio y por lo tanto los mismo privilegios).

Un ejemplo sencillo es la virtualización: una máquina virtual que corre en el dominio qemu_t necesita privilegios de escritura en el fichero imagen que contiene el sistema operativo de la máquina virtual. Sin embargo, si correo dos máquinas, no deseará que una de ellas escriba en el fichero imagen de la otra y viceversa. Con dominios regulares, necesitará ofrecer este comportamiento. Con mcs, puede darle a cada instancia en ejecución una categoría específica (un número) y únicamente conceder privilegios de escritura al fichero de la máquina virtual con la categoría (el número) correcta.

mls (utilizando múltiples niveles de seguridad)

El tipo de directriz mls está disponible, pero aún no está soportado por Gentoo Hardened. Con este tipo de directriz, es posible ofrecer niveles de sensibilidad a ficheros y recursos así como a dominios. Los niveles de sensibilidad se pueden expresar mejor en los términos public, private, confidential o strictly confidential (público, privado, confidencial o estrictamente confidencial). Con MLS, puede marcar un fichero con un (o un conjunto) nivel de sensibilidad y asegurarse de que únicamente los dominios con el nivel de sensibilidad correcto puede acceder a él.

Conmutando entre tipos

No se recomienda conmutar entre tipos con frecuencia. En el mejor de los casos, elegimos un tipo de directriz en el momento de instalar y nos ajustamos a él. No es imposible (ni tampoco muy difícil) cambiar entre tipos.

Asegúrese de que su variable POLICY_TYPES en make.conf ya contiene el tipo de directriz destino y que se han reconstruido los paquetes de la directriz de SELinux. Si este no es su caso, edite la variable POLICY_TYPES para incluir la directriz destino y reconstruya todos los paquetes de directriz SELinux utilizando emerge $(qlist -IC sec-policy).

Ahora cambie sus sistema la modo permisivo (permissive) utilizando setenforce 0 o, si su sistema no permite el cambio de modo, edite /etc/selinux/config para que el sistema arranque en modo permisivo. Si no puede utilizar setenforce 0 entonces necesitará reiniciar ahora de modo que el sistema funcione en modo permisivo.

A continuación, edite /etc/selinux/config y cambie la variable SELINUXTYPE de la directriz actual a la nueva. Esto le indicará a SELinux que cargue la directriz correcta cuando se inicie el sistema.

Ahora vaya a los módulos construidos para la directriz en /usr/share/selinux ya que necesitamos cargar la nueva directriz (ya que actualmente el sistema está corriendo con la antigua). El ejemplo de abajo muestra como hacer esto si viene de un tipo de directriz estricto strict y quiere ir al tipo mcs:

Listado de Código 2.2: Cargar la directriz mcs

# cd /usr/share/selinux/mcs
# semodule -b base.pp -i $(ls *.pp | grep -v base.pp | grep -v unconfined.pp)

Ahora su sistema está corriendo con la directriz mcs cargada, pero observará que se producen múltiples denegaciones de acceso a la hora de realizar cualquier acción en el sistema de ficheros, ya que los ficheros de su sistema no están etiquetados correctamente: El tipo de directriz mcs requiere a las etiquetas tener una etiqueta de sensibilidad sobre ellas, lo cual no es el caso si utiliza la directriz estricta. Por lo tanto, reetiquetemos completamente el sistema de ficheros, incluyendo aquéllas localizaciones que podrían estar ocultas debido a que otros sistemas de ficheros se han montado sobre ellas.

Listado de Código 2.3: Reetiquetar completamente el sistema de ficheros

(Sustituya "strict" por su SELINUXTYPE, y utilice "lib" en lugar de "lib64" si tiene un sistema de 32 bits)
# rlpkg -a -r
# mount -o bind / /mnt/gentoo
# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/dev
# setfiles -r /mnt/gentoo /etc/selinux/strict/contexts/files/file_contexts /mnt/gentoo/lib64
# umount /mnt/gentoo

Para terminar, edite /etc/fstab y actualice los parámetros rootcontext= para incluir también una etiqueta de sensibilidad (en caso de que cambiara a mcs o mls) o ninguna (en caso de que cambiara a targeted o strict).

Listado de Código 2.4: Cambiar /etc/fstab

# Ejemplo cuando cambiamos de strict a mcs
tmpfs  /tmp  tmpfs  defaults,noexec,nosuid,rootcontext=system_u:object_r:tmp_t:s0  0 0

Una vez realizadas todas estas acciones, reinicie su sistema para asegurarse de que funciona correctamente (también la secuencia de arranque).

5. Modificar la directriz de SELinux en Gentoo Hardened

5.a. Lenguaje de la directriz SELinux

Introduction

Por defecto, Gentoo ofrece una directriz genérica aunque altamente controlada que es considerada como una buena directriz de comienzo para todos los usuarios. Sin embargo, el propósito detrás de los sistemas de Control de Acceso Obligatorio es que el administrador de seguridad tome el control. Por lo tanto, un manual sobre SELinux sin información acerca de como escribir directrices no estaría completo.

En este capítulo, hablaremos un poco sobre el lenguaje que hay detrás de las directrices SELinux y daremos algunos consejos sobre cómo crear sus propias directrices, roles, etc.

Construyendo un módulo SELinux

En primer lugar, antes de que descubramos el arte sobre la escritura de directrices SELinux, crearemos un pequeño módulo SELinux con una regla que podamos probar, construiremos el módulo y veremos si las cosas funcionan. A pesar de que estos pasos son muy fáciles de realizar, son muy importantes. Modificar la directriz SELInux tal y como la ofrece Gentoo se lleva a cabo de mejor forma a través de las directrices de módulo adicionales. Solo cuando la directriz principal (la directriz base) no es de su agrado, deberá plantearse el uso de una directriz completamente distinta.

Comencemos con un esqueleto para un módulo de directriz que llamaremos testmod. Utilice nombres simples para los módulos ya que la infraestructura de construcción es muy sensible a nombres especiales. Utilice únicamente letras de la a a la z y números, y nunca comience el nombre de un módulo con un número.

Listado de Código 1.1: Esqueleto de módulo de directriz

policy_module(testmod, 1.0.0)

Sí, eso es todo. Pero, como puede observar, está prácticamente vacío. Añadamos una regla que permita a un usuario normal (en el dominio user_t) leer ficheros ebuild (de tipo portage_ebuild_t).

Listado de Código 1.2: Módulo de directriz testmod

policy_module(testmod, 1.0.0)

require {
  type user_t;
  type portage_ebuild_t;
  class file { read open getattr };
  class dir { read search open getattr };
}

allow user_t portage_ebuild_t:file { read open getattr };
allow user_t portage_ebuild_t:dir { read search open getattr };

Como puede ver, algo tan simple como permitir a un usuario leer ficheros requiere unos cuantos privilegios. Los privilegios de directorio son necesarios para permitir a un usuario navegar por la estructura de árbol de Portage, mientras que los privilegios de fichero son necesarios para que el usuario puede acceder y abrir los ebuilds. Guarde este fichero con el nombre testmod.te.

Para construir la directriz y convertirla en un módulo binario que se pueda cargar en el almacén de directriz SELinux, podemos utilizar el fichero Makefile disponible en /usr/share/selinux/strict/include (sustituya strict por el tipo de directriz SELinux que esté utilizando).

Listado de Código 1.3: Construir un módulo de directriz binario

$ make -f /usr/share/selinux/strict/include/Makefile testmod.pp

El nombre de fichero (testmod.pp) es el nombre para el fichero binario SELinux destino. El Makefile buscará automáticamente el fichero testmod.te que tiene en su directorio de trabajo.

Deberá obtener como resultado un fichero llamado testmod.pp. Este fichero de módulo se puede ahora cargar en el almacén de directriz SELinux de la siguiente forma:

Listado de Código 1.4: Cargar un módulo binario

# semodule -i /path/to/testmod.pp

¡Enhorabuena! Acaba de construir su primer módulo de directriz SELinux. Si quiere deshabilitarlo, elimínelo usando semodule -r testmod.

Este método de construcción de una directriz (utilizando el Makefile y semodule) es algo que necesitará hacer cada vez que actualice la directriz SELinux en su sistema. El contenido de la directriz, sin embargo, cambia como veremos en el resto de este documento.

Obtener las interfaces de directriz SELinux

Para hacer más rápido el desarrollo de directrices, la directriz SELinux basada en la directriz de referencia utiliza interfaces para acceder a los privilegios dentro de un módulo. Si ha construido selinux-base-policy con USE="doc" entonces esta información está disponible en /usr/share/doc/selinux-base-policy-<versión>/html. Se recomienda tener esta información a mano ya que la mayoría de los desarrollos o actualizaciones se realizarán utilizando las interfaces que ofrece la directriz.

Si está interesado, puede también encontrar estas definiciones de interfaz en línea. Recuerde que este recurso en línea es únicamente la directriz de referencia y puede variar un poco de la disponible en Gentoo.

Usar interfaces de directriz

El uso de interfaces de directriz le permite actualizar la directriz con funciones más legibles. Por ejemplo, para permitir al dominio user_t domain llamar y utilizar aplicaciones Portage, el módulo podría tener el siguiente aspecto:

Listado de Código 1.5: Directriz ejemplo para permitir a user_t utilizar portage

policy_module(testmod, 1.0.0)

require {
  type user_t;
  role user_r;
}

portage_run(user_t, user_r)

Desde luego, esto hace que el dominio user_t tenga más privilegios que las reglas definidas anteriormente para leer fichero ebuild: permite al usuario llamar a portage, actualizar el sistema, etc. Desde luego, el usuario todavía necesita los permisos comunes de Linux apropiados (por lo que necesita pertenecer al grupo portage o poder convertirse en root). Por supuesto, no recomendamos conceder esto a un usuario regular ;-)

5.b. Módulos completos de directriz SELinux

Comprobando un módulo aislado

Teniendo en cuenta lo de arriba, podemos avanzar un poco más e investigar un módulo de directriz completo, con las reglas de forzado de tipos (fichero .te), los ficheros de contextos (.fc) e interfaces (.if).

Debería saber que escribir un módulo requiere familiarizarse con la aplicación. Es cuestión de simplemente esperar lo mejor: como administrador de seguridad, será el responsable de definir qué accesos se permiten y cuáles no. Si olvida alguno, la aplicación se podría romper en las manos de los usuarios. Pero, si añade demasiados, podría estar concediendo privilegios de los cuales se podría abusar en adelante. También sería más complicado hacer un seguimiento y eliminar privilegios más adelante ya que se dudaría de si ese privilegio es necesario o no.

En esta sección, no discutiremos como crear uno. Tenemos un excelente recurso: Desarrollo SELinux en Gentoo Hardened que le guía en ese proceso. Sin embargo, echaremos un vistazo a ese módulo completo para explicar otros aspectos del desarrollo de directrices.

Fichero de forzado de tipos

El fichero .te que escribimos anteriormente es un fichero de forzado de tipos. Se utiliza para definir reglas de acceso al módulo que se está construyendo, pero también, y más importante, define nuevos tipos (e incluso roles).

El ejemplo de abajo es un extracto de un módulo para la aplicación skype.

Listado de Código 2.1: Extracto de skype.te

policy_module(skype, 1.0.0)

type skype_t;
type skype_exec_t;
application_domain(skype_t, skype_exec_t)

type skype_home_t;
userdom_user_home_content(skype_home_t)

manage_dirs_pattern(skype_t, skype_home_t, skype_home_t)
manage_files_pattern(skype_t, skype_home_t, skype_home_t)

En el ejemplo de arriba, se declaran tres nuevo tipos: skype_t (que se usará para la aplicación), skype_exec_t (que es la etiqueta que se asigna al binario de la aplicación) y skype_home_t (que se utilizará para la ubicación del fichero de usuario ~/.Skype). También, se asignan al dominio skype_t algunos privilegios con respecto a la etiqueta skype_home_t (gestionar directorios y ficheros).

Fichero de contexto de ficheros

En el fichero .fc (cuya extensión significa file context file o fichero de contexto de ficheros), se definen los recursos del modulo (ficheros, directorios, zócalos, etc.). Una vez se carga el módulo, estas reglas se añaden de forma que el reetiquetado del sistema de ficheros asignará los contextos correctos a cada uno de los ficheros.

El ejemplo de abajo es un extracto del fichero de contexto de ficheros del módulo skype.

Listado de Código 2.2: Extracto de skype.fc

HOME_DIR/\.Skype(/.*)?    gen_context(system_u:object_r:skype_home_t,s0)
/opt/skype/skype       -- gen_context(system_u:object_r:skype_exec_t,s0)
/usr/bin/skype         -- gen_context(system_u:object_r:skype_exec_t,s0)

El formato del fichero tiene la siguiente sintaxis:

  1. La expresión regular que concuerda con el/los fichero/s y directorio/s afectados por esa línea.
  2. Un identificador opcional para diferenciar el tipo de objeto (fichero, directorio, zócalo o socket, enlace simbólico, etc.)
  3. Una línea gen_context que contiene el contexto que se debe asignar a el/los fichero/s y directorio/s.

Fichero de interfaz

En el fichero .if (que significa interface file o fichero de interfaz), se declaran las interfaces que pueden usar otros módulos. Es, mediante el uso de interfaces, la forma en la que una directriz definida se puede construir de forma adecuada sobre otros módulos existentes.

Una interfaz podría usarse para permitir a los usuarios llamar y ejecutar una aplicación. Por ejemplo, podemos encontrar en el módulo skype, la siguiente interfaz.

Listado de Código 2.3: Extracto de skype.if

interface(`skype_role',`
        gen_require(`
                type skype_t, skype_exec_t, skype_tmpfs_t, skype_home_t;
        ')

        role $1 types skype_t;

        domtrans_pattern($2, skype_exec_t, skype_t)

        allow $2 skype_t:process { ptrace signal_perms };

        manage_dirs_pattern($2, skype_home_t, skype_home_t)
        manage_files_pattern($2, skype_home_t, skype_home_t)
        manage_lnk_files_pattern($2, skype_home_t, skype_home_t)

        relabel_dirs_pattern($2, skype_home_t, skype_home_t)
        relabel_files_pattern($2, skype_home_t, skype_home_t)
        relabel_lnk_files_pattern($2, skype_home_t, skype_home_t)

        ps_process_pattern($2, skype_t)
')

A través de este skype_role, podemos permitir a los usuarios que llamen a skype, tal y como se indica en el fichero unprivuser.te (el cual define el dominio user_t):

Listado de Código 2.4: Extracto de unprivuser.te para llamar a skype

optional_policy(`
        skype_role(user_r, user_t)
')

La siguiente tabla muestra algunas interfaces comunes que se podrían utilizar. Recomendamos echar un vistazo a las interfaces disponibles cuando cree o mejore sus propios módulos. Asegúrese de elegir la interfaz que añade exactamente lo que necesita y nada más.

Plantillas
Sufijo Ejemplo Descripción
_template virt_domain_template(prefijo) No se trata realmente de una interfaz, las plantillas crean dominios adicionales basados en la información que se les facilita. Esto se realiza normalmente en plantillas de directriz ajustadas finamente con un (sub)conjunto de privilegios.
Transformaciones
Sufijo Ejemplo Descripción
miscfiles_cert_type(recurso) Las interfaces de transformación, generalmente añaden atributos específicos a recursos o dominios. Los atributos "transforman" el recurso dado en algo más. En el ejemplo dado, miscfiles_cert_type(recurso), asigna el atributo cert_type al recurso (y también lo marca como un fichero). Las interfaces como miscfiles_read_all_certs trabajan con estos atributos.
Interfaces de acceso
Sufijo Ejemplo Descripción
_<access>_<recurso> mta_getattr_spool(dominio) Concede acceso al dominio especificado al recurso mostrado. El recurso normalmente define también el tipo (como kudzu_getattr_exec_files: concede getattr sobre los ficheros kudzu_exec_t) a menos que sea obvio a partir del nombre, o cuando el recurso es un término más específico que el dominio. Puede incluir también dontaudit (como mta_dontaudit_getattr_spool).
_exec dmesg_exec(dominio) Concede a un dominio el derecho de ejecutar el fichero ejecutable del dominio dado (en el ejemplo, permite a "dominio" ejecutar dmesg_exec_t files), pero sin implicar una transición del dominio. En otras palabras, dmesg se ejecuta pero está confinado por los privilegios del dominio fuente.
_domtrans dmesg_domtrans(dominio) Concede a un dominio privilegios de ejecución y de realizar transiciones hacia el nuevo dominio. Esta interfaz es comúnmente utilizada para permitir a los dominios de aplicación realizar transiciones a otros dominios. En el ejemplo dado, dmesg se ejecuta con los privilegios del dominio dmesg_t.
_run netutils_run(dominio, rol) Concede a un rol y dominio dados los derechos para ejecutar y realizar transiciones hacia el dominio dado. Esto se concede normalmente a roles y dominios de usuario (ya existentes) y les da un conjunto de privilegios necesarios para interactuar de forma segura con el nuevo dominio (interactivo), tal como el acceso a un terminal.
_role xserver_role(rol, dominio) Permite al rol y dominio dado los permisos necesarios para realizar transiciones e interactuar con el dominio dado. Esta interfaz se ha mejorado con los privilegios para interactuar de forma más amplia con el dominio (y sus ficheros correspondientes), y normalmente se asigna a los nuevos usuarios y roles creados en la directriz (en lugar de mejorar los dominios y roles de usuario ya existentes).
_admin aide_admin(dominio) Concede al dominio dado los derechos para administrar el entorno del dominio objetivo. Esto normalmente involucra privilegios para gestionar y reetiquetar todos los ficheros, directorios, zócalos (sockets), etc. asociados.

5.c. Utilizar audit2allow

Introducción

Cuando lea los recursos disponibles en línea sobre SELinux, observará que hay muchas referencias a una herramienta llamada audit2allow. El propósito de esta herramienta es leer los mensajes de denegación AVC del registro de auditoría y transformarlos en un módulo de directriz que se pueda cargar. La ventaja aquí es que hace bastante más fácil la escritura de directrices. La parte mala es que la salida (a menos que utilice la opción -R) no se puede utilizar en el fichero Makefile que utilizamos anteriormente para construir módulos.

Otra desventaja es que la herramienta no actúa inteligentemente ante los cambios. Acepta las denegaciones a ciegas y las trata como si debieran ser permitidas en lugar de investigar si se deberían asignar otros contextos al fichero, etc.

Usar audit2allow

El uso de audit2allow es bastante simple. Se le envían las denegaciones que quiere corregir y se almacena el resultado en un fichero .te. Puede entonces convertir este fichero a un formato intermedio que se puede traducir a un fichero .pp para cargarlo finalmente con semodule.

Por ejemplo, para capturar todas las denegaciones y transformarlas en sentencias válidas para las denegaciones relacionadas con firefox:

Listado de Código 3.1: Generar una nueva directriz utilizando audit2allow

# grep firefox /var/log/avc.log | audit2allow -m firefoxmod > firefoxmod.te
# checkmodule -m -o firefoxmod.mod firefoxmod.te
# semodule_package -o firefoxmod.pp -m firefoxmod.mod
# semodule -i firefoxmod.pp

El nombre del módulo (indicado mediante la opción -m) debe ser sencillo: únicamente utilice caracteres ([a-z]) y números ([0-9]), y comience el nombre del módulo con un carácter.

5.d. Usar selocal

Introducción

En algunas ocasiones necesitamos realizar un pequeño ajuste aquí y alguna adición allá a lo largo del tiempo. Si utilizamos audit2allow, esto+ podría resultar en algunos módulos separados a lo largo del tiempo - midirectriz1, midirectriz2, ... Después de un tiempo, no sabremos qué reglas hemos añadido, dónde y porqué razón.

Para dar soporte a esto en el futuro, Gentoo ofrece una herramienta que le permite añadir pequeños conjuntos de reglas a lo largo del tiempo, y también documentar las razones por las que se añadieron y de esta forma simplificar la gestión de estas reglas.

Usar selocal

A partir de policycoreutils-2.1.13-r11, se dispone de una nueva orden llamada selocal. Esta orden permite a los usuarios añadir de forma fácil reglas de directriz SELinux adicionales a la directriz local si tener que pasar por la penuria de construir y mantener sus propios ficheros .te. En lugar de esto, esta orden hace todo el trabajo.

Las reglas que se añaden a la directriz local (de ahí el nombre, selocal) se pueden acompañar de un pequeño comentario para permitir a los usuarios describir porqué se ha realizado cierto cambio (o para hacer referencia a una incidencia en el bugzilla de Gentoo).

Listado de Código 4.1: Añadir una regla a la directriz local

# selocal -a "rpcbind_stream_connect(sysadm_t)" -c "Poder llamar a exportfs (NFS)"
# selocal --build --load

Con --list puede ver las reglas de directriz local que se han añadido actualmente y con --delete se pueden eliminar de la directriz local. Cuando quiera que los cambios tengan efecto, ejecute selocal --build --load para construir la nueva directriz local y cargarla en memoria.

5.e. Crear roles adicionales

Crear el rol y el dominio

Si desea crear roles adicionales en el sistema, en primer lugar necesitará crear un módulo SELinux que cree ese rol, a la vez que su dominio principal. Abajo se muestra un ejemplo muy sencillo para un rol de administración de base de datos, el cual ofrecemos a través del paquete sec-policy/selinux-dbadm:

Listado de Código 5.1: Ejemplo de definición de dbadm_r y dbadm_t

policy_module(dbadm, 1.0.0)

#######################################
#
# Declaraciones
#

role dbadm_r;

# Crear un dominio de usuario (dbadm_t)
userdom_base_user_template(dbadm)

#######################################
#
# Directriz local dbadm
#

allow dbadm_t self:capability { dac_override dac_read_search sys_ptrace };

files_dontaudit_search_all_dirs(dbadm_t)
files_delete_generic_locks(dbadm_t)
files_list_var(dbadm_t)

selinux_get_enforce_mode(dbadm_t)

logging_send_syslog_msg(dbadm_t)

userdom_dontaudit_search_user_home_dirs(dbadm_t)

optional_policy(`
       # Conceder al usuario privilegios de administración de PostgreSQL
       # (sobre todos los procesos)
       postgresql_admin(dbadm_t, dbadm_r)
')

Construya y cargue el módulo y verifique que el rol está disponible:

Listado de Código 5.2: Construya y verifique

# make -f /usr/share/selinux/strict/include/Makefile dbadm.pp
# semodule -i dbadm.pp
# seinfo -r | grep dbadm
  dbadm_r

Asignar el rol a los usuarios

A continuación, asigne a los usuarios el rol que acaba de crear. Puede hacerlo con usuarios SELinux ya existentes, pero, en este caso, crearemos un usuario SELinux adicional para el rol.

Listado de Código 5.3: Conceder el rol al usuario

(Crear un nuevo usuario SELinux llamado dbadm_u y concederle el rol dbadm_r)
# semanage user -a -R "staff_r dbadm_r system_r" dbadm_u

Lo siguiente es mapear el usuario(s) a este usuario SELinux.

Listado de Código 5.4: Mapear un conjunto de usuarios al usuario dbadm_u

# semanage login -a -s dbadm_u david
# semanage login -a -s dbadm_u laura

También se debe cargar la siguiente directriz para dar soporte a la transición hacia el rol dbadm_r para el rol staff_r:

Listado de Código 5.5: Permitir la transición a dbadm_r

dbadm_role_change(staff_r)

En la primera orden semanage, en la que creamos el usuario dbadm_u, puede observarse que le hemos concedido el rol system_r. Esto se debe a que al usuario se le concede el rol postgresql_admin, permitiendo a ese usuario la manipulación del guión de inicio de postgresql:

Listado de Código 5.6: Usario reiniciando el servicio postgresql

$ ls -Z /etc/init.d/postgresql
system_u:object_r:postgresql_initrc_exec_t    /etc/init.d/postgresql
$ sudo -r dbadm_r -t dbadm_t /etc/init.d/postgresql restart

Gracias al soporte SELinux en sudo, puede también mencionar el rol y tipo en el fichero sudoers:

Listado de Código 5.7: Usar el fichero sudoers para roles específicos

david ALL=(ALL) ROLE="dbadm_r" TYPE="dbadm_t" NOPASSWD: /etc/init.d/postgresql [a-z]*

Con este ajuste, el usuario puede ejecutar simplemente sudo /etc/init.d/postgresql restart.

Utilizando sudo de forma correcta, se puede conceder al usuario derechos completos de administración sobre un demonio (incluyendo la edición de ficheros), con bastante menor riesgo de que el usuario pueda escalar sus privilegios a un rol administrativo con más privilegios sobre el sistema.

La idea detrás de este enfoque es que el usuario permanezca en su dominio principal (como staff_t) pero que se le permita realizar acciones administrativas a través de sudo lo que le permite (de forma temporal) realizar la transición al rol dbadm_r. role.

6. Solucionando problemas con SELinux

6.a. No se puede cargar la directriz de SELinux

Descripción del problema

Si observa que SELinux no está funcionando, puede ejecutar sestatus para ser informado rápidamente si SELinux está habilitado y cargado o no. Si obtiene la siguiente salida, entonces ninguna directriz de SELinux se ha cargado:

Listado de Código 1.1: Salida de sestatus

SELinux status:                disabled

Si éste es el caso, continúe leyendo esta sección para averiguar cómo corregir esta situación.

No hay ninguna directriz instalada

Una raíz potencial de este problema es que no hay ninguna directriz con la que comenzar. Eche un vistazo a /usr/share/selinux/strict o a /usr/share/selinux/targeted (dependiendo de su configuración) y busque un fichero llamado base.pp. Si no existe este fichero, necesitará instalar la directriz base. Esta directriz se ofrece con el paquete sec-policy/selinux-base-policy, pero es mejor leer el capítulo relacionado con la Instalación de Gentoo SELinux / Conversión ya que podría pasar por alto detalles importantes.

La directriz no se ha cargado

Si existe el fichero base.pp en /usr/share/selinux/strict (o en targeted/), eche un vistazo a /etc/selinux/strict/policy. Esta localización también debería contener un módulo de directriz base.pp (cuando se carga una directriz de SELinux, se copia desde la primera localización a la segunda).

Si no existe el fichero base.pp, instale la directriz y cárguela:

Listado de Código 1.2: Instalar la directriz base

~# semodule -n -B

Esto es una operación que se realiza solo en una ocasión. Una vez instalada y cargada, ésta será recargada en cada reinicio.

Init no puede cargar la directriz SELinux

Durante el inicio del sistema, el proceso init es el responsable de cargar e interactuar con la directriz SELinux en memoria. Si init no soporta SELinux, su entorno no dispondrá de soporte para SELinux.

Para verificar si init soporta SELinux, necesitamos comprobar si utiliza el objeto compartido libselinux.so:

Listado de Código 1.3: Comprobar si init soporta SELinux

~# ldd /sbin/init
        linux-vdso.so.1 =>  (0x00006ace30e84000)
        ( Debería ver algo similar a la siguiente línea: )
        libselinux.so.1 => /lib/libselinux.so.1 (0x00006ace30a46000)
        libc.so.6 => /lib/libc.so.6 (0x00006ace306e9000)
        libdl.so.2 => /lib/libdl.so.2 (0x00006ace304e5000)
        /lib64/ld-linux-x86-64.so.2 (0x00006ace30c68000)

Si éste no es el caso, asegúrese de que emerge --info muestra que el ajuste USE selinux está en su sitio y reinstale sys-apps/sysvinit. Si este ajuste no está definido, compruebe su perfil Gentoo y asegúrese de que apunta a un perfil selinux/v2refpolicy/....

El almacén de directices está corrupto

Si aparecen problemas en el inicio del sistema o en operaciones semodule que fallan con problemas en la carga pero no se puede resolver con la solucón de arriba, entonces necesitará reinstalar las directrices una vez eliminado el almacén corrupto.

Listado de Código 1.4: Recuperarse de un almacén corrupto

~# semodule -n -B
libsemanage.semanage_load_module: Error while reading from module file
/etc/selinux/targeted/modules/tmp/base.pp. (No such file or directory)

~# setenforce 0
~# mv /etc/selinux/targeted /etc/selinux/targeted.old
~# FEATURES="-selinux" emerge -1av $(qlist -IC sec-policy)
~# restorecon -R /etc/selinux

Esto desactivará efectivamente el almacén corrupto actual de la directriz de SELinux y utilizará Portage para reinstalar todos los paquetes de directriz que se han instalado en el sistema. Cuando haya terminado, los contextos de fichero de /etc/selinux serán restaurados, después de lo cual podrá continuar.

6.b. No se puede ingresar en el sistema

Descripción del problema

Si no puede ingresar en el sistema en una situación en particular (en remoto, en local, como root, como usuario regular,...) puede que se esté encontrando con algún problema sin mucha importancia. Sin embargo, para resolverlo tendrá que ingresar en el sistema como sysadm_r de un modo u otro.

Si no puede ingresar como un usuario sysadm_r, deshabilite SELinux (arranque con enforcing=0) de este modo no se realiza ningún forzado SELinux. Los cambios que haga en modo permisivo son igual de efectivos que en el modo forzado (enforcing).

Contexto incorrecto

En la mayoría de los casos encontrará que el problema es un contexto de seguridad incorrecto. Ejecute sestatus -v y compare los contextos de proceso o los contextos de fichero que observe con los dados en la siguiente tabla.

Proceso Contexto Si el contexto no es el adecuado...
Contexto init system_u:system_r:init_t En primer lugar, verifique que el propio init está correctamente etiquetado. Compruebe la salida de la ejecución anterior de la orden sestatus -v para el fichero /sbin/init y asegúrese de que está ajustado a system_u:object_r:init_exec_t. Si este no es el caso, etiquete de nuevo sys-apps/sysvinit usando rlpkg sysvinit. Haga las mismas comprobaciones que se realizan en la sección No se puede cargar la directriz de SELinux . Reinicie su sistema e inténtelo de nuevo.
Contexto agetty system_u:system_r:getty_t Asegúrese de que el binario /sbin/agetty esta etiquetado como system_u:object_r:getty_exec_t. Si no es así, etiquete de nuevo el paquete sys-apps/util-linux usando rlpkg util-linux. A continuación reinicie todos los procesos agetty usando pkill agetty (estos procesos se pondrán en marcha de nuevo automáticamente).
Fichero Contexto Si el contexto no es el adecuado...
/bin/login system_u:object_r:login_exec_t El binario login forma parte de sys-apps/shadow. Ejecute rlpkg shadow para etiquetar de nuevo los ficheros de este paquete y reintente el ingreso en el sistema.
/sbin/unix_chkpwd system_u:object_r:chkpwd_exec_t Este binario es parte del paquete sys-libs/pam y SSH lo utiliza cuando se configura para que use PAM a la hora de realizar la autenticación de usuarios. Etiquete de nuevo el paquete usando rlpkg pam e intente de nuevo el ingreso en el sistema.
/etc/passwd system_u:object_r:etc_t Tanto /etc/passwd como /etc/shadow deben estar etiquetados correctamente, de lo contrario PAM no podrá autenticar a ningún usuario. Etiquete de nuevo los ficheros con restorecon /etc/passwd /etc/shadow e intente de nuevo el ingreso en el sistema.
/etc/shadow system_u:object_r:shadow_t
/bin/bash system_u:object_r:shell_exec_t El intérprete de comandos del usuario (en este caso, bash) se debe etiquetar correctamente de modo que el usuario pueda cambiar al dominio de usuario cuando ingrese en el sistema. Para hacer esto, etiquete de nuevo el paquete app-shells/bash usando rlpkg bash. Entonces puede intentar de nuevo el ingreso en el sistema.

6.c. No se puede hacer emerge de ningún paquete (OSError: [Errno 22] Invalid argument)

Descripción del problema

Cuando se intenta instalar software con Portage, se obtiene un volcado enorme de la pila de python y finalmente el mensaje de error OSError: [Errno 22] Invalid argument:

Listado de Código 3.1: Volcado de la traza de la pila cuando falla portage al instalar software

Traceback (most recent call last):
  File "/usr/bin/emerge", line 43, in <module>
    retval = emerge_main()
  File "/usr/lib64/portage/pym/_emerge/main.py", line 1906, in emerge_main
    myopts, myaction, myfiles, spinner)
  File "/usr/lib64/portage/pym/_emerge/actions.py", line 437, in action_build
    retval = mergetask.merge()
...
  File "/usr/lib64/portage/pym/portage/package/ebuild/doebuild.py", line 104, in _doebuild_spawn
    return spawn(cmd, settings, **kwargs)
  File "/usr/lib64/portage/pym/portage/package/ebuild/doebuild.py", line 1255, in spawn
    return spawn_func(mystring, env=mysettings.environ(), **keywords)
  File "/usr/lib64/portage/pym/portage/_selinux.py", line 105, in wrapper_func
    setexec(con)
  File "/usr/lib64/portage/pym/portage/_selinux.py", line 79, in setexec
    if selinux.setexeccon(ctx) < 0:
OSError: [Errno 22] Invalid argument

Contexto erróneo

El error de arriba se produce cuando se lanza portage (mediante emerge) y no nos encontramos en el contexto sysadm_t. Puede verificar esto con id -Z:

Listado de Código 3.2: Comprobando el contexto actual

~# id -Z
system_u:system_r:local_login_t

Portage fallarán mientras el contexto utilizado no sea sysadm_t. Esto es debido a que Portage quiere cambiar su contexto de ejecución de portage_t a portage_sandbox_t, sin embargo no puede conseguirlo (para empezar, no está en portage_t debido a que el usuario que lanzó Portage no está en sysadm_t).

Por favor, compruebe la sección No se puede ingresar en el sistema de arriba en primer lugar. También, asegúrese de que puede hacer dispatch-conf o etc-update después de instalar SELinux de modo que se actualice /etc/pam.d/system-login con las llamadas correctas a pam_selinux.so.

Forzar la instalacilón

Si necesita forzar a Portage para que continúe a pesar de todo (por ejemplo, se encontraba en medio de una instalación de SELinux por lo que no puede resolver esas cuestiones ahora), ejecute la orden emerge pero con FEATURES="-selinux". Esto deshabilitará efectivamente la integración de SELinux en Portage y permitirá continuar con la instalación del software.

Listado de Código 3.3: Correr emerge sin soporte selinux

~# FEATURES="-selinux" emerge -u world

¡Asegúrese de que etiqueta de nuevo todo el sistema de ficheros después de aplicar este enfoque!. Portage no etiquetará correctamente los ficheros instalados en el sistema si deshabilita el soporte SELinux. Para etiquetar de nuevo todo el sistema de ficheros, utilice rlpkg -a -r.

7. Historial de cambios

7.a. Introducción

Acerca de este documento

Este documento ofrece una vista rápida de todos los cambios en SELinux documentados y que se han realizado en fechas particulares y que por tanto pueden ser de importancia para los usuarios hagan un seguimiento de los mismos.

Los cambios que únicamente afectan a los usuarios con instalaciones de prueba (~arch) se documentarán abajo y se moverán más arriba en el documento cuando se realice su estabilización. Sin embargo, es posible que estos cambios se "corrijan" de forma automática y por tanto se eliminen de esta página.

7.b. Vista rápida de los cambios para usuarios de instalaciones estables

19/04/2013 - Presentar la orden selocal

Con la aparición de policycoreutils-2.1.13-r11 y versiones posteriores, se dispone de una nueva orden llamada selocal. Esta orden permite a los usuarios añadir fácilmente a la directriz local, reglas de directriz SELinux adicionales sin tener que realizar la tarea de mantener y construir sus propios ficheros .te. En lugar de eso, esta orden hace todo el trabajo.

Las reglas que se añaden a la directriz local (de ahí su nombre, selocal) se pueden acompañar de un pequeño comentario para que los usuarios describan porqué realizan determinado cambio (o para hacer referencia a un identificador de incidencia en el bugzilla de Gentoo).

Listado de Código 2.1: Añadir una regal a la directriz local

# selocal -a "rpcbind_stream_connect(sysadm_t)" -c "Permitir las llamadas a a exportfs (NFS)"
# selocal --build --load

Con --list se muestran las reglas que se han añadido a la directriz local, y con --delete se pueden eliminar de la directriz local. Cuando quiera que los cambios tengan efecto, ejecute selocal --build --load para construir la nueva directriz local y cargarla en memoria.

16/04/2013 - Presentar el guión de inicio selinux_gentoo

Con el paquete policycoreutils-2.1.13-r8 y los posteriores, ofrecemos nuestro propio guión de inicio selinux_gentoo, el cual incluye el soporte necesario para los usuarios con initramfs en sus sistemas, también reinicia los contextos de los recursos generados dinámicamente (en pseudo sistemas de ficheros) que son distintos de los ajustes por defecto.

El primer usuario a tener en cuenta es /sys/devices/system/cpu/online el cual obtiene labeled cpu_online_t (desde la revisión 13 de la directriz SELinux, o cuando se están utilizando ebuilds live para la directriz).

El guión de inicio también restaurará por defecto los contextos de todos los dispositivos /dev (a menos que el sistema se inicie con la opción norestorecon) y cambiará al modo forzado (enforcing) si /etc/selinux/config tiene definido SELINUX=enforcing y el usuario inició el sistema con enforcing=0 (a menos que inicie con la opción nosetenforce).

Esto significa que ahora se recomienda a los usuarios que añadan este guión al nivel de ejecución boot:

Listado de Código 2.2: Añadir selinux_gentoo al nivel de ejecución

# rc-update add selinux_gentoo boot

04/12/2012 - Presentar USE=unconfined

A partir de la versión selinux-base-2.20120725-r9, se da soporte al ajuste USE=unconfined. Cuando éste se habilita, configurará su directriz SELinux para dar soporte a dominios no confinados. Si su directriz es targeted, este comportamiento estará implícito, mientras que la directriz strict no considerará este ajuste USE de ningún modo (no activará dominios no confinados en strict).

El soporte de este ajuste USE, nos permite diferenciar entre dominios no confinados y dominios regulares cuando utilizamos los tipos de directriz mls o mcs. Cuando está definido, se construirá también el paquete selinux-unconfined, y el módulo se cargará, e igualmente, se actualizará el fichero de directriz seusers (el cual contiene los mapeas de los dominios por defecto para los usuarios) para utilizar el usuario SELinux unconfined_u para root y otros usuarios.

16/08/2012 - Añadir el rol system_r a los administradores

Desde la versión selinux-base-2.20120725-r3 y en las posteriores, los guiones de inicio ahora ofrecen soporte al enfoque "etiquetado" (labeled) del guión de inicio ofrecido por el equipo de desarrollo principal. Esto implica que los servicios cuyo guión de inicio siguen la convención de nombres <domain>_initrc_exec_t se pueden asignar ahora a usuarios específicos (permitiendo a éstos gestionar servicios sin necesidad de concederles privilegios de administración del sistema).

Lo malo de este enfoque es que el propio administrador del sistema (que utiliza el dominio sysadm_t) ahora necesita que se le conceda el privilegio de gestionar esos servicios. Y el hecho de concederle este privilegio implica que el usuario SELinux (sea root o staff_u) necesita que se le conceda el rol system_r:

Listado de Código 2.3: Conceder el rol system_r

# semanage user -m -R "staff_r sysadm_r system_r" root
# semanage user -m -R "staff_r sysadm_r system_r" staff_u

24/06/2012 - Definición de /run en fstab

Se necesita montar la localización /run con el contexto var_run_t. Para hacer esto, se debe modificar /etc/fstab según las instrucciones dadas en Ajustar los contextos del sistema de ficheros.

26/05/2012 - Soporte de initramfs

Los usuarios que inician su sistema con un initramfs necesitarán iniciar en primer lugar en modo permisivo, y a continuación cambiar a modo forzado. Esto se puede realizar de forma automática utilizando un guión de inicio, tal y como se documenta en Usuarios de Initramfs.

26/05/2012 - Soporte para gestores gráficos de ingreso en el sistema

Los usuarios que inicien en un entorno gráfico (como GDM) tendrán que editar sus ficheros de configuración PAM de forma adecuada para dar soporte a las definiciones de contexto de seguridad de SELinux. Esto está documentado en Usuarios de entornos gráficos.

18/05/2012 - Ya no es necesario configurar sandbox

La edición previa de la documentación de /etc/sandbox.conf para permitir la escritura abierta de /sys/fs/selinux/context se puede eliminar ya que el perfil de SELinux lo hace ahora de forma automática.

29/04/2012 - No es necesario editar los guiones lvm-start/stop

Cuando el usuario instala las nuevas directrices estables 2.20120215, la edición documentada de /lib/rcscripts/addons/lvm-st*.sh ya no es necesaria.

21/02/2012 - La línea de montaje /dev en fstab ya no es necesaria

La documentación previa de la línea de montaje /dev mount in /etc/fstab ya no es necesaria ya que util-linux-2.20.1-r1 se ha marcado como estable (la cual ya contiene la corrección correcta).

10/12/2011 - Depreciación de los perfiles selinux/v2refpolicy/*

Los antiguos perfiles de SELinux (los que comienzan por selinux/v2refpolicy) ya no tienen soporte. Se recomienda encarecidamente a los usuarios que cambien a los nuevos perfiles (los que terminan en /selinux).

22/07/2011 - Introducción del soporte para MLS/MCS

Actualmente ofrecemos soporte para MLS y MCS, para los tipos de directriz SELinux targeted y strict SELinux. Cuando utilice MLS o MCS, necesitará actualizar la entrada /tmp en su /etc/fstab para que utilice rootcontext=system_u:object_r:tmp_t:s0 (observe el :s0 al final).

7.c. Vista rápida para los usuarios de instalaciones de prueba (~Arch)

07/07/2013 - Presentar el soporte para mcstrans

Cuando la directriz SELinux está habilitada para MLS (MCS o MLS), entonces tenemos la opción de gestionar las categorías. Las categorías nos permiten "etiquetar" recursos y asegurarnos de que solo los procesos que tienen el conjunto categoría asignado a ellos, pueden leer o manipular los recursos.

Para SELinux, las categorías son números que comienzan por c0 (categoría cero) hasta el máximo que se utilice en la directriz:

Listado de Código 3.1: Comprobar el número máximo de categorías

$ seinfo | grep Categories
  Sensitivities:      1   Categories:       1024

Sin embargo, para la mayoría de los adminstradores, esto no es muy eficiente. Para dar soporte a formatos más legibles por los humanos. SELinux ofrece soporte a traducciones de categorías (e incluso a traducciones sensibles). Dentro de un fichero de configuración (setrans.conf en el directorio principal de configuración, como /etc/selinux/mcs) los administradores pueden introducir conjuntos comunes sensibles y rangos. La herramienta chcat se puede utilizar entonces para listar éstos:

Listado de Código 3.2: Listar las traducciones de los rangos de sensibilidad

# chcat -L
s0                             SystemLow
s0-s0:c0.c1023                 SystemLow-SystemHigh
s0:c0.c1023                    SystemHigh

Par habilitar estas traducciones, cree el fichero de traducción apropiado (del cual puede encontrar numerosos ejemplos en /usr/share/doc/policycoreutils-*/mcstrans) y a continuación arranque el serviciomcstransd.

Listado de Código 3.3: Arrancar el servicio mcstransd

# rc-service mcstransd start

Eso es todo, si ahora miramos a los contextos, veremos los rangos traducidos.

Listado de Código 3.4: Listar contextos para ver los rangos traducidos

# ls -lZ seusers
-rw-r--r--. root root system_u:object_r:selinux_config_t:SystemLow seusers

Imprimir

Página actualizada 9 de abril, 2014

Sumario: Este es el manual de SELinux para Gentoo.

Chris PeBenito
Autor

Sven Vermeulen
Autor

Chris Richards
Autor

José María Alonso
Traductor

Donate to support our development efforts.

Copyright 2001-2014 Gentoo Foundation, Inc. Questions, Comments? Contact us.