Seguridad en Sistemas de Ficheros en BSD

Por lo general, los sistemas derivados de BSD4.4 usan la implementación de Fast File System (FFS - algunas veces llamado también UFS Unix File System) como método de gestión de sistemas de ficheros. Dependiendo del sistema operativo, se hacen algunas mejoras orientadas hacia optimización de almacenamiento, rendimiento e interacción con discos, pero el concepto en BSD sigue siendo homogéneo. Por otro lado, para sistemas de ficheros de gran tamaño, se cuenta con la implementación de FFS2 (actualmente no soportada para particiones del sistema).

FFS fue diseñado para ser rápido y confiable. Divide los ficheros en dos grupos: Bloques ("blocks") y Fragmentos ("Fragments"), siendo los bloques grandes pedazos de datos, mientras que los fragmentos son pedazos más pequeños. Un fichero esté compuesto de muchos bloques y usa fragmentos para almacenar restos pequeños de información. A medida que el fichero crece, el sistema le asigna bloques adicionales. En este órden de ideas, los ínodos contienen información básica del fichero ("metadata") incluyendo datos de ubicación de bloques y fragmentos, permisos, fechas y tamaños.
Para compatibilidad con sistemas Windows, existen implementaciones de drivers para permitir acceso de lectura a particiones de tipo FFS, como es el caso del proyecto "FFS File System driver for Windows" http://ffsdrv.sourceforge.net/index.php

Al igual que en la mayoría de sistemas de ficheros actuales, FFS incorpora múltiples variables de seguridad, como se discute a continuación:

Opciones de Montaje de FFS/UFS
En FFS/UFS se usan los siguientes métodos de montaje, que pueden garantizar unos niveles adicionales de integridad, disponibilidad y confidencialidad en la información almacenada:

Read-Only:
Empleando esta configuración, un administrador puede montar un sistema de ficheros en modo de lectura únicamente, previniendo potenciales cambios, eliminación o reemplazo de ficheros.

Noexec, Nosuid y Nodev:
Al igual que el anterior, estos parámetros evitan el uso de ciertas características, restringiendo el ámbito de un potencial ataque. Noexec previene que ficheros ejecutables sean "ejecutados". Esto incluye scripts y binarios, pero no previene que un script sea interpretado desde la shell actual con el prefijo ".". Nosuid previene la ejecución de ficheros que tengan activado el flag SUID, mientras que Nodev previene que un fichero de dispositivo sea reconocido.

Soft Updates (o SoftDep):
Mediante esta característica, se pretende mantener una integridad en los datos almacenados en disco después de un apagado intempestivo o cortes de energía electríca. Es una alternativa al "journaling", ya que no emplea un log auxiliar (journal) para almacenar operaciones con metadatos sino que "ordena" parcialmente la escritura para asegurar la consistencia de metadatos y gestionando dependencias, optimizando el desempeño del disco. En implementaciones particulares, Sun Solaris combina Journaling con UFS en UFS Logging, disponiendo de ambas características para optimizar la consistencia en los datos. En sistemas BSD, Soft Updates no viene habilitado por defecto, por compatibilidad con arquitecturas antiguas.

No access Time
FFS registra la última vez que un fichero fue accedido para ejecución, lectura o escritura. Estas actualizaciones consumen una pequeña cantidad de tiempo y desempeño de disco que en gran medida pueden ser considerables. Montando la partición como "noatime" se puede ahorrar este tiempo.

File System Flags

Como complemento a las opciones de montaje, los sistemas BSD bajo FFS/UFS permiten aplicar una serie de restricciones adicionales de permisos sobre los ficheros, permitiéndole al administrador proteger ficheros clave de accesos o modificaciones no autorizadas o corrupción mediante el comando "chflags". Estas características a nivel de filesystem permiten definir controles de acceso (ACL) granulares más allá de los permisos normales de otros sistemas Unix. Esto se hace mediante el uso de "flags" o parámetros, dentro de los cuales se destacan:

System Change flag (schg)
Este flag previene que los ficheros sean movidos, cambiados o eliminados (inmutabilidad). Solamente puede ser habilitado por root y no puede ser removido si el sistema se encuentra ejecutándose en SecureLevel 1 o superior.

User Change flag (uchg)
Este flag actúa igual que el anterior, salvo que el dueño del fichero y root pueden habilitarlo o deshabilitarlo.

System append-only flag (sappnd)
Este flag previene que los ficheros sean modificados, de forma muy similar a como lo hace el flag immutable, con la única excepción que los datos pueden ser añadidos al final del fichero. Esta característica es útil en ambientes de gestión de ficheros de registro (logs) o en ficheros .history, en los cuales se quiere que se añada información pero que no se modifiquen los datos que estaban previamente. Es importante tener en cuenta que cuando se aplica este flag, el fichero no puede ser eliminado.

User append-only flag (uappnd)
Igual que el anterior, con la única diferencia que éste flag puede ser deshabilitado por el dueño del fichero o por root en cualquier momento, sin importar el securelevel en el que esté el sistema. Esta característica es útil cuando se quiere permitir que los usuarios puedan usar este nivel de protección en sus propios ficheros.

System no unlink flag (sunlnk)
Este flag previene la eliminación de un fichero y únicamente puede ser habilitado por root cuando el security level es superior a 0.

User no unlink flag (uunlnk)
Este flag le permite a un usuario indicarle al sistema que un fichero no debe ser eliminado, independientemente de sus permisos Unix tradicionales o los permisos de su directorio padre. Puede ser habilitado/deshabilitado por el usuario o por root.

Archived flag (arch)
Este flag permite que programas de backup o respaldo (dump, por ejemplo) ignoren determinados ficheros. Útil cuando se quiere evitar el almacenamiento de ficheros clave en otros lugares. Actualmente sólo se eucnetra activado por compatibilidad.

No Dump Flag (nodump)
Igual que el anterior. Es el flag actual a ser empleado.
Es importante tener en cuenta que mediante la utilidad "find" es posible hacer búsquedas de ficheros con base en los flags de los ficheros, lo cual le puede facilitar la vida a un administrador.

Sysctl y Kernel Security Levels

Una característica importante de los kernels BSD es que permiten la alteración de variables en el kernel durante la ejecución. Esto es necesario en la administración diaria de aplicativos, gestión de conexiones y buffers y seguridad del sistema. Para esta gestión se emplea el comando "sysctl". La variable sysctl más importante es kern.securelevel. El valor que tenga dicha variable en el sistema define los comportamientos generales de determinadas funciones y características posterior al inicio del sistema operativo (boot process):

kern.securelevel=-1 (Permanentemente inseguro):
Bajo este nivel, el sistema se comporta como un Unix tradicional en modo multiusuario, permitiendo al usuario root hacer cualquier operación. Todos los flags del filesystem pueden ser habilitados y deshabilitados, todos los dispositivos pueden ser leídos y escritos conforme con sus permisos normales, las reglas de filtrado pueden ser modificadas y el relój del sistema puede ser cambiado. Por lo general, éste securelevel es empleado en actividades de mantenimiento y/o depuración del sistema y nunca es recomendado para producción.

kern.securelevel=0 (Transicional):
Igual comportamiento que el anterior y empleado temporalmente cuando el sistema está en proceso de boot e ingresa en modo monousuario.

kern.securelevel=1 (Seguridad operativa mejorada):
En este nivel, el kernel aplica las restricciones tradicionales de sistemas Unix, habilita los flags "immutable" y "append-only" en los filesystems, bloquea la escritura en /dev/mem y /dev/kmem y evita el cargue/descargue de módulos y drivers.

kern.securelevel=2 (Alta Seguridad):
En este nivel se activan las protecciones de niveles anteriores y se agregan otras restricciones, como evitar la creación o modificación de tamaño de filesystems, permite el acceso a dispositivos de red y de cinta solamente a procesos con privilegios de root, no permite los cambios de relój en el sistema, evita que las reglas de filtrado y NAT sean cambiadas y evita que las variables de depuración de kernel (DDB) sean cambiadas.

En sistemas como FreeBSD, existe el securelevel 3, que por lo general tiene las mismas funcionalidades del securelevel 2 pero evitando la modificación de reglas de filtrado.

Se puede cambiar de un nivel inferior a uno superior mediante el cambio de variable con sysctl, pero no se puede cambiar de un nivel superior a uno inferior sin reiniciar el sistema.

A pesar de los controles implementados en los securelevels, es importante tener en cuenta que las configuraciones de securelevels son implementadas posterior al proceso de inicio del sistema (boot process). Por lo tanto, si un atacante logra tener acceso antes que el securelevel sea activado, sus protecciones serán inválidas.

Encriptación de Memoria Virtual (SWAP)

Después de aplicar controles de confidencialidad en filesystems mediante técnicas criptográficas, aún queda una ubicación vulnerable: la memoria virtual. Después que un proceso autorizado a accedido a datos encriptados en un filesystem cifrado, dichos datos aparecen temporalmente en texto plano en la memoria virtual hasta que el sistema es apagado (e incluso, pudiendo dejar rastros aún después). Para ello, se emplea la encriptación/desencriptación de páginas (pages) que necesitan ser intercambiadas (swapped). En este sentido, sistemas operativos como OpenBSD permiten el uso de particiones swap cifradas por defecto y se permite habilitar o deshabilitar esta característica mediante "sysctl" con el uso de la variable vm.swapencrypt.enable.



Autor: David Eduardo Acosta - CISSP, CISA, CISM, PCI QSA, CCNA Security, OPST, CHFI Instructor, BS25999 Lead
Departamento Consultoría