La mayoría de vosotros ya sabréis que OSSEC es un sistema de detección de intrusos basado en host (HIDS). Si aun no lo conocéis, os recomiendo echarle un vistazo a la entrada “OSSEC como herramienta de Incident Handling”.
En esta entrada vamos a comentar la capacidad de monitorizar en tiempo real las salidas de comandos personalizados en un sistema Linux. Esta utilidad se configura en el fichero “ossec.conf”, entre etiquetas “<localfile>” y “<command>”. Si miráis este fichero, podéis ver como ya existen algunos preestablecidos, como df, netstat o last. Nosotros podemos añadir los que queramos y sean de utilidad para nuestro entorno. Por ejemplo, un comando netstat más personalizado o un listado de los módulos cargados en el kernel de Linux con lsmod. En nuestro ejemplo, proponemos el siguiente comando personalizado de netstat:
netstat -antupd |sort |awk 'BEGIN{printf "%-8s %-20s %-20s %-20s %-10s\n","PROTO", "IP/PUERTO LOCAL","IP/PUERTO REMOTO", "ESTADO CONEXION", "PROCESO LOCAL"}/ESTABLISHED/{printf "%-8s %-20s %-20s %-20s %-10s\n",$1,$4,$5,$6,$7}'|uniq
La salida del comando anterior muestra un listado de las conexiones establecidas en el equipo. Hemos utilizado awk para crear un encabezado y filtrar algunas columnas para que solo muestre las que nos interesan. La salida de la ejecución del comando anterior es:
PROTO IP/PUERTO LOCAL IP/PUERTO REMOTO ESTADO CONEXION PROCESO LOCAL tcp 127.0.0.1:3306 127.0.0.1:40146 ESTABLISHED 3192/mysqld tcp 127.0.0.1:40146 127.0.0.1:3306 ESTABLISHED 3992/ossec-dbd
El comando habrá que definirlo en el fichero de configuración ossec.conf para que sea ejecutado por el agente de OSSEC:
<localfile> <log_format>full_command</log_format> <frequency>60</frequency> <command>netstat -antupd |sort |awk 'BEGIN{printf "%-8s %-20s %-20s %-20s %-10s\n", "PROTO","IP/PUERTO LOCAL","IP/PUERTO REMOTO","ESTADO CONEXION","PROCESO LOCAL"}/ESTABLISHED/{printf "%-8s %-20s %-20s %-20s %-10s\n",$1,$4,$5,$6,$7}'| uniq</command> </localfile>
En las opciones de configuración del comando hemos indicado el tipo de formato de log, así como la frecuencia de repetición en segundos, por lo que se ejecutará cada minuto.
El siguiente paso es crear las reglas para que se disparen cuando se den las condiciones que deseamos. En nuestro caso, la regla que generaremos en el servidor es la siguiente:
<rule id="100006" level="7"> <if_sid>530</if_sid> <match>ossec: output: 'netstat -antupd</match> <check_diff /> <description>Mi netstat personalizado.</description> </rule>
La regla se disparará cuando detecte el patrón contenido entre las etiquetas <match>, comprobará la salida de este comando en el log con el generado anteriormente y, en el caso de que no coincidan, generará una alerta indicando que ha ocurrido algún cambio en las conexiones. Los resultados de cada ejecución los guarda en ficheros en el directorio /var/ossec/queue/diff/.
Para comprobar la correcta monitorización de las conexiones abrimos una conexión, podemos hacerlo con la herramienta ncat:
$ ncat -l 50000 | ncat 127.0.0.1 50000
Ahora podemos ver las alertas generadas en el log /var/ossec/logs/alerts/alerts.log:
** Alert 1407164058.25113: mail - ossec, 2014 Aug 04 16:54:18 debian->netstat -antupd ... Rule: 100006 (level 7) -> 'Mi netstat personalizado.' ossec: output: 'netstat -antupd … : PROTO IP/PUERTO LOCAL IP/PUERTO REMOTO ESTADO CONEXION PROCESO LOCAL tcp 127.0.0.1:3306 127.0.0.1:40297 ESTABLISHED 3192/mysqld tcp 127.0.0.1:40297 127.0.0.1:3306 ESTABLISHED 9986/ossec-dbd tcp 127.0.0.1:45827 127.0.0.1:50000 ESTABLISHED 10093/ncat tcp 127.0.0.1:50000 127.0.0.1:45827 ESTABLISHED 10092/ncat Previous output: ossec: output: 'netstat -antupd … : PROTO IP/PUERTO LOCAL IP/PUERTO REMOTO ESTADO CONEXION PROCESO LOCAL tcp 127.0.0.1:3306 127.0.0.1:40293 ESTABLISHED 3192/mysqld tcp 127.0.0.1:40293 127.0.0.1:3306 ESTABLISHED 9986/ossec-dbd
Hasta aquí todo funciona correctamente, pero el problema ocurre cuando utilizamos bases de datos para almacenar las alertas. Hemos configurado una base de datos MySQL para almacenar la información de OSSEC.
El problema es que cuando se genera la alerta, ésta se almacena en una tabla de la base de datos pero, debido a la sintaxis del comando personalizado que hemos utilizado, la base de datos genera un error. Esto es a causa de la existencia de comillas en el comando, las cuales provocan una ruptura en la sentencia de inserción de la query, generando un error de sintaxis. Este error lo podéis ver en /var/ossec/logs/ossec.log.
2014/08/04 16:54:21 ossec-dbd(5203): ERROR: Error executing query 'INSERT INTO location(server_id, name) VALUES ('1', 'debian->netstat -antupd |sort |awk 'BEGIN{...}'|uniq')'. Error: 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'BEGIN...' at line 1'.
¿Como podemos solucionarlo? Muy fácil, basta con ejecutar el comando a través de un script. De esta forma se almacenará el nombre del script en la base de datos en lugar del comando problemático. Los cambios ha realizar quedarían del siguiente modo:
1. Crear el script con el comando y almacenarlo en el equipo donde se encuentra el agente de OSSEC, por ejemplo en /bin/minetstat.sh:
#!/bin/bash netstat -antupd |sort |awk 'BEGIN{printf "%-8s %-20s %-20s %-20s %-10s\n","PROTO", "IP/PUERTO LOCAL","IP/PUERTO REMOTO", "ESTADO CONEXION","PROCESO LOCAL"}/ESTABLISHED/{printf "%-8s %-20s %-20s %-20s %-10s\n",$1,$4,$5,$6,$7}'|uniq
2. Cambiar la configuración del agente para que ejecute el script (ossec.conf):
<localfile> <log_format>full_command</log_format> <frequency>60</frequency> <command>/bin/minetstat.sh</command> </localfile>
3. Modificar la regla en el servidor para que detecte la nueva entrada del log:
<rule id="100006" level="7"> <if_sid>530</if_sid> <match>ossec: output: '/bin/minetstat.sh</match> <check_diff /> <description>Mi netstat personalizado.</description> </rule>
A continuación podemos ver como se ha sustituido el comando original por la ruta del script y ver como el problema con MySQL ha sido resuelto.
** Alert 1407167245.40847: mail - ossec, 2014 Aug 04 17:47:25 debian->/bin/minetstat.sh Rule: 100006 (level 7) -> 'Mi netstat personalizado.' ossec: output: '/bin/minetstat.sh': PROTO IP/PUERTO LOCAL IP/PUERTO REMOTO ESTADO CONEXION PROCESO LOCAL tcp 127.0.0.1:3306 127.0.0.1:40344 ESTABLISHED 3192/mysqld tcp 127.0.0.1:40344 127.0.0.1:3306 ESTABLISHED 12223/ossec-dbd tcp 127.0.0.1:45873 127.0.0.1:50000 ESTABLISHED 12274/ncat tcp 127.0.0.1:50000 127.0.0.1:45873 ESTABLISHED 12273/ncat Previous output: ossec: output: '/bin/minetstat.sh': PROTO IP/PUERTO LOCAL IP/PUERTO REMOTO ESTADO CONEXION PROCESO LOCAL tcp 127.0.0.1:3306 127.0.0.1:40344 ESTABLISHED 3192/mysqld tcp 127.0.0.1:40344 127.0.0.1:3306 ESTABLISHED 12223/ossec-dbd
Con estos pasos espero haber ayudado a aquellos que alguna vez se han encontrado con este problema. Además, ejecutar los comandos a través de scripts nos permite desarrollar funcionalidades mas avanzadas y mantenerlas al margen de los ficheros de configuración de reglas, facilitándonos la compresión y edición de los scripts.
Hay que tener en cuenta que estos scripts deben tener los permisos y restricciones adecuados al entorno con el fin de evitar brechas de seguridad en el sistema.
¡Hasta la próxima!