Gentoo Logo

Renuncia de responsabilidad: Este documento ya no es válido y carece de soporte.


[ << ] [ < ] [ Inicio ] [ > ] [ >> ]


5. Modificar la directriz de SELinux en Gentoo Hardened

Contenido:

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.


[ << ] [ < ] [ Inicio ] [ > ] [ >> ]


Imprimir

Ver completo

Página actualizada 7 de julio, 2013

Sumario: 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.

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.