En el artículo de hoy os vamos a mostrar un pequeño script que hemos realizado JoseMi Holguín (@J0SM1) y un servidor, y cuya finalidad es poder tratar el conjunto de reglas activas en una instalación de Snort y, llegado el caso, realizar modificaciones a las mismas.
El script está realizado en python, y cuenta con dos clases, una llamada ruleDissector(), que se encarga de trocear cada regla y guardar sus parámetros por separado, y otra llamada ruleseParser(), que lee los ficheros de configuración de Snort y selecciona los ficheros de reglas que están activos.
Para utilizar el script únicamente es necesario importarlo, y llamar a la siguiente función (todos los parámetros son opcionales, y se muestran los valores por defecto):
ruleset = rulesetParser(basedir = '/usr/local/snort/etc', snortfile = 'snort.conf', classiffile = 'classification.config', rulesdir = 'rules')
Una vez hecho esto, tenemos las siguientes variables disponibles:
- ruleset.base_dir: Parámetro basedir. Directorio base de la configuración.
- ruleset.snort_file: Parámetro snortfile. Fichero de configuración base a utilizar.
- ruleset.classif_file: Parámetro clasiffile. Fichero de clasificaciones.
- ruleset.rules_dir: Parámetro rulesdir. Directorio de reglas (relativo a basedir).
- ruleset.included_files: Listado de ficheros no de reglas incluidos.
- ruleset.rule_files: Listado de ficheros de reglas incluidos.
- ruleset.classification: Diccionario de clasificaciones disponibles. Nos interesa este dato ya que durante la carga del fichero de reglas introducimos en cada una la criticidad asociada a la clasificación.
- ruleset.ruleset: Listado de reglas. Cada regla es un elemento del tipo ruleDissector().
Por su parte, en la clase ruleDissector() tenemos guardadas todas las opciones de la regla (acción, protocolo, IP/Puerto origen y destino, dirección y argumentos), con las siguientes funciones para obtener información relevante:
- regla.getSid() y regla.setSid(): Obtener y fijar el SID.
- regla.getClasstype() y regla.setClasstype(): Obtener y fijar el Classtype.
- regla.getMsg() y regla.setMsg(): Obtener y fijar el mensaje.
- regla.getRev() y regla.setRev(): Obtener y fijar la revisión.
- regla.getArgument(), regla.setArgument() y regla.addArgument():Obtener, modificar, y crear nuevos argumentos.
- regla.createRule(): Imprime la regla en el estado actual en que se encuentra en memoria.
Y todo esto… ¿para qué? Pues aunque el script es muy simple, puede tener muchas utilidades.
Un posible uso puede ser el de realizar búsquedas. Por ejemplo, para comprobar, de nuestro conjunto de reglas activas, cuales cumplen cierto requisito. Si queremos saber, por ejemplo, el mensaje de todas las reglas activas relacionadas con la botnet Palevo, el código a utilizar es el siguiente:
for regla in ruleset.ruleset: if regla.getMsg().find('Palevo') != -1: print regla.getMsg()
Otra utilidad puede ser obtener estadísticas. Para saber cuantas reglas activas tienen criticidad 2, el código sería el siguiente:
contador = 0 for regla in ruleset.ruleset: if regla.getArgument('priority') == '2': contador++ print contador
También es útil, por ejemplo, para ayudarnos a decidir cual es la mejor categorización de las alertas que genera Snort hacia nuestro producto Tritón para realizar tareas de correlación avanzada.
Limitaciones y tareas pendientes
Actualmente no se detectan como dependientes del anterior todos los modificadores de los campos content, por lo que si tenemos en una regla un fragmento como el siguiente:
content:"|03|"; offset: 0; depth: 1;
Se guardará en nuestro código en tres argumentos separados, uno con nombre “content” y valor “|03|“, otro con nombre “offset” y valor 0, y otro con nombre “depth” y valor 1.
Sólo se insertan como dependientes los campos que no tienen valor, como por ejemplo el campo nocase. Para un fragmento como el siguiente:
content:".php"; nocase;
Se guardará un único argumento, con nombre “content” y valor ‘".php"; nocase‘.
Tampoco se han introducido todavía controles en las funciones getArgument y setArgument para manejar el caso en el que existan dos argumentos del mismo tipo (p.ej. dos campos content o dos campos reference), por lo que, utilizando estas variables, siempre se obtendrá/modificará el primero de ellos.
Aunque el script aún no está 100% terminado esperamos que os pueda ser de utilidad. Os animamos a utilizarlo y a escribir en los comentarios vuestra opinión, así como críticas (constructivas a poder ser ;) ) y sugerencias de mejora.
Podéis obtener el código de ruleDissector en el siguiente enlace: https://github.com/jovimon/ruleDissector
Gracias por al aporte :)
Saludos