Archivo por meses: junio 2014

Monitorización de cambios en ficheros con tripwire (II)

Si has instalado tripwire, habrás empezado a recibir correos con los cambios en el sistema de ficheros desde la última actualización de la base de datos.

En algunas ocasiones son cambios que has realizado tú, o cualquier otra persona o proceso, y que simplemente requieren que actualices la base de datos (tripwire -m u) para que queden registrados. Pero en otras ocasiones se trata de ficheros o directorios que están en constante cambio (spools de correo o impresión, directorios de usuarios, bases de datos, logs, etc…).

En este caso debemos enseñar a tripwire que esos cambios son normales (dentro de unos límites) y evitar que en el correo con el informe diario vengan listados como cambios no esperados. Esto es de vital importancia porque acabaremos acostumbrándonos a que el correo de tripwire liste un montón de cambios (y hará inútil el uso de la herramienta) y porque no podremos diferenciar un cambio normal en un fichero que varía con el tiempo, por ejemplo que cambie su fecha de modificación, de un cambio sospechoso, por ejemplo que cambie su propietario o permisos. Repito lo que dije en mi post anterior. El correo diario de tripwire debe limitarse a decir: No violations.

El fichero de políticas (/etc/tripwire/tw.pol) nos permite definir que ficheros no pueden cambiar en absoluto, cuales pueden ver su contenido modificado pero no otros atributos como propietario o permisos, cuales debemos ignorar porque varían aleatoriamente (como el $HOME de un usuario), etc. El fichero de políticas se genera partiendo de un fichero de texto (en los paquetes de la distribución suele venir uno base: /etc/tripwire/twpol.txt), es este fichero en el que definimos las reglas y posteriormente generamos el fichero de políticas real.

Adicionalmente con la documentación de tripwire (normalmente bajo /usr/share/doc/tripwire) viene un fichero de ejemplo hiper-documentado con casi todas las posibilidades que permite el fichero de políticas, su nombre es policyguide.txt.

Sintaxis

En el fichero de políticas podemos encontrar (entre otras cosas):

  • Propiedades a tener en cuenta en los ficheros o directorios a vigilar. Por ejemplo:
 g - El grupo propietario
 i - El número de inodo
 l - El tamaño de un fichero va en aumento (para logs, aunque cuando sean rotados fallaría)
 m - La fecha de modificación
 n - El número de enlaces duros. Que varía sobre todo en directorios con la creación o borrado de subdirectorios
 p - Los permisos
 s - El tamaño
 t - El tipo de fichero
 u - El propietario
 C - CRC32 del contenido
 M - MD5 del contenido
 S - SHA del contenido
  • Variables que nos permiten organizar mejor nuestro fichero. Su contenido puede ser cualquier valor que podamos usar en el fichero de políticas (el nombre de un directorio, una lista de propiedades comunes que podemos aplicar a varios ficheros, etc..):
# Para agrupar propiedades
Intocable = +pinugtsdbmCM-rlacSH;
# Y luego usarlo en reglas
/etc/passwd -> $(Intocable);
  • Ficheros o directorios sobre los que aplicar reglas:
# /etc no debe cambiar
/etc -> +pinugtsdbmM-rlacCSH;
# el mtab varia en su contenido
/etc/mtab -> +pnugtd-ismMrlacCSHM;
# este fichero puede estar o puede no estar, lo ignoramos totalmente
!/etc/foobar;
  • Agrupaciones de ficheros/directorios para aplicarles la misma gravedad ante cambios, notificar a unos destinatarios concretos o ejecutar chequeos sólo sobre ese grupo:
(Rulename=sistemabase, severity=90)
{
/etc -> +pinugtsdbmM-rlacCSH;
/bin -> +pinugtsdbmM-rlacCSH;
/lib -> +pinugtsdbmM-rlacCSH;
/usr -> +pinugtsdbmM-rlacCSH;
}
(Rulename=aplicacion, emailto=desarrollo@example.com, severity=50)
{
/usr/local/foo -> +pinugtsdbmM-rlacCSH;
/usr/local/foo/data -> +pinugtd-srlbacmCMSH;
}

 Definiendo una política

