Revisión de la guía CCN-STIC-619 del Esquema Nacional de Seguridad

Kuko Armas <kuko@canarytek.com>
|

Una revisión crítica de la guía CCN-STIC-619 de bastionado de CentOS 7 del Esquema Nacional de Seguridad

Antecedentes

Recientemente he iniciado un proyecto para ayudar a securizar los servidores CentOS de una entidad que debe cumplir con el Esquema Nacional de Seguridad (ENS) y mi experiencia por ahora no ha sido muy satisfactoria. Este post es fruto de la frustración que he sentido de cómo está enfocado todo el ENS.

Tengo que decir que también he comentado mis “quejas” con algún colega del sector y se han extrañado, porque me dicen que su experiencia es muy buena. Por lo que me dicen, el soporte en sistemas Windows es muy bueno. No lo sé, aún no he llegado a esa parte…

También adelanto que estoy trabajando en una definición de la configuraciones de la guía de bastionado de CentOS del ENS en formato SCAP que intentare publicar en el proyecto ComplianceAsCode. Espero publicar otro post sobre esto en breve

Un planteamiento cerrado

El primero punto que me sorprendió es el hecho de que todo el ENS, es relativamente “cerrado”. El CCN-CERT ha desarrollado numerosas herramientas que no están disponibles al público y que sólo funcionan en combinación con las otras herramientas de CCN-CERT. Y además, estas herramientas no están disponibles al público, solo a las Administraciones Públicas. Estos dos puntos me han sorprendido bastante, teniendo en cuenta los siguientes puntos:

  • ¿Si las herramientas se están desarrollando con dinero público, no sería lógico que fueran de uso público?
  • Es cierto que el ENS solo deben cumplirlo las AAPP y sus proveedores, pero ¿no seria deseable que todas las empresas y particulares pudieran usar estas herramientas para estar mas seguras?
    • Si el nivel de seguridad aumenta en todas las empresas y particulares, eso implicaría mayor seguridad también en las AAPP. Un “ecosistema” mas seguro incrementa la seguridad de sus “individuos”
  • Por otra parte, existen estándares de seguridad para hacer gran parte de los que se hace en el ENS, y existen entidades gubernamentales que llevan años publicando sus especificaciones de seguridad en este formato (SCAP). ¿Por que reinventar la rueda y desarrollar herramientas desde cero? ¿Por que no publicar los requerimientos en dicho estándar? El publicarlo en algún formato estándar, tiene muchísimas ventajas:
    • Se puede usar cualquier herramienta que soporte este estándar, no solo las de CCN-CERT
    • Nos aprovechamos de la experiencia acumulada de entidades que llevan años publicando sus especificaciones de seguridad
    • En el estándar SCAP no solo se definen los requisitos de seguridad, también se pueden definir las acciones correctivas, con lo que en la misma definición tienes la comprobación y la acción automatizada que aplica ese cambio
    • Existen numerosas herramientas que permiten hacer verificación de cumplimiento utilizando estos estándares
    • De hecho, existe incluso un proyecto libre para facilitar la generación de definiciones SCAP a partir de plantillas fáciles de usar: ComplianceAsCode (https://github.com/ComplianceAsCode/content)
  • Si lo hubieran planteado como un proyecto publico, abierto a la colaboración, seguro que muchos técnicos estarían dispuestos a colaborar y aportar posibles mejoras.

La guía CCN-STIC-619

Mi siguiente paso tras ver el enfoque general del ENS, fue leerme la guia CCN-STIC-619 de bastionado de CentOS 7.

Durante la lectura de la guía CCN-STIC-619, lo primero que me llamo la atención es que es básicamente un compendio de recomendaciones genéricas de seguridad y una descripción de las nuevas funcionalidades de CentOS 7 relacionadas con la seguridad

Lo primero que me llamo la atención es que gran parte de la guía es una (no muy buena) traducción de las “Release Notes” de CentOS 7. En algunos apartados incluso da la impresión de que el traductor del documento no tenía muy claro de qué se estaba hablando, ya que hay párrafos en los que la traducción no es la más apropiada para los términos técnicos que se están utilizando. Un detalle en el que se evidencia claramente el desconocimiento técnico por parte del traductor, es el hecho de que en el apartado 6.4.7.3 hablan de AIDE como un “CONTROL DE INTEGRIDAD DE HARDWARE”, cuando no tiene nada que ver con el hardware. AIDE es un HIDS (Host based Intrusion Detection System). La “H” viene de “Host”, no de “Hardware”

Los scripts de bastionado

La guía está acompañada de unos scripts de bastionado que se supone que se deben ejecutar en la maquina que se quiere proteger. Estos scripts son la referencia más clara sobre las configuraciones necesarias para cumplir el ENS en servidores CentOS 7.

Pero estos scripts también contienen errores y realizan configuraciones “discutibles” (como mínimo). Además, con un simple vistazo a cómo están escritos los scripts, parece evidente que han sido escritos por alguien que no tiene mucha experiencia.

A continuación analizamos cada uno de los scripts. Las pruebas las he hecho en una maquina instalada con la configuración por defecto, con exactamente la misma versión que indican en a guía.

CCN-STIC-619_Paso_1_contrasena_grub

Es este script se configura una contraseña para proteger el gestor de arranque GRUB2

También modifica la entrada del menú de arranque de Grub con el siguiente texto, “ES UN DELITO CONTINUAR SIN LA DEBIDA AUTORIZACION INICIE CENTOS 7 LINUX”. El problema de este cambio dificulta ver versión del kernel utilizado, lo que suele ser necesario cuando existen varias versiones instaladas. Además, el mensaje desaparecerá cuando se desinstale la versión del kernel utilizada cuando se ejecutó el script

CCN-STIC-619_Paso_2_parametros_del_kernel

En este script se desactivan numerosas funcionalidades del kernel de Linux.

En este script da la impresión de que es un compendio de recomendaciones recopiladas de diferentes fuentes, pero sin tener muy claro lo que hace cada una. Por ejemplo, casi al principio se desactiva la respuesta a cualquier “ICMP Echo Request” (ping), y más adelante se desactiva la respuesta a “ping” a la dirección de broadcast. ¿Por que desactivar la respuesta a la dirección de broadcast si ya se han desactivado las respuesta a cualquier “ping”?.

Además, la forma en que se aplican estos cambios no es la “mas limpia”. CentOS viene preparado para poder definir parámetros en diferentes ficheros, de forma que no se pisen unos parámetros con otros, pero este script reescribe totalmente el fichero de configuración principal. Además, para aplicar los parámetros, realizar un reinicio de la maquina, lo que es totalmente innecesario.

CCN-STIC-619_Paso_3_reglas_audit

El primer detalle que llama la atención de este scripts, es que el fichero de configuración de auditd se genera con mas de 60 entradas del tipo:

echo "lineas de configuracion" >> fichero_de_configuracion

Cualquier persona con un mínimo de experiencia hubiera generado una configuración como esa utilizando la sintaxis “here document”

cat > fichero_de_configuracion <EOF
mis multiples
lineas de
configuracion
EOF

Lo anterior no es más que un detalle estético, pero no es el único problema de ese script, hay otro mas grave: la configuración generada contiene un error que hace que solo se carguen las primeras 12 entradas (de 48), ya que la entrada numero 13 es exactamente la misma que la entrada 1, por lo que la carga de auditd genera un error y deja de procesarlas

CCN-STIC-619_Paso_4a_repositorio_inst

En este script se instalan varios paquetes desde el DVD de instalación, pero se asume que esta montado en /media, que no es el directorio en el que se monta por defecto, y tampoco se informa de ello, con lo que el script falla. Para que el script se complete, hay que leer el script para ver donde esta buscando el DVD de instalación y montarlo manualmente en esa ruta.

Los paquetes que se instalan son los siguientes: iptables-services, yum-utils, usbguard y aide

Algo que llama la atención es que se genera una ejecución de “yum install” para cada paquete, cuando es mucho más rápido indicar todos los paquetes a instalar en una única ejecución de “yum install” Ademas, se installa el paquete iptables-service, que en esta versión se considera obsoleta, sustituido por firewalld

CCN-STIC-619_Paso_4b_repositorio_local

Este script simplemente instala las actualizaciones de seguridad. En este script también se asume que el DVD esta montado en “/media”

CCN-STIC-619_Paso_5_limitacion_usb

Este script simplemente genera un fichero de configuración para el servicio “usbguard”, que limita el acceso a dispositivos de almacenamiento USB.

Lo curioso, es que el fichero de configuración generado (usbguard-daemon.conf) hace que el servicio no arranque, porque contiene errores de configuración: en las rutas de los ficheros de configuración y logs, aparecen las macros %sysconfdir% y %localstatedir%, que no son macros que entienda USBGuard, por lo que el arranque falla porque no encuentra dichos ficheros.

Esas macros se supone que deben expandirse antes de generar el fichero de configuración usbguard-daemon.conf. De hecho, en el código fuente del proyecto USBGuard, esas macros aparecen en el fichero usbguard-daemon.conf.in, que es a partir del que genera el usbguard-daemon.conf, precisamente tras expandir dichas macros.

Da la impresión de que la persona que genero este script copió la configuración desde el código fuente, sin tener muy claro que es lo que estaba copiando.

Y toda esta complicación, para cambiar simplemente un parámetro de la configuración por defecto, que podía hacerse con este simple diff:

--- /etc/usbguard/usbguard-daemon.conf.dist	2019-12-15 15:34:22.340997440 -0500
+++ /etc/usbguard/usbguard-daemon.conf	2019-12-15 15:42:13.446543514 -0500
@@ -49,7 +49,7 @@
 # * apply-policy - evaluate the ruleset for every present
 #                  device
 #
-PresentControllerPolicy=keep
+PresentControllerPolicy=apply-policy

Además añaden permisos para el usuario que utilizan para la configuración en la guía: “aCdCmN616”, un usuario que casi con toda seguridad no existirá en una maquina real de producción

IPCAllowedUsers=root aCdCmN616

CCN-STIC-619_Paso_6_limites_recursos_usuario

En este script se establecen diferentes limites por usuario (generación de cores, numero de procesos, etc) También se establece el siguiente mensaje en el /etc/hosts y /etc/issue*: “ES UN DELITO CONTINUAR SIN LA DEBIDA AUTORIZACIÓN - El sistema está restringido a los usuarios autorizados”

Finalmente se reinicia la maquina para forzar a que se apliquen

CCN-STIC-619_Paso_7_herramientas_servicios_y_demonios_innecesarios

En este script de desinstala software y se desactivan servicios “innecesarios”

Otra vez se realizan numerosas ejecuciones de “yum remove” en lugar de indicar todos los paquetes en una única ejecución, que seria mucho mas eficiente.

Este es uno de los scripts mas “conflictivos”, debido a su definición de software y servicios “innecesarios”.

Algunas de las decisiones “discutibles” de este script:

  • Elimina firewalld, que es el servicio recomendado en CentOS 7 para gestión de iptables (en la guía y los scripts se utiliza iptables-service, que es un servicio obsoleto)
  • Enmascara el servicio tmp.mount, con lo que no se puede configurar el “/tmp” en fstab con opciones seguras como noexec,nodev (cosa que intenta hacer un script posterior)
  • Desinstala NetworkManager, el gestor de red por defecto en CentOS7
  • También enmascara el servicio network, por lo que los interfaces de red no se activarán en el inicio de la máquina
  • Desinstala paquetes que son dependencia fundamental de gnome, por lo que ¡se desinstala el entorno grafico gnome!
  • Un detalle “llamativo” es que intenta enmascarar servicios después de desinstalar el paquete, lo que, evidentemente, no tiene sentido (por ejemplo, postfix)

Veamos el impacto de las acciones anteriores en dos perfiles de máquina (servidor y maquina de usuario):

  • Maquina de usuario: se supone que la guía esta redactada para bastionar “maquinas cliente independientes”, es decir, ordenadores de usuario. En este caso, la decisión de desactivar la red en el arranque puede tener sentido, ya que el usuario esta delante del ordenador y podrá levantar los interfaces de red si los necesita. Pero lo que no tiene sentido es desinstalar el entorno gráfico, ya que una maquina de usuario en consola no tiene utilidad para el 99.999% de los usuarios.
  • Servidor: en el caso de bastionar una máquina servidor, la decisión de desinstalar el entorno gráfico es totalmente acertada, pero en este caso lo que no tiene sentido es desactivar el arranque de la red en el inicio de la máquina, ya que cada vez que se inicie el servidor, alguien tendrá que conectarse en console para levantar los interfaces de red manualmente con “ifup INTERFACE”.

En resumen, que tras ejecutar este script, lo que tendremos es una máquina inservible (un “ladrillo”), ya que no tendrá entorno gráfico (necesario para las maquinas de usuario), y no arrancará la red en el inicio (necesario para los servidores)

CCN-STIC-619_Paso_8_desinstalar_usuarios_innecesarios

Este script elimina varios usuarios y establece el shell de otros tantos, pero igual que en el caso anterior, toma decisiones muy discutibles.

Establece el shell del usuario root a /bin/false así que si no tienes otro usuario en esa maquina, ¡tienes un problema gordo! (Pista: existen métodos menos intrusivos de evitar el acceso de los usuarios como root. El acceso como root en consola no suele ser un riesgo)

Vale, es verdad, todos sabemos que la recomendación es tener un usuario no privilegiado y hacer sudo. Pero claro, habrá que hacer “sudo bash”, porque “sudo -i” o “sudo su -“, que son las formas habituales, no funcionarán, porque esas formas ejecutan el shell configurado para el usuario root, que ahora es /bin/false.

Pero aún no hemos llegado a lo peor: ¡tambien elimina el usuario sshd! que se utiliza en la configuración por defecto de SSH en CentOS 7 para separación de privilegios, con lo que SSH dejará de funcionar. Si la máquina era un servidor, este script termina de convertirlo en un “ladrillo”, porque aunque levantemos los interfaces a mano (o arreglemos el desastre del script anterior), este script “rompe” el SSH, que no podrá arrancar y no podremos gestionar el servidor en remoto.

Si, es verdad que no hay máquina más segura que aquella a la que nadie se puede conectar (ni siquiera los usuarios legítimos), pero tengo mis dudas sobre la utilidad de esa máquina. ;)

