[ << ]
[ < ]
[ 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:
-
La expresión regular que concuerda con el/los fichero/s y directorio/s
afectados por esa línea.
-
Un identificador opcional para diferenciar el tipo de objeto (fichero,
directorio, zócalo o socket, enlace simbólico, etc.)
-
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. 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 4.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 4.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 4.3: Conceder el rol al usuario |
# 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 4.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 4.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 4.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 4.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 ]
[ > ]
[ >> ]
El contenido de este documento, a no ser que se especifique
expresamente, está registrado bajo los términos de la licencia
CC-BY-SA-2.5. Se aplican las
Pautas de
Utilización del logotipo y nombre de Gentoo.
|