217 lines
14 KiB
Plaintext
217 lines
14 KiB
Plaintext
¿Qué es SELinux?
|
|
SELinux o Security Enhanced Linux es un software de seguridad desarrollado por la NSA, asociado al kernel de Linux que permite o deniega el acceso de las aplicaciones a ciertos servicios, como puede ser un archivo o un puerto de comunicaciones, en función de las políticas de seguridad configuradas.
|
|
|
|
SELinux es complejo, por lo que en esta guía vamos a ver algunos conceptos básicos de funcionamiento de SELinux acompañados de ejemplos.
|
|
|
|
Haz clic para aceptar las cookies de márketing y permitir este contenido
|
|
Habilitar SELinux
|
|
SELinux viene preinstalado y habilitado por defecto, diría que, en todas las distribuciones de Linux. Lo podemos comprobar en el archivo /etc/selinux/config:
|
|
|
|
[root@server1 ~]# cat /etc/selinux/config
|
|
|
|
# This file controls the state of SELinux on the system.
|
|
# 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 three values:
|
|
# targeted - Targeted processes are protected,
|
|
# minimum - Modification of targeted policy. Only selected processes are protected.
|
|
# mls - Multi Level Security protection.
|
|
SELINUXTYPE=targeted
|
|
|
|
|
|
[root@server1 ~]#
|
|
Si queremos habilitarlo o deshabilitarlo momentáneamente en caliente lo haremos mediante línea de comandos:
|
|
|
|
[root@server1 ~]# sestatus
|
|
SELinux status: enabled
|
|
SELinuxfs mount: /sys/fs/selinux
|
|
SELinux root directory: /etc/selinux
|
|
Loaded policy name: targeted
|
|
Current mode: enforcing
|
|
Mode from config file: enforcing
|
|
Policy MLS status: enabled
|
|
Policy deny_unknown status: allowed
|
|
Memory protection checking: actual (secure)
|
|
Max kernel policy version: 33
|
|
[root@server1 ~]# setenforce 0
|
|
[root@server1 ~]# sestatus
|
|
SELinux status: enabled
|
|
SELinuxfs mount: /sys/fs/selinux
|
|
SELinux root directory: /etc/selinux
|
|
Loaded policy name: targeted
|
|
Current mode: permissive
|
|
Mode from config file: enforcing
|
|
Policy MLS status: enabled
|
|
Policy deny_unknown status: allowed
|
|
Memory protection checking: actual (secure)
|
|
Max kernel policy version: 33
|
|
[root@server1 ~]#
|
|
Fijaos en cómo ha cambiado el valor de la directiva «current mode». Para volverlo a habilitar, utilizaremos «setenforce 1».
|
|
|
|
Contextos de SELinux
|
|
Los contextos de SELinux son una serie de etiquetas que se utilizan en procesos y archivos de Linux para permitir o no el acceso de las aplicaciones a ellos:
|
|
|
|
[root@server1 ~]# semanage login -l
|
|
|
|
Login Name SELinux User MLS/MCS Range Service
|
|
|
|
__default__ unconfined_u s0-s0:c0.c1023 *
|
|
root unconfined_u s0-s0:c0.c1023 *
|
|
[root@server1 ~]#
|
|
Usuario: Las políticas de SELinux se asocian a los usuarios del sistema operativo. De esta manera, un usuario de Linux hereda las políticas de SELinux que se hayan configurado.
|
|
Rol: El acceso a los archivos y procesos del sistema se permitirá en función al rol asociado al usuario de SELinux.
|
|
Tipo: Tanto los procesos como los archivos están asociados a un dominio de SELinux. Las políticas de seguridad configuradas en SELinux define cómo se acceden los tipos entre sí (un dominio que accede a un tipo o un dominio que accede a otro dominio, por ejemplo).
|
|
Nivel: SELinux permite definir políticas de acceso basadas en niveles de seguridad y categorías. Por ejemplo: s0-s0:c0.c1023
|
|
LEER Configuración de un Proxy por defecto en Linux RedHat
|
|
Conocer el contexto al que pertenece un archivo
|
|
Con el parámetro «Z» del comando «ls» sabremos a qué contexto pertenece un archivo:
|
|
|
|
[root@server1 ~]# touch test.txt
|
|
[root@server1 ~]# ls -lZ test.txt
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:admin_home_t:s0 0 Aug 8 07:24 test.txt
|
|
[root@server1 ~]#
|
|
Otra manera de averiguar las reglas configuradas para un archivo o un directorio, es con el comando semanage fcontext -l.
|
|
|
|
root@server1 ~]# semanage fcontext -l |more
|
|
SELinux fcontext type Context
|
|
|
|
/ directory system_u:object_r:root_t:s0
|
|
/.* all files system_u:object_r:default_t:s0
|
|
/[^/]+ regular file system_u:object_r:etc_runtime_t:s0
|
|
/\.autofsck regular file system_u:object_r:etc_runtime_t:s0
|
|
/\.autorelabel regular file system_u:object_r:etc_runtime_t:s0
|
|
/\.ismount-test-file regular file system_u:object_r:sosreport_tmp_t:s0
|
|
/\.journal all files <<None>>
|
|
/\.snapshots(/.*)? all files system_u:object_r:snapperd_data_t:s0
|
|
/\.suspended regular file system_u:object_r:etc_runtime_t:s0
|
|
/a?quota\.(user|group) regular file system_u:object_r:quota_db_t:s0
|
|
/afs directory system_u:object_r:mnt_t:s0
|
|
/bacula(/.*)? all files system_u:object_r:bacula_store_t:s0
|
|
/bin all files system_u:object_r:bin_t:s0
|
|
/bin/.* all files system_u:object_r:bin_t:s0
|
|
/bin/alsaunmute regular file system_u:object_r:alsa_exec_t:s0
|
|
/bin/bash regular file system_u:object_r:shell_exec_t:s0
|
|
Restaurar las etiquetas de los contextos de todo el sistema
|
|
Si por alguna razón necesitamos restaurar los contextos de todos los archivos del sistema, el procedimiento a seguir es:
|
|
|
|
Configurar SELinux en modo permisivo
|
|
Crear el fichero touch /.autorelabel
|
|
Rebotar el sistema. Puede ser un proceso muy largo si tenemos muchos archivos a reetiquetar
|
|
Reinicio de Linux con autorelabel para restaurar las etiquetas de SELinux
|
|
Revisar los errores del sistema en /var/log/messages y /var/log/audit/audit.log.
|
|
Volver a configurar SELinux en modo enforcing.
|
|
Rebotar de nuevo
|
|
Poniendo a prueba el contexto de un archivo con SELinux
|
|
Para esta prueba he creado un fichero sencillo html que ha de cargar Apache si el contexto del archivo es el correcto.
|
|
|
|
[root@server1 html]# pwd
|
|
/var/www/html
|
|
[root@server1 html]# cat test.html
|
|
<html>
|
|
|
|
<body>
|
|
|
|
<script type="text/javascript">
|
|
document.write('Hello, I am ' + window.location.hostname);
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
[root@server1 html]# ls -lZ test.html
|
|
-rw-r--r--. 1 root root system_u:object_r:httpd_sys_content_t:s0 140 Aug 7 07:56 test.html
|
|
[root@server1 html]#
|
|
Apache test file
|
|
Como podemos comprobar, Apache ha podido cargar correctamente el archivo.
|
|
|
|
LEER Modificar el Keepalive en Linux RedHat
|
|
Ahora vamos a realizar una segunda prueba con un fichero con un contexto de SELinux no permitido. Apache no debería poder cargar el archivo.
|
|
|
|
[root@server1 ~]# ls -lZ test2.html
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:admin_home_t:s0 140 Aug 8 07:55 test2.html
|
|
[root@server1 ~]# cp -a test2.html /var/www/html/
|
|
[root@server1 ~]# ls -lZ /var/www/html/test2.html
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:admin_home_t:s0 140 Aug 8 07:55 /var/www/html/test2.html
|
|
[root@server1 ~]#
|
|
Como vemos, el contexto del fichero test2.html es admin_home_t y Apache no tiene permisos para leerlo:
|
|
|
|
Apache no puede leer un fichero con un contexto incorrecto de SELinux
|
|
En el fichero /var/log/messages, nos está avisando, justamente, de que el contexto del fichero test2.htm es incorrecto:
|
|
|
|
Aug 8 07:58:06 server1 setroubleshoot[3842]: SELinux is preventing /usr/sbin/httpd from getattr access on the file /var/www/html/test2.html.#012#012***** Plugin restorecon (99.5 confidence) suggests ************************#012#012If you want to fix the label. #012/var/www/html/test2.html default label should be httpd_sys_content_t.#012Then you can run restorecon. The access attempt may have been stopped due to insufficient permissions to access a parent directory in which case try to change the following command accordingly.#012Do#012# /sbin/restorecon -v /var/www/html/test2.html#012#012***** Plugin catchall (1.49 confidence) suggests **************************#012#012If you believe that httpd should be allowed getattr access on the test2.html file by default.#012Then you should report this as a bug.#012You can generate a local policy module to allow this access.#012Do#012allow this access for now by executing:#012# ausearch -c 'httpd' --raw | audit2allow -M my-httpd#012# semodule -X 300 -i my-httpd.pp#012
|
|
Por lo tanto, lo que tenemos que hacer es modificar el contexto del fichero test2.html. Lo haremos de la siguiente manera:
|
|
|
|
[root@server1 ~]# /sbin/restorecon -v /var/www/html/test2.html
|
|
Relabeled /var/www/html/test2.html from unconfined_u:object_r:admin_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
|
|
[root@server1 ~]# ls -lZ /var/www/html/test2.html
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 140 Aug 8 07:55 /var/www/html/test2.html
|
|
[root@server1 ~]#
|
|
Ahora ya sí que deja cargar el fichero.
|
|
|
|
Lo que hace el comando restorecon ejecutado anteriomente, es revisar cuál es la regla de SELinux configurada para el directoro /var/www/html y aplicársela al archivo test2.html, ya que es una regla recursiva.
|
|
|
|
[root@server1 ~]# semanage fcontext -l |grep "/var/www/html"
|
|
/var/www/html(/.*)?/sites/default/files(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
|
|
/var/www/html(/.*)?/sites/default/settings\.php regular file system_u:object_r:httpd_sys_rw_content_t:s0
|
|
/var/www/html(/.*)?/uploads(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
|
|
/var/www/html(/.*)?/wp-content(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
|
|
/var/www/html(/.*)?/wp_backups(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
|
|
/var/www/html/[^/]*/cgi-bin(/.*)? all files system_u:object_r:httpd_sys_script_exec_t:s0
|
|
/var/www/html/cgi/munin.* all files system_u:object_r:munin_script_exec_t:s0
|
|
/var/www/html/configuration\.php all files system_u:object_r:httpd_sys_rw_content_t:s0
|
|
/var/www/html/munin(/.*)? all files system_u:object_r:munin_content_t:s0
|
|
/var/www/html/munin/cgi(/.*)? all files system_u:object_r:munin_script_exec_t:s0
|
|
/var/www/html/nextcloud/data(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
|
|
/var/www/html/owncloud/data(/.*)? all files system_u:object_r:httpd_sys_rw_content_t:s0
|
|
[root@server1 ~]#
|
|
Aplicar una regla nueva de contexto de SELinux a un directorio nuevo
|
|
Pongamos por caso que tenemos un nuevo servicio de Apache en /apache2 pero no hay ninguna regla de SELinux aplicada todavía y, por lo tanto, Apache no podrá leer el archivo.
|
|
|
|
LEER Comandos básicos de Linux relacionados con los procesos
|
|
Lo que tendremos que hacer es añadir una regla nueva de SELinux al nuevo directoro. Veámos cómo se hace:
|
|
|
|
Creamos el directorio nuevo y un archivo de pruebas que deberá leer apache:
|
|
[root@server1 ~]# mkdir /apache2
|
|
[root@server1 ~]# cd /apache2/
|
|
[root@server1 apache2]# touch test > test.txt
|
|
[root@server1 apache2]# ls -lZ
|
|
total 0
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Aug 8 08:25 test
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Aug 8 08:25 test.txt
|
|
[root@server1 apache2]#
|
|
Creamos una nueva regla de SELinux para que Apache pueda leer el directorio /apache2 de manera recursiva:
|
|
[root@server1 ~]# semanage fcontext -a -t httpd_sys_content_t "/apache2(/.*)?"
|
|
[root@server1 ~]# restorecon -R -v /apache2
|
|
Relabeled /apache2 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
|
|
Relabeled /apache2/test.txt from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
|
|
Relabeled /apache2/test from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
|
|
[root@server1 ~]#
|
|
Podemos comprobar que la etiqueta del ficheros de /apache2 ha cambiado:
|
|
|
|
[root@server1 ~]# ls -lZ /apache2/
|
|
total 0
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 0 Aug 8 08:25 test
|
|
-rw-r--r--. 1 root root unconfined_u:object_r:httpd_sys_content_t:s0 0 Aug 8 08:25 test.txt
|
|
[root@server1 ~]#
|
|
Si quisiéramos eliminar la regla de SELinux que hemos configurado previamente para el directorio /apache2, lo haríamos con el parámetro «-d» (delete) de semanage:
|
|
|
|
[root@server1 ~]# semanage fcontext -d "/apache2(/.*)?"
|
|
Puedes consultar más ejemplos con: man semanage-fcontext
|
|
|
|
Aplicando reglas de SELinux a puertos de comunicaciones
|
|
Anteriormente comentaba que las reglas de SELinux no solamente se aplican a ficheros, si no también a procesos. Pongamos por caso que queremos arrancar Apache por un puerto personalizado. Pongamos por caso, el 82. Si no hay una regla definida en SELinux para asociar el puerto 82 a Apache, el servicio no arrancará.
|
|
|
|
Aug 08 08:50:41 server1 httpd[4918]: (13)Permission denied: AH00072: make_sock: could not bind to address [::]:82
|
|
Aug 08 08:50:41 server1 httpd[4918]: (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:82
|
|
Para habilitar esta nueva regla, también utilizaremos semanage con el parámetro port:
|
|
|
|
[root@server1 conf]# semanage port -a -t http_port_t -p tcp 82
|
|
[root@server1 conf]# semanage port -l |grep http_port
|
|
http_port_t tcp 82, 80, 81, 443, 488, 8008, 8009, 8443, 9000
|
|
pegasus_http_port_t tcp 5988
|
|
[root@server1 conf]#
|
|
Puedes consultar más ejemplos con: man semanage-port. |