Además, aquellos usuarios a los que cambia el shell a /bin/false (excepto root), son usuarios que por defecto tienen como shell a /bin/nologin, así que tampoco se gana mucho con el cambio.

Y como último detalle de lo poco “pulido” que esta este script, intenta cambiar el shell a un usuario que ha borrado previamente (dbus)

CCN-STIC-619_Paso_9_paquetes_huerfanos

Este script es muy sencillo, tanto que no tiene errores graves.

Básicamente lo que hace es limpieza de paquetes RPM (dependencias que ya no son necesarias, kernels antiguos, etc).

CCN-STIC-619_Paso_10_caducidad_complejidad_contraseñas

Lo primero que llama la atención de este script, es la “eñe” en el nombre. Algo que no suelo ver a menudo en scripts escritos por gente con experiencia.

También es “curioso” que el script reinicia la maquina “para aplicar los cambios”, cosa que es totalmente innecesaria.

CCN-STIC-619_Paso_11_intentos_fallidos

Este script simplemente activa el uso de pam_tally2 para bloquear una cuenta tras 3 intentos de acceso fallidos, pero mantiene la cuenta bloqueada hasta que un administrador la desbloquee.

CCN-STIC-619_Paso_12_Permisos_particiones

Este script configura opciones de montaje de los sistemas de ficheros, pero como ya se ha comentado, el de “/tmp” no funcionará porque en un script previo se enmascaró el servicio “tmp.mount”

