Translate

miércoles, 5 de julio de 2017

Corrección de contextos de seguridad de SELinux en CentOS 6 (6.9)

Por omisión RedHat Enterprise Linux, CentOS, etc. vienen con contextos de seguridad de SELinux para sus sistemas de archivos. Si se intenta realizar cambios en la estructura del sistema de archivos, entonces el SELinux empieza a enviar una serie de avisos de que no se tiene acceso a un archivo , programa , etc.

Los cambios en la estructura pueden ser debido a que desde el principio no se calculó correctamente el tamaño de las particiones o volúmenes lógicos. Por omisión el instalador pone una partición relativamente pequeña para el directorio raíz ( / ) , en mi caso solo 50 GB del total de 4.5 TB, 500 MB para la partición primaria de /boot y el resto ( más de 4 TB para /home). Este tipo de particionamiento no toma en cuenta de que las bases de datos, el servidor de páginas web, etc., se encuentran ubicados en /var. Lo correcto sería crear una partición aparte y montarla en /var dándole al menos la mitad de la capacidad del disco duro. Por ejemplo en mi caso, serían unos 2TB.

Cuando ya está hecha la instalación de los programas tales como la base de datos y el servidor WWW en una partición '/' pequeña, se hace entonces necesario redireccionar los directorios a los espacios físicos que quedan libres. Así por ejemplo, dentro de /home , se decidió crear un nuevo directorio '/' (root) para que allí estuvieran los archivos que ya no caben en el directorio '/' original. Por ejemplo:

ls -al /home/ext-root-fs/
total 12
drwxr-xr-x.  3 root root 4096 Oct 31  2016 .
drwxr-xr-x. 23 root root 4096 Jul  4 21:24 ..
drwxr-xr-x.  3 root root 4096 Oct 31  2016 var

En este caso ext-root-fs (extensión del sistema de archivos de root), contiene un directorio (var), el cual a su vez tiene el directorio lib que es donde está instalado el RDBMS PostgreSQL, así como todos los demás programas que normalmente se instalan en /var/lib. para hacer esto simplemente se creó una liga en /var:

ls -al /var/lib
lrwxrwxrwx. 1 root root 25 Oct 31  2016 /var/lib -> /home/ext-root-fs/var/lib

( con ln -s /home/ext-root-fs/var/lib /var/lib )

Aunque esta es una solución sencilla, el problema es que el SELinux se da cuenta que los archivos que normalmente van en /var se están metiendo en un contexto muy diferente que es el de /home. Y es aquí donde empiezan las complicaciones del SELinux.

Para verificar si está activado el SELinux. Ponemos:

getenforce
Enforcing

Por omisión el archivo que tiene la política de habilitación del SELinux es:

cat /etc/selinux/config | grep SELINUX
# SELINUX= can take one of these three values:
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
SELINUXTYPE=targeted

 Sin necesidad de reiniciar la máquina, podemos deshabilitar y habilitar SELinux con setenforce:

setenforce 0
getenforce
Permissive
setenforce 1
getenforce
Enforcing

Los permisos de acceso a archivos, directorios, puertos , etc. se realizan mediante los valores booleanos de SELinux, cada uno de los  cuales tiene un nombre predefinido.

Por ejemplo si queremos ver todos los booleanos de SELinux que existen, ponemos:

getsebool -a

que en mi caso son 237:

  getsebool -a  | wc -l
237

 Si quiero conocer todos los booleanos relacionados con httpd, le pongo:

getsebool -a | grep httpd 

Si quiero ver si los usuarios pueden tener en su home páginas web lo verifico con :

getsebool -a | grep httpd  | grep home
httpd_enable_homedirs --> on

En mi caso está activo este booleano pero se puede desactivar/activar:

setsebool httpd_enable_homedirs 0
getsebool httpd_enable_homedirs
httpd_enable_homedirs --> off
setsebool httpd_enable_homedirs 1
getsebool httpd_enable_homedirs

httpd_enable_homedirs --> on


Ahora bien, para corregir el problema del contexto mencionado anteriormente tenemos que hacer o siguiente.

Lo primero, por si acaso, es restaurar el contexto de seguridad de todos los Filesystems:

restorecon -r -v /