El verdadero trabajo con tripwire consiste en ajustar una política a nuestro sistema. Podemos partir de la que viene definida por el fichero de políticas que viene en el paquete (o en la instalación desde fuentes). O podemos comenzar con una de cero. Esta última opción será más dura, pero posiblemente cubrirá mejor nuestras necesidades.

Empezaríamos definiendo una regla que abarque todo el sistema de ficheros y que indica que no debe cambiar nada (luego iremos corrigiendo). Para mayor comodidad podemos definir alguna variable que englobe tipos de cambios comunes (ficheros inmutables, ficheros que cambian su contenido, cambios en las propiedades pero no en el contenido, etc..)

@@section FS

# INTOCABLE. Ignoramos la fecha de acceso, alguna propiedad
# menos interesante y los checksums CRC, Haval, y SHA1 por
# economía en los chequeos. Dejamos el MD5 para comprobar la
# integridad del contenido del fichero.
# Para los más paranoicos, mover CSH a continuación de la "M"
# Equivalente a la variable predefinida por tripwire llamada
# "ReadOnly"
INTOCABLE = +pinugtsdbmM-rlacCSH ;

# CAMBIA_CONTENIDO. Ficheros en los que el contenido cambia,
# pero que deben mantener otros atributos (propietarios,
# permisos, inodo, dispositivo,...)
# Igual que la variable "Dynamic" de tripwire
# CAMBIA_CONTENIDO = $(Dynamic)
CAMBIA_CONTENIDO = +pinugtd-srlbacmCMSH ;

/ -> $(INTOCABLE) ;

Si ya tenemos una política (ya estamos haciendo chequeos diarios), tendremos que cambiar la política con el siguiente comando:

# tripwire -m p -Z low mi_politica.txt

El motivo de usar la opción “-Z low” es que nos permita cambiar la política aún cuando ya hay ficheros que se salen de la política anterior. De otra forma no nos dejaría realizar el cambio. Si no hemos usado ninguna política hasta ahora, es decir no estamos ejecutando tripwire todos los días, deberemos de firmar nuestra política e inicializar la base de datos:

# twadmin -m P -S mi_politica.txt
# tripwire -m i

En ambos casos podemos encontrarnos con advertencias de este tipo:

The object: "/boot" is on a different file system...ignoring.
The object: "/dev" is on a different file system...ignoring.
The object: "/proc" is on a different file system...ignoring.
The object: "/run" is on a different file system...ignoring.

Se trata de sistemas de ficheros diferentes al de la partición raíz. Esto significa que debemos de añadir una regla para cada uno de ellos. En algunos casos (por ejemplo en /boot con el kernel y el gestor de arranque) querremos chequearlos y en otros ignorarlos por completo, o aplicar reglas menos estrictas. En este caso podemos añadir las siguientes reglas a nuestro fichero de políticas:

# Comprobar /boot. Necesario por ser un sistema de ficheros
# diferente al raíz
/boot -> $(INTOCABLE) ;

# Para /dev hay una variable que vigila permisos, propietarios
# y algún atributo propio de dispositivos: $(Device)
/dev -> $(Device) ;

# /proc varía mucho lo ignoramos por completo. Pero podemos
# vigilar las variables de configuración en /proc/sys
!/proc;
/proc/sys -> $(INTOCABLE) ;

# En /run tenemos ficheros de PID y sockets, podemos vigilarlos
# pero teniendo en cuenta que cambiaran sus contenidos, fechas,
# ID de dispositivo e inodo. Podemos partir de CAMBIA_CONTENIDO
# y quitar estas cosas:
/run -> $(CAMBIA_CONTENIDO) -id ;