Conclusiones

Tras el análisis de la guía y los scripts, tengo que admitir que me he llevado una importante decepción con la calidad de la guía, y, sobre todo, de los scripts. Da la impresión de que este trabajo se ha llevado a cabo “para cubrir el expediente” y se lo ha realizado personal sin conocimiento y experiencia real de lo que estaban haciendo.

De hecho, teniendo en cuenta la fecha de publicación de estas guías, y que tras ejecutar todos los scripts lo que obtienes es una máquina prácticamente inservible, me sorprende no haber leído críticas en ningún sitio. ¿Es que nadie ha intentado aplicar estos scripts en sus máquinas?

En cuanto al enfoque general del ENS, es evidente que es necesario un “órgano regulador” que defina los criterios de cumplimiento, y ese puede ser el CCN-CERT. Pero eso no debería ser excluyente con que pueda existir un proyecto de comunidad en el que se pueda compartir conocimiento, ideas y posibles mejoras. Con este enfoque, probablemente CCN-CERT podría beneficiarse de las aportaciones de los excelentes profesionales que tenemos en España en materia de seguridad informática.

Además, como ya he comentado, creo que sería mucho más sencillo y eficiente si los requisitos del ENS se publicaran en un estándar reconocido para tal efecto como SCAP, tal como llevan haciendo otros órganos reguladores durante años.