(-r es recursivo y -v muestra los cambios realizados).

Nota: Esto puede tardar decenas de minutos. Depende del número de archivos.

Lo siguiente es analizar si está funcionando correctamente el audit:

service auditd status

Y verificar si está guardando mensajes en :

ls -al /var/log/audit




Suponiendo de que está trabajando correctamente el audit, queda ver si el setroubleshootd  está enviando correctamente los reportes de SELinux. En mi caso me di cuenta que no era así, ya que al darle al comando sealert , no me mostraba nada ( No alerts) . Para verficar el problema le puse:

audit2allow -w -a

-a significa todas las bitácoras
-w que explique cual es el problema.

En  mi caso habían unas lineas tales como:

type=AVC msg=audit(1499299412.626:38955212): avc:  denied  { write } for  pid=25797 comm="setroubleshootd" name="setroubleshoot_database.xml" dev=dm-2 ino=283248333 scontext=system_u:system_r:setroubleshootd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:user_home_t:s0 tclass=file
    Was caused by:
        Unknown - would be allowed by active policy
        Possible mismatch between this policy and the one under which the audit message was generated.

        Possible mismatch between current in-memory boolean settings vs. permanent ones.



El número 1499299412.626 en audit( , es el número de segundos desde 1970-01-01 tiempo UTC. Para saber a qué fecha hora, min, seg corresponde, podemos poner:

date -d @1499299412.626
Wed Jul  5 19:03:32 CDT 2017

o si se tiene un date de una versión más vieja que no acepta la '@':

date -d '1970-01-01 UTC + 1499299412.626 seconds'
Wed Jul  5 19:03:32 CDT 2017



El problema es que el contexto de setroubleshootd system_u:object_r:user_home
Para corregir esto, buscamos primero el nombre correspondiente del contexto con:

audit2allow -a

En mi caso aparecieron unas lineas como estas:

#============= setroubleshootd_t ==============

allow setroubleshootd_t user_home_t:file { write setattr };


Para 'corregir' el problema se ejecutó el comando que genera los permisos de los accesos con:

audit2allow -a -M setroubleshootd_t
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i setroubleshootd_t.pp

Y  se ejecutó el comando correspondiente:

semodule -i setroubleshootd_t.pp


Lo mismo se hizo con el contexto de httpd:

 audit2allow -a  


#============= httpd_t ==============
allow httpd_t home_bin_t:file getattr;

 audit2allow -a -M  httpd_t
******************** IMPORTANT ***********************
To make this policy package active, execute:

semodule -i httpd_t.pp

semodule -i httpd_t.pp


Otro ejemplo:
Debido a que /tmp está en root y esta partición había quedado pequeña, se decidió hacer otro directorio en /home/tmp para guardar allí los archivos temporales.
Por ejemplo el owncloud requiere un directorio temporal para guardar allí los archivos que se suben antes de procesarlos y enviarlos a su destino original.  Si el owncloud no encuentra suficiente espacio para crear los archivos temporales, entonces envía el error "Failed to write to disk". Para arreglar estom se tuvo que hacer lo siguiente:

  1. Modificar el  archivo /etc/php.ini, cambiando el parámetro upload_tmp_dir, para que quede: upload_tmp_dir = /home/tmp
  2. Agregar el contexto de los atributos del directorio de /tmp y ponérselos a /home/tmp. Esto se hizo con:
# ls -lZd /tmp
drwxrwxrwt. root root unconfined_u:object_r:tmp_t:s0   /tmp
# ls -lZd /home/tmp
drwxrwxrwt. root root unconfined_u:object_r:user_home_dir_t:s0 /home/tmp
# semanage fcontext -a -t  tmp_t /home/tmp
# restorecon -R /home/tmp







Ahora podemos verificar el contexto de /home/tmp y podemos ver que el contexto de /home sigue siendo el mismo:

# ls -lZd /home/tmp
drwxrwxrwt. root root unconfined_u:object_r:tmp_t:s0   /home/tmp
# ls -lZd /home
drwxr-xr-x. root root system_u:object_r:home_root_t:s0 /home


Actualización: Contexto para nginx y drupal 7:


Si sale error de que no puede crear archivos temporales o escribir. Modificar el contexto de los archivos con:

cd /usr/share/nginx
chcon -t httpd_sys_rw_content_t -R html

Es decir, nos cambiamos al directorio donde están los archivos html del nginx y cambiamos el contexto de los archivos poniéndole el correcto (en forma recursiva).

Actualización 2020-03-05: Contexto para nginx en CentOS 6

El nginx mediante el php-fpm, impedía la escritura de archivos en un subdirectorio ubicado dentro de /usr/share/nginx/html :

grep php-fpm  /var/log/audit/audit.log| grep denied  | tail -1
type=AVC msg=audit(1583456547.180:181159): avc:  denied  { write } for  pid=6206 comm="php-fpm" name="SI2017dea4ebfedd5b9a0d8e9c16b5ce9ee04f_0012345.png" dev=dm-0 ino=3398201 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:usr_t:s0 tclass=file
[root@ingenieria qr]# grep php-fpm  /var/log/audit/audit.log| grep denied  | tail -1  | audit2why


Para verificar el contexto del acceso se empleó el comando:

grep php-fpm  /var/log/audit/audit.log| grep denied  | tail -1  | audit2why
type=AVC msg=audit(1583456547.180:181159): avc:  denied  { write } for  pid=6206 comm="php-fpm" name="SI2017dea4ebfedd5b9a0d8e9c16b5ce9ee04f_0012345.png" dev=dm-0 ino=3398201 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:usr_t:s0 tclass=file

    Was caused by:
        Missing type enforcement (TE) allow rule.

        You can use audit2allow to generate a loadable module to allow this access.


El problema es que el contexto fuente: 
scontext=unconfined_u:system_r:httpd_t:s0,
no coincide con el contexto destino:
tcontext=unconfined_u:object_r:usr_t:s0, 
por lo que se hace necesario cambiar el contexto del archivo destino.


Para que persistan los cambios de contexto es necesario poner:

semanage fcontext -a -t httpd_sys_content_t "/usr/share/nginx/html(/.*)?"
restorecon -R -v /usr/share/nginx/html


Ejemplo de corrección de contexto en otro directorio ( /home/ext-root-fs/var/www
)
:

semanage fcontext -a -t httpd_sys_content_t "/home/ext-root-fs/var/www(/.*)?"
restorecon -R -v /home/ext-root-fs/var/www

Actualización 2021-10-02: Corrección de contexto para un archivo script en CentOS 6

 

#Verificación de contexto del script
# ll -Z script
-rwxr-xr-x. root root unconfined_u:object_r:user_home_t:s0 script

#Corrección de contexto
# chcon  system_u:system_r:user_home_t:s0 script
# ls -alZ script
-rwxr-xr-x. root root system_u:system_r:user_home_t:s0 script


Las siguientes ligas pueden servir como referencias:
https://wiki.centos.org/HowTos/SELinux
https://wiki.centos.org/TipsAndTricks/SelinuxBooleans

http://www.serverlab.ca/tutorials/linux/administration-linux/troubleshooting-selinux-centos-red-hat/

https://wiki.gentoo.org/wiki/SELinux/Tutorials/Where_to_find_SELinux_permission_denial_details

RedHat:

5.6.2. Persistent Changes: semanage fcontext

https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Fixing_Problems-sealert_Messages.html
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Fixing_Problems-Allowing_Access_audit2allow.html
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/SELinux_Users_and_Administrators_Guide/sect-Security-Enhanced_Linux-Troubleshooting-Fixing_Problems.html


http://melikedev.com/2012/09/28/centos-sealert-convert-audit-messages-into-human-readable-and-understandable-format/


Contexto para Drupal:
https://www.drupal.org/forum/support/post-installation/2009-09-20/error-when-trying-to-upload-logo-file-upload-error-could#comment-12601586


Contexto de nginx:
Contexto de SELinux en nginx


Tutorial:

  1. https://www.digitalocean.com/community/tutorials/an-introduction-to-selinux-on-centos-7-part-1-basic-concepts
  2. https://www.digitalocean.com/community/tutorials/an-introduction-to-selinux-on-centos-7-part-2-files-and-processes
  3. https://www.digitalocean.com/community/tutorials/an-introduction-to-selinux-on-centos-7-part-3-users














No hay comentarios: