Skip to content

Registros de auditoría forense en servidores Web Apache: mod_forensics

Publicado por Sergio Hernando el 30 septiembre 2007

Buenas,

Apache es un servidor Web que no necesita presentación. Existe mucha documentación asociada a cómo compilarlo, cómo configurarlo y cómo administrarlo, así que sobre eso poco o nada tengo que decir.

Lo que os voy a contar hoy es cómo se activa y se utiliza un módulo determinado en el servidor. Ese módulo es mod_log_forensics. Las explicaciones se harán para una instalación FreeBSD, con lo que los usuarios de Linux que se anden con ojo, ya que los filesystem de *BSD difieren de los Linux, con lo que quizás algún fichero de configuración tenga distintas ubicaciones y denominaciones que las mostradas en este pequeño tutorial. La instalación la he efectuado en Apache/1.3.39

1. Los registros (logs) de Apache

Apache cuenta con muchos logs. Es natural que así sea, ya que un servidor Web necesita registrar cierto tipo de información, siempre valiosa para una gestión adecuada del mismo. Estos registros son ideales para hacer minería de datos, a efectos estadísticos, y están estandarizados bajo lo que se conoce como CLF (Common Log Format)

Los logs más populares son el log de acceso y el log de errores. El primero sirve para registrar peticiones que el servidor ha respondido correctamente, y el segundo, registra errores en las peticiones. Apache tiene muchos más registros, como el log de PID, de scripts o el de reescritura, pero no serán objeto de este análisis.

Así por ejemplo:

192.168.1.3 - - [29/Sep/2007:21:32:41 +0200] "GET / HTTP/1.1" 200 563 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7"

En este log se registra una petición correcta contra el directorio raíz del servidor (/) que ha sido atendida correctamente (200). Se presentan además la fecha, la IP solicitante (192.168.1.3) y los datos que presenta el navegador, en este caso, un Firefox en Windows XP. Esta información se vuelca en el log de acceso /var/log/httpd-access.log

[Sat Sep 29 21:46:21 2007] [error] [client 192.168.1.3] File does not exist: /usr/local/www/data/quiero_generar_un_error

En este caso se ha registrado un error, ya que hemos intentado acceder a un contenido no existente allí donde residen los ficheros HTTP (/usr/local/www/data). Esta información sobre accesos erróneos se conserva en /var/log/httpd-error.log

2. ¿Por qué mod_log_forensics?

La directiva ForensicLog se emplea para registrar, en servidores Apache, peticiones especiales para análisis forense. Para ello, cada entrada del log recibe un identificador único, asociable a las peticiones corrientes del servidor tal y como veremos más adelante, asignando para ello un token que se llama forensic-id que permite hacer evaluaciones forenses a posteriori, ya que:

* Los registros se hacen antes y después de procesar una petición, así que el log contendrá dos líneas para cada petición diferenciando por tanto las peticiones completas de las inacabadas.
* El formato es fijo, y no es posible modificar el formato de registros en ejecución.
* Ta y como veremos, si se segregan adecuadamente los logs regulares de los forenses, es posible casar información de uno sobre el otro, empleando el token de auditoría forense, y con garantías de que los datos regulares de acceso no han sido adulterados.

3. Configuracion y puesta en marcha

Lo primero es añadir, si no están presentes, las instrucciones para añadir y cargar el módulo en el fichero /usr/local/etc/apache/httpd.conf. Este fichero está ubicado en el directorio /usr/local/etc/apache/. Esto se consigue mediante las directivas AddModule, para la adición del módulo, y LoadModule, para la carga del mismo.

AddModule mod_log_forensic.c

LoadModule log_forensic_module libexec/apache/mod_log_forensic.so

Ubicarlas o añadirlas es muy fácil, ya que la instalación por defecto escribe numerosas entradas tanto para LoadModule como para AddModule. Basta con pegarlas justo detrás de la última que tengamos.

A continuación, añadimos la directiva ForensicLog, que servirá para decirle a Apache dónde debe escribir el registro forense. Para ello seguimos las instrucciones del fabricante.

Sin entrar en la opción de piping, lo único que hay que hacer es darle al módulo un nombre de fichero donde se escribirán las entradas del log forense. Un buen lugar para ubicar la directiva puede ser a continuación de la directiva CustomLog, que regula la ubicación y formato del registro de acceso del servidor sirviéndose de las definiciones presentes en la directiva LogFormat. Así tendremos las dos directivas a la vista en futuras revisiones del fichero de configuración.

ForensicLog /var/log/httpd-forensic.log

La presencia en el directorio asegura que los usuarios no podrán acceder a sus contenidos, ya que el directorio /var/log está o debería estar al menos con permisos drwxr-xr-x, siendo propiedad del root. En este caso, por simplicidad, se ha optado por escribir el registro forense en el mismo directorio donde está el registro convencional, cabiendo en este punto todo tipo de operativas: traslado a otros servidores, a carpetas especiales, etc.

4. Vinculación con los logs de acceso regulares

El siguiente paso sería asegurarnos de que el módulo escribe el identificador forense también en el log convencional, ya que así podemos cruzar datos de ambos registros empleando el token forense. Maneras hay muchas, yo recomiendo usar la directiva LogFormat, que en mi caso proporciona un log denominado combinado (es el formato por defecto en las instalaciones Apache)

Así pues, de un LogFormat por defecto del tipo:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

Pasaremos a esta nueva directiva LogFormat, con el identificador forense añadido y que resaltamos en negrita:

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{forensic-id}n" combined

Estos cambios en la configuración provocan que:

1. El nuevo formato de httpd-access.log incuirá el token de identificación forense. Imaginemos que hemos solicitado el documento http://192.168.1.5/sergio/index.html

192.168.1.3 - - [29/Sep/2007:23:42:37 +0200] "GET /sergio/index.html HTTP/1.1" 200 563 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7" Rv7GzcCoAQUAAFiYAv8

2. En paralelo, se ha escrito un registro en httpd-forensics

+Rv7GzcCoAQUAAFiYAv8|GET /sergio/index.html HTTP/1.1|Accept:text/xml,application/xml,application/xhtml+xml,text/html;
q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5|Accept-Charset:ISO-8859-1,utf-8;
q=0.7,*;q=0.7|Accept-Encoding:gzip,deflate|Accept-Language:es-es,es;
q=0.8,en-us;q=0.5,en;q=0.3|Connection:keep-alive|Host:192.168.1.5|Keep-Alive:300|
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; es-ES; rv%3a1.8.1.7) Gecko/20070914 Firefox/2.0.0.7
-Rv7GzcCoAQUAAFiYAv8

En negrita aparece el identificador forense, que es único para cada petición. Mediante ambos logs, si están debidamente segregados, podemos tener la certeza de que ante una modificación maliciosa del registro de accesos, siempre quedará un registro en paralelo vinculado al mismo, que demostrará si los contenidos del log de acceso regular son legítimos o no.

5. Reinicio del servidor

Lo último que nos queda es reiniciar Apache, para lo que ejecutaremos:

nas# /usr/local/sbin/apachectl stop

En caso de existir algún error en httpd.conf, se nos anunciará al ejecutar el reinicio. Recordad que existe una utilidad que se llama configtest, que podemos invocar para localizar el error.

nas# /usr/local/sbin/apachectl configtest
Syntax OK

6. Revisión mediante check_forensic

En el paquete del código fuente de Apache, bajo las carpetas src y support, hay un shell-script que se llama check_forensic. Mediante este script podemos analizar automáticamente todas las peticiones del registro forense, y obtener una relación de peticiones incompletas.

#!/bin/sh

# check the forensic log for requests that did not complete
# output the request log for each one

F=$1

cut -f 1 -d '|' $F > /tmp/fc-all.$$
grep + < /tmp/fc-all.$$ | cut -c2- | sort > /tmp/fc-in.$$
grep -- - < /tmp/fc-all.$$ | cut -c2- | sort > /tmp/fc-out.$$
# use -i instead of -I for GNU xargs
join -v 1 /tmp/fc-in.$$ /tmp/fc-out.$$ | xargs -I xx egrep "^\\+xx" $F
rm /tmp/fc-all.$$ /tmp/fc-in.$$ /tmp/fc-out.$$

Espero os haya sido de utilidad. Si alguien tiene alguna duda, que utilice los comentarios :)

Be Sociable, Share!

Categoría/s → Auditoria, Forensics

3 comentarios
  1. 2 octubre 2007

    Muy interesante compañero! ;)

Trackbacks & Pingbacks

  1. SigT
  2. links for 2007-09-30 » Xeon

Escribir un comentario

Note: XHTML permitido. Tu email nunca será publicado.

Suscribirse a los comentarios via RSS