Una vez más tendríamos que actualizar la política con el contenido de nuestro fichero de texto:

# tripwire -m p -Z low mi_politica.txt

Y una vez más veremos cosas que corregir, por ejemplo de ficheros que no se pueden leer:

### Filename: /proc/sys/net/ipv6/route/flush
### Permission denied
### Continuing...
### Warning: File could not be opened.
### Filename: /proc/sys/vm/compact_memory
### Permission denied

Así que añadimos unas reglas que ignoren esos ficheros por completo:

# Algunos ficheros en /proc/sys no se pueden leer, los ignoramos
!/proc/sys/net/ipv4/route/flush;
!/proc/sys/net/ipv6/route/flush;
!/proc/sys/vm/compact_memory;

Volveríamos a ejecutar la actualización de política (-m p) y si ya no tenemos errores mi recomendación es ejecutar un chequeo (-m c). De esta forma vamos a tener inmediatamente un listado de ficheros que están cambiando (logs, bases de datos, directorios temporales) y que por tanto hay que añadir nuevamente a la política. Y el segundo motivo es que los ficheros de tripwire habrán sido modificados con la actualización de la política y por tanto un chequeo y posterior actualización de la base de datos (-m u) evitará que en el chequeo nocturno salgan como modificados con nuestro consiguiente susto 🙂

En mi caso un chequeo me devolvió campos en el directorio de la base de datos, el spool del servidor de correo y algunos logs. Así que añadiré unas reglas que los contemplen:

# Los logs varían, pero los permisos y propietarios no.
# Si lo hará su inodo
/var/log/ -> $(CAMBIA_CONTENIDO) -i ;

# La propia base de datos de tripwire varía cuando se actualiza,
# así que no podemos vigilar el contenido. Por eso viene la
# recomendación de tenerla en un dispositivo que evite su
# modificación
/var/lib/tripwire/ -> $(CAMBIA_CONTENIDO) ;
# El directorio de informes de tripwire va creciendo
# No nos interesa el contenido, sí sus permisos
/var/lib/tripwire/report -> $(CAMBIA_CONTENIDO) (recurse=false) ;

# Del spool de postfix nos interesa su estructura, no su contenido
# Miramos sólo el primer nivel
/var/spool/postfix/ -> $(CAMBIA_CONTENIDO) -i (recurse=1) ;

# /tmp es el caos, vigilamos sólo el propio directorio
/tmp -> $(CAMBIA_CONTENIDO) (recurse=0) ;

# El HOME de root puede variar por su uso
/root -> $(CAMBIA_CONTENIDO);
# El .viminfo cambia de inodo con el uso de vim
/root/.viminfo -> $(CAMBIA_CONTENIDO) -i;

Y repetimos el proceso una vez más. Digamos que quedaría un modus operandi de este tipo:

## Editamos el fichero txt de reglas y actualizamos la política
tripwire -m p -Z low mipolitica.txt
## Ejecutamos un chequeo
## (sin prioridad de io, para dejar a la máquina hacer su trabajo)
ionice -c 3 tripwire -m c
## Si lo único que sale del chequeo son los cambios en los ficheros de tripwire,
## actualizamos la base de datos con ellos y listo
tripwire -m u -r /var/lib/tripwire/report/$( hostname ) -FECHA-HORA.twr

Una vez tengamos la política afinada, sólo tendremos que actualizar la base de datos (-m u) cuando hagamos cambios fuera del funcionamiento normal de la máquina (actualizaciones, cambios de configuración, etc.).

Una vez más, el objetivo es:

===============================================================================
Object Summary: 
===============================================================================

-------------------------------------------------------------------------------
# Section: Unix File System
-------------------------------------------------------------------------------

No violations.

===============================================================================
Error Report: 
===============================================================================

No Errors

-------------------------------------------------------------------------------
*** End of report ***

 

$ exit