scieee AI-readable full text Open interactive document viewer

Repositorio Institucional de Documentos

Abstract

El objetivo de nuestro proyecto es el de contribuir con una nueva herramienta en el campo de la "Detección y Prevención" de ataques a la seguridad de Sistemas de Información en el entorno industrial. Para esto, el software sobre el que he estado trabajando, realizará un estudio estadístico de las tramas que transmiten información y señales de control entre dispositivos electrónicos que conforman segmentos de red en sistemas de entorno industrial. El "sniffer" que aquí presento, va algo mas allá con respecto a los analizadores de paquetes que ya conocemos (Ethereal, Wireshark...). Es capaz de extraer los campos de interés que caracterizan un conexión entre dichos dispositivos, almacenar estos datos en estructuras de almacenamiento dínámicas para datos adaptadas para este propósito, llegando a realizar una completa descripción del tráfico observado; para. Para posteriormente, con dicha información, realizar "listas blancas" (comportamiento permitido), las cuales serán utlizadas por el Detector de Intrusiones de software libre conocido como Snort. Además, nuestra herramienta, será capaz de interactuar con el sistema de ficheros de Snort. Utilizando las alternativas que los Sistemas Operativos Linux nos brindan a través de script. Somos de este modo capaces de automatizar el intercambio de archivos tanto de información como de configuración entre componentes software, facilitando en definitiva la labor de un admisnistrador de red. Ruiz Mañas, Arturo; Schukat, Michael

Full text

Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Arturo Ruiz Mañas OSNA Cyber Security Research Group www.osna-solutions.com Director: Dr. Michael Schukat Ponente: Dr. José Luis Salazar Riaño email: [email protected] Zaragoza, Agosto de 2013 UNIVERSIDAD DE ZARAGOZA -------------------------------------------------------------------------------------- ESCUELA DE INGENIERÍA Y ARQUITECTURA Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Resumen A lo largo de esta memoria, voy a tratar sobre el complejo pero importante problema de la seguridad en redes de Control Industrial y sistemas SCADA (Supervisory Control And Data Acquisition). Para esto, previo a este trabajo, se me ha presentado abundante información sobre Hacking y técnicas de Intrusión ICS (Internet Connection Sharing). En el presente texto profundizaremos en una solución ante situaciones de “black-hat hacking”1para dichos entornos. Lograr un nivel alto de seguridad en nuestros sistemas de información y señales de control es el objetivo de todo empleado en seguridad informática. Durante este texto presentaré el software que he creado durante mi estancia en el grupo OSNA en Irlanda, que busca precisamente ayudar a conseguir ese nivel alto de seguridad. Para ello me baso en la idea de “Deep Packet Inspection”[30]: se toma cada paquete que la interfaz de red detecta y se examinan campos concretos del paquete. De este modo el programa realizará un estudio de los valores que dichos campos toman, originando una representación lo más precisa posible de la información que recorre nuestro segmento de red a estudiar, en forma de reglas para Snort. Además, otro objetivo añadido a mi diseño, es el combinar dos de los métodos tradicionales de seguridad informática: listas-blancas y listas-negras. Por un lado, nuestro enfoque mediante “Deep Packet Inspection”, comentado en el párrafo anterior, aporta el enfoque de “listado-blanco”, basado en listas-blancas, y por otro, el componente de listas-negras vendrá dado por la multitud de ficheros de reglas-Snort colgadas en la red, creadas por especialistas en temas de seguridad informática[Snus00], y que como “software libre” que es, podemos perfectamente descargar y utilizar a nuestro antojo. La integración en un sólo diseño de ambas filosofías, es por lo tanto, un punto interesante a tener en cuenta.Sintetizando con pocas palabras, diré que, utilizando mi programa, cuyo fin será el de elaborar una descripción lo más exacta posible del tráfico de red (listas blancas), y pasando dicha representación a Snort, programa para la “Detección de Intrusiones”, junto con ficheros de listas-negras y preprocesadores para Snort ya presentes en la Web, estamos generando una herramienta que, sin duda alguna, va a ser muy útil en las tareas de seguridad de redes y que representa a mi parecer, un recurso muy interesante a tener entre el software de todo encargado de la seguridad en sistemas de comunicaciones informáticas. i 1.Hacking se puede dividir en tres categorías diferentes: hacking de sombrero negro, hacking de sombrero blanco, y hacking de sombrero gris. Los nombres resultan muy representativos sobre sus significados. Los de sombrero negro son los “malos”, los de sombrero blanco son los “buenos”, y los de sombrero gris son lo que están entre medio. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Agradecimientos: En especial a mi familia, por todo el apoyo recibido por su parte a lo largo de estos años. Agradecimientos al grupo OSNA y en especial a Michael Schukat. Debo también agradecer a José Luis su ayuda en la composición de este escrito. ii Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Tabla de Contenidos Resumen …........................................................................................................................ i Agradecimientos …........................................................................................................... ii Tabla de Contenidos.......................................................................................................... iii Tabla de Figuras …............................................................................................................ v Lista de Tablas ….............................................................................................................. vi 1. Introducción y Exposición de Objetivos ..................................................................... 1 1.1 Introducción a la Seguridad en Redes ........................................................... 1 1.2 Ciberseguridad y Amenazas a CCI ................................................................ 1 1.3 Seguridad en Sistemas SCADA ..................................................................... 2 1.3.1 ¿Qué significa SCADA? ................................................................ 2 1.3.2 Nivel de Seguridad en los Sistemas SCADA ................................. 3 1.4 Exposición de Objetivos ................................................................................ 3 2. Requisitos de Usuario .................................................................................................. 4 2.1 Redes de Comunicación en el Entorno Industrial .......................................... 4 2.1.1 Modbus ............................................................................................ 5 2.2 IDS / IPS ( Intrusion Detection System / Intrusion Prevention System ) ...... 6 2.2.1 Snort ................................................................................................. 6 2.3 Requisitos para la Creación del Software ....................................................... 7 3. Análisis y Diseño …...................................................................................................... 8 3.1 Entorno de Trabajo …..................................................................................... 8 3.2 Librería PCAP …............................................................................................ 8 iii Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 3.3 ¿Cómo nuestro programa trabaja con Snort?.................................................... 9 3.4 Árbol de Listas Anidadas …............................................................................. 9 4. Implementación …......................................................................................................... 12 4.1 Código …......................................................................................................... 12 4.2 Diagrama de Flujo del Código ….................................................................... 12 4.3 Diagrama de Flujo del Funcionamiento del Programa.................................... 18 5. Testeo …......................................................................................................................... 20 5.1 Eficacia que No Eficiencia …........................................................................... 20 5.2 Testeo del Software........................................................................................... 21 5.2.1 Testeo del Sniffer Base y Recogida de Datos IP-TCP y Modbus …. 21 5.2.2 Testeo mediante “Sniffing” en un Entorno Controlado..................... 24 5.2.3 Testeo del Funcionamiento de los Scripts.......................................... 24 6. Conclusiones ….............................................................................................................. 24 Anexo A: Código completo. …...................................................................................................... 26 Anexo B: English report …............................................................................................................ 50 Revisión de la Bibliografía ….......................................................................................................168 iv Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Tabla de figuras Fig.1 Representación de mi software + Snort en una red conformada por nodos de interconexión (hubs / switches) … 4 Fig.2 Ejemplo de set-up de una red Modbus …................................................................................................................ 5 Fig.3 Modbus TCP – ADU …........................................................................................................................................... 6 Fig.4 Cabecera en Modbus TCP ….................................................................................................................................. 6 Fig.5 Flujo de los paquetes a través de los módulos de Snort …..................................................................................... 6 Fig.6 Ejemplo de regla Snort …....................................................................................................................................... 7 Fig.7 Nodo en una lista anidada …................................................................................................................................. 10 Fig.8 Ejemplo de lista anidada …................................................................................................................................... 10 Fig.9 Representación “reducida” de un “Árbol de listas anidadas” …........................................................................... 11 Fig.10 Nodo del Árbol de Listas Anidadas …................................................................................................................ 11 Fig.11 Visión global …................................................................................................................................................... 12 Fig.12 Pcap_loop …....................................................................................................................................................... 13 Fig.13 Carga en Árboles …............................................................................................................................................ 14 Fig.14 ip_func.c & Modbus_func.c …........................................................................................................................... 15 Fig.15 Funciones para los Árboles …............................................................................................................................ 16 Fig.16 Visión del resultado final …................................................................................................................................ 17 Fig.17 Ejecución scripts iniciales ….............................................................................................................................. 18 Fig.18 Banners de inicio …............................................................................................................................................ 18 Fig.19 Comprobación existencia de carpetas …............................................................................................................ 19 Fig.20 Distintas pantallas en el funcionamiento del programa …................................................................................. 19 Fig.21 Output de nuestro programa ….......................................................................................................................... 20 Fig.22 Estadísticas Wireshark …................................................................................................................................... 22 Fig.23 Fichero de estadísticas de nuestro sniffer …...................................................................................................... 22 Fig.24 Wireshark estadísticas “endpoints” …............................................................................................................... 23 Fig.25 Fichero de información IP-TCP ….…............................................................................................................... 23 Fig.26 Fichero de reglas IP-TCP ….............................................................................................................................. 23 v Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Lista de tablas Tabla 1 ….................................................................................................................................................................... 5 vi Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 1. Introducción y Exposición de Objetivos 1.1 Introducción a la Seguridad en Redes A día de hoy nos vemos envueltos en un mundo sin igual, en el que las comunicaciones y asuntos diarios pasan a través de una “nube” formada por multitud de máquinas y dispositivos electrónicos. Nuestros emails alcanzan su destinatario, no sin antes haber atravesado la maraña de routers que conforman Internet; ahora ya podemos sobrevivir sin poner pie en un supermercado, ya que con tan sólo un ordenador, una conexión a Internet y un pequeño número de clicks podemos realizar nuestra compra semanal; transacciones bancarias, últimos libros, ropa, redes sociales... Todo puede ser realizado, y así lo es, desde el despacho en el trabajo, o desde el confort de tu sofá en casa. Pero, ¿qué sucede en el ámbito de las empresas privadas? Datos personales, información y señales de control en entornos industriales, documentos de importancia... todo sale/llega desde/a un computador, viaja a lo largo del cable en una intranet, estando esta intranet muy probablemente conectada a la red de redes: Internet está más presente que nunca y todo el mundo debería entender el importante papel que juega la Seguridad en Redes en todo esto. Guste o no, nos encontramos inmersos de lleno en una era digital, en la cual todo es traducido a unos y ceros. Dicho esto, diría que un buen punto de partida para este documento podría consistir en definir con pocas palabras lo que es la “Seguridad en Redes”. Así pues, ¿qué es la Seguridad en Redes? •Según la Wikipedia [1]: La seguridad en redes consiste en las medidas y políticas adoptadas por un administrador de red para prevenir y monitorizar accesos no autorizados, malos usos, modificaciones o restricciones a una red de computadores o recursos de red accesibles a través de la misma. •La Webopedia dice [2]: Un campo especializado dentro del “computer networking” que involucra la seguridad de una infraestructura de la red. La seguridad en redes es normalmente manejada por un administrador de red o administrador del sistema que implementa las políticas de seguridad, el software y el hardware necesitados para proteger una red y los recursos accedidos a través de la misma de accesos no autorizados. •Una definición más simple la tenemos en la revista digital “ Magazine Encyclopedia”[3]: Protección de sistemas de computadores en red de intrusiones no deseadas. En definitiva, podemos concluir que la Seguridad en Redes previene de ataques y posibles amenazas, protegiendo los sistemas de computadores que posibilitan el desarrollo de nuestras actividades diarias. Pero también podríamos plantear esto desde otra perspectiva, considerando las implicaciones de la Seguridad de Redes, una vez las medidas de seguridad han sido vulneradas, y afirmar que se ocupa de controlar y monitorizar lo que dentro de la red sucede, de modo que se pueda verificar que todo está dentro de un orden, y en caso contrario poner medidas al respecto. 1.2 Ciberseguridad y Amenazas a CCI Para explicar correctamente el contexto de este trabajo, me gustaría hablar sobre qué representa el término Ciberseguridad y qué son los Ataques a CCI (Conexión Compartida a Internet) para posteriormente realizar la exposición de objetivos. En el mundo actual, ataques contra IC (Infraestructuras Críticas) de energía, gas, petróleo, agua... están creciendo, y no es extraño conocer que detrás de dichos ataques se encuentran organizaciones respaldadas económicamente tanto por empresas competidoras como incluso por 1 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort gobiernos de países[32]. Basta tan sólo para dar un marco real a este punto, con consultar en Internet artículos de periódicos, que en los meses que llevamos de año 2013, hacen referencia a ataques a la seguridad informática: •HuffingtonPost [31] → Posted: 05/16/2013 : “Syria faced an Internet blackout for eight hours on Wednesday, its second one in the past week and the sixth one of the two-year uprising against President Bashar al-Assad, a U.S. web trafficking firm reported. Phone lines into Damascus were also down.” •Informe Semanal [33] - Espionaje masivo → 15 jun 2013 “Edward Snowden era, hasta hace unos días, uno más de los miles de empleados anónimos que analizan la información para las agencias de inteligencia del Gobierno de Estados Unidos. Huido a Hong Kong y después en paradero desconocido, se ha convertido en uno de los hombres más buscados por el FBI. ” •esmateria.com [39]→ “La ciberguerra es inevitable” 04/06/2013 “Los expertos advierten de que las infraestructuras críticas dependen de sistemas vulnerables” •BBC News Technology [40]→ 19 May 2013 Last updated at 23:52 GMT “How to hack a nation's infrastructure” La lista de noticias que hablan sobre hechos relacionados con ciberseguridad/ciberataques es larga, podemos sin duda encontrar una buena colección de páginas web que dan cuenta de estos hechos. Dedicar sólo unos instantes a leer alguna de estas noticias, nos ayuda a comprender por qué es tan importante invertir esfuerzos en asegurar y proteger las redes de datos y entornos como el que tratamos en este texto. 1.3 Seguridad en Sistemas SCADA 1.3.1 ¿Qué significa SCADA? El acrónimo SCADA hace referencia a Supervisory Control And Data Acquisition. Los sistemas SCADA son un tipo de CCI, en concreto son sistemas controlados por computador cuya tarea es monitorizar y controlar sistemas industriales. Han estado presentes en nuestras vidas desde principios de los años 70, permitiéndonos controlar remotamente dispositivos distribuidos a lo largo de grandes extensiones. Ejemplos de sistemas SCADA son los sistemas que permiten a operadores establecer y modificar condiciones que hacen saltar alarmas que controlan la temperatura en sistemas de control de temperatura por enfriamiento de agua en ciertos procesos industriales; o los sistemas que monitorizan los niveles alto y bajo en tanques de agua, y alertan cuando el nivel de agua ha alcanzado un cierto límite... Existen muchos ejemplos de sistemas SCADA que desarrollan importantes funciones en procesos que intervienen directamente en nuestro bienestar social y calidad de vida. El diseño de los sistemas SCADA ha evolucionado mucho a lo largo de los años. Su arquitectura consiste en un sistema de computadores centrales que se comunican con otras máquinas usando una o más tecnologías de comunicación. Durante la última década, Internet también se ha incluido en el diseño de estos sistemas, de este modo, por un lado, se les está dotando de una mayor flexibilidad y funcionalidades extra, pero a su vez, por contra, resultan en sistemas mucho más vulnerables a ataques, siendo esta la motivación de este trabajo. 2 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort en tus programas. El modo en el que se usan siempre es el mismo: comienzas usando una función “open”, que abre un flujo de datos sobre el cual puedes leer y/o escribir como si fuera un archivo normal. La idea de las API concuerda con la filosofía Linux (y previamente UNIX) de “hacerlo todo 'un archivo' ” (el sistema operativo “mapea” cualquier hardware conectado al PC como si fuera un archivo) resultando en un nivel de “abstracción” que facilita el trabajo. PCAP (Packet CAPture) es precisamente una implementación de API que se usa para capturar tráfico de red. Es la base hoy en día para cualquier programa sniffer o cualquier Sistema de Detección de Intrusiones como Snort o sniffers tales como Wireshark. Conocidos paquetes software como “Aircrack-ng suite” [Hck01] también basan sus funcionalidades en PCAP. Los sistemas operativos tipo UNIX implementan PCAP en su librería libpcap,y podrá ser utilizada en tareas de programación C tras su inclusión mediante la sentencia #include <pcap/pcap.h>, donde pcap.h es el fichero de cabecera. 3.3 ¿Cómo nuestro programa trabaja con Snort? Snort trabaja contrastando las reglas que describen comportamientos permitidos y no permitidos y que están contenidas en sus ficheros de reglas, con el tráfico que observa en su NIC (Network Interface Card). Esta NIC, por su parte, deberá estar en modo promiscuo, lo que significa que deberá de ser capaz de captar cualquier paquete que vea circulando en su segmento de red [Hck01] . El aporte de una filosofía de “listas blancas” implementando la idea de “Deep Packet Inspection” (DPI) [30] va a ser nuestro aporte principal al campo de la Detección de Intrusiones; pero, ¿cómo podemos crear estas listas que describen el comportamiento permitido en nuestra red, sin necesidad de hacerlo a mano y afinar al máximo en la descripción de dicho comportamiento? Snort posee un modo propio de descripción de los comportamientos que se emplea en la elaboración de reglas, que consiste en una estructuración concreta y forma de escritura particular de sus reglas, al cual, los archivos resultado de nuestro software, se deben adaptar, de modo que podamos entendernos con Snort. Poniendo a correr mi software, durante una fase de estudio inicial del tráfico de red en el segmento a controlar, el sniffer que he elaborado, será capaz de generar reglas Snort que describan el comportamiento a nivel IP-TCP (referente a direcciones y puertos) y a nivel Modbus (recogiendo los campos de funciones, números de identidad, longitud paquete Modbus), automatizando el proceso de creación de reglas blancas y cumpliendo con los puntos 2 y 3 de los requisitos parciales de usuario. Posteriormente, y una vez finalizado este proceso de estudio, también será capaz de interactuar con el sistema de archivos y ficheros de Snort, colocando estos ficheros de reglas (además de las reglas negras que se decidan incluir al diseño) dentro de las carpetas que Snort utiliza para almacenar los ficheros de este tipo y modificará el fichero de configuración de Snort mediante sentencias “include”, permitiendo al sensor conocer la existencia de nuestros nuevos ficheros de reglas. En definitiva el proceso resulta muy automático y alivia en gran medida las tareas de cualquier administrador de red, facilitando el proceso de “ajuste” de un sensor IDS/IPS Snort. 3.4 Árbol de Listas Anidadas Todo programa que se precie de realizar una función útil, deberá contener estructuras de datos donde almacenar el valor de sus variables. Mi programa necesita almacenar los datos con los que realizar estadísticas, la estructura que utilizaré la he llamado “Árbol de listas anidadas”. De modo que podamos entender qué son y cómo he llegado a ello, muestro a continuación el pensamiento evolutivo que me ha llevado hasta dar con la idea del “Árbol de Listas Anidadas”: 9 _ _ struct linked list node { ; void data _ _ * ; struct linked list node ptr } Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 1. Primera idea: arrays; el principal problema que presenta un array es la delimitación del mismo: declarar el número de variables que lo componen. Por el tipo de problema al que nos enfrentamos, no podemos determinar a priori cuántas variables vamos a necesitar; si lo hiciéramos, estaríamos haciendo un uso ineficiente de memoria. 2. Necesitamos algo que pueda ser determinado a tiempo real. Las listas anidadas nos dan la facilidad de reservar espacio de memoria dentro del “heap” de un programa, y sólo, cuando sea necesario. Por contra, esta segunda opción no termina de cubrir nuestras necesidades, de algún modo perdemos una dimensión, no somos capaces de establecer una clasificación por niveles (direcciones IP, puertos, función, longitud, identidad). Esto hace que esta segunda idea no termine de encajar. 3. Pero, ¿qué tal si extendemos la idea de listas anidadas buscando obtener una dimensionalidad extra? Utilizando listas anidadas, pero añadiendo un segundo puntero (un puntero para los datos de un mismo nivel y otro puntero para los datos del nivel/tipo inmediatamente inferior) guardaríamos datos, siempre y cuando, fuera necesario mediante la asignación dinámica que caracteriza a las listas anidadas, utilizando de manera eficiente la memoria; pero además tendríamos la información almacenada por niveles obteniendo tal dimensionalidad buscada. Basándonos en un diseño de listas anidadas simple y unidimensional, lo primero que se me ocurre es presentar el “struct” que se usa para almacenar datos en este método de almacenamiento: Fig.7 Nodo en una lista anidada Ejemplificándolo, pudieran existir los 5 nodos siguientes en una lista anidada: Fig.8 Ejemplo de lista anidada Cada nodo estará representado por un “struct” como el anterior: cada ai representa el dato dentro de la estructura y el número contenido en el segundo recuadro (800, 712, 992, 692, 0) es la dirección de la siguiente estructura dentro de la lista anidada. Los números bajo los recuadros internos son la dirección de la estructura de datos dibujada sobre ellos. Las estructuras serán emplazadas en memoria mediante asignación dinámica[AlWe0], siendo esto la ventaja frente a la utilización de arrays: mediante asignación dinámica somos capaces de usar únicamente la memoria necesaria, sin desperdiciar, o hacer corto de la misma. Volviendo a la idea de “Árbol” y uniendo diseño y requisitos de usuario: en el punto dos, se habla sobre la recogida de información de campos del paquete IP (direcciones IP) y segmento TCP (puertos); en el punto tres, incluimos Modbus al diseño, en cuyo caso, nuestro “Árbol de Listas Anidadas” se deberá extender varios niveles “hacia abajo” con el fin de dar cabida a tres campos extra (función, identidad y longitud). Así, vemos un cierto numero de niveles que se corresponden con el tipo de datos que la variable en sí contiene. Ya de aquí, extendiendo la idea de listas anidadas mediante la añadidura de un puntero más, obtenemos la idea de “Árbol de Listas Anidadas”, que es capaz de cubrir a la perfección nuestras necesidades de almacenamiento. 10 Dato dentro de la estructura. Dirección al nodo siguiente en la lista anidada. _ _ struct ip node t { * ;void ptrdata _ _ * _ ; struct ip node t ptr r _ _ * _ ; struct ip node t ptr b } Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort La siguiente figura muestra una posible realización de un “Árbol” que acumula datos IP-TCP: Fig.9 Representación “reducida” de un “Árbol de listas anidadas” La idea es que cada vez que el programa encuentre en un paquete una nueva combinación de los campos dirección Ip fuente, dirección Ip destino, número de puerto fuente y número de puerto destino, respecto a combinaciones anteriormente vistas, deberá incluir nuevos nodos en el árbol. Explicando la figura anterior en la que se mostraba un pequeño Árbol: •Llega un primer paquete con direcciones Ip fuente 207.144.24.5, dirección Ip destino 110.87.25.74, número de puerto fuente 450 y número de puerto destino 80. Como la lista estaba vacía, esta combinación de datos no están aun almacenados, así que los guarda. Reservando para ello espacio y completando los campos de nuestra estructura de datos. •Llega un segundo paquete con direcciones Ip fuente 207.144.24.5, dirección Ip destino 78.207.124.25, número de puerto fuente 1240, número de puerto destino 21. Como la dirección Ip fuente ya la tenía y el primer campo nuevo en aparecer es la dirección Ip destino; a partir de este nodo, se plantea una nueva conexión desde este nodo hacia una posición de memoria que almacene la nueva dirección Ip destino y, a partir de ésta, el resto de campos de información (número de puerto fuente y número de puerto destino). •Siguiente paquete: Ip fuente 207.144.24.5, dirección Ip destino 78.207.124.25, número de puerto fuente 80 y número de puerto destino 1562. Los nuevos campos son los números de puerto. Desde el nodo que contiene la información de dirección Ip destino 78.207.124.25 se añade un nuevo nexo a otro nodo que contenga la información del nuevo número de puerto fuente y de este, un nexo a otro nodo con la información de número de puerto destino. Y así, este proceso continuaría, comparando la información ya presente con la información que llega en el nuevo paquete. El árbol, puede ser tan extenso como nueva información vaya llegando. ¿Cuánta información debe ser almacenada? Eso dependerá del diverso número de máquinas y del número de conexiones diferentes que se establezcan entre ellas. La estructura de datos que utiliza cada nodo del “Árbol” presentado es la siguiente: Fig.10 Nodo del Árbol de Listas Anidadas 11 207.144.24.5 110.87.25.74 450 80 78.207.124.25 1240 21 80 1562 10.10.0.5 98.200.128.14 23 5051 1025 1110 Dirección de memoria del dato. Dirección de memoria del siguiente nodo que contiene información del mismo tipo. Dirección de memoria de la “hoja” que contiene información del siguiente nivel. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 4. Implementación 4.1 Código Los archivos que componen el software creado durante estos meses para el proyecto: . ├── 0.compiling.sh ├── DOC_README.odt ├── 1.remove.sh ├── DOC_README.pdf ├── conf_Snort_files ├── ip.c │ ├── classification.config ├── ip_func.c │ ├── important_considerations ├── ip.h │ ├── input ├── ip_node.h │ ├── output ├── merge_ip.c │ ├── reference.config ├── Modbus_func.c │ └── Snort.conf ├── Modbus_node.h ├── demos ├── moving_conf_files.sh │ ├── demo1 ├── moving_rule_files.sh │ ├── demo2-less read traffic ├── opt_Snort_etc.sh │ ├── demo3-UnsolicitedPacketsfrom05 ├── opt_Snort_rules.sh │ ├── demo3-UnsolicitedPacketsfrom06 ├── var_log_Snort.sh │ ├── FC1-permit.pcap ├── rules │ ├── http.cap │ ├── backdoor.rules │ ├── Modbus_FC_1_Coil.pcap │ ├── community-virus.rules │ └── Modbus.pcap │ ├── dos.rules │ ├── ftp.rules └ └── icmp.rules 4.2 Diagrama de Flujo del Código ¿Cómo conectan los archivos previamente expuestos? Fig.11 Visión global 12 Scripts de compilación y eliminación de ficheros de realizaciones anteriores. Configuración de Snort Ficheros .pcap usados para testeo Ficheros principales de código Scripts de gestión de archivos de reglas y carpetas de configuración dentro de las jerarquías de carpetas de Snort. CARPETA “rules”: Aquí añadiremos los ficheros de reglas negras que queremos para nuestro diseño. Mi sniffer añadirá estos ficheros dentro de la carpeta de reglas de Snort e incluirá una sentencia “include” dentro del fichero de configuración para que Snort las tenga en cuenta. Estos “.rules” son una elección mia, pero se podrán añadir todos aquellos que un administrador de red decida añadir. ip.c Archivos de funciones: - ip_func.c - modbus_func.c - merge.c moving_conf_files.sh moving_rule_files.sh opt_snort_etc.sh opt_snort_rules.sh var_log_snort.sh Archivos de cabecera: - ip.h - ip_node.h - modbus_node.h NIC Paquetes que la NIC detecta Uso llamada “system” Retorno del Script Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Fig.12 Pcap_loop En este punto tenemos la estructura general del programa. Primeramente se comprueban los switches con los que se invoca al programa: -n, -i, -f. Con los switches -f, y -i se indica desde dónde va a “leer” el sniffer (desde fichero .pcap o desde interfaz de red); en el caso de leer desde .pcap, éste se “toma” como si fuera la misma interfaz de red (NIC), pero resulta interesante entender la distinción. Para la fase de testeo este switch -f es de especial importancia. Usando las funciones de librería “pcap_open_” se ha abierto un descriptor de flujo que nos sirve para trabajar con el “interfaz” como si trabajásemos con un fichero cualquiera; es aquí donde comenzamos a hacer uso de la abstracción que la API PCAP nos brinda. El switch -n indica el número de paquetes que conformarán la fase de estudio del segmento de red, el software deberá trabajar hasta que se hayan registrado/estudiado dicho número de paquetes. Una vez llegado a dicho número, se termina dicha fase de estudio y se comienza la organización de ficheros estadísticos y de reglas como se ha indicado en el recuadro inferior más a la derecha. 13 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Profundizamos en la ejecución del programa: •Volcado a estructuras de datos, uso ip_func.c y Modbus_func.c para generación de Árboles y obtención de primeras estadísticas (statistics.txt) y datos de “sniffing” (sniff_data.txt) : Fig.13 Carga en Árboles 14 ip_func.c modbus_func.c Statistics.txt sniff_data.txt ICMP UDP Others TCP pcap_open_ * NIC pcap_loop configurada con nuestra función recurrente Tipo de paquete: - ARP - RARP - IP - otros Volcado Ethernet Volcado IP Volcado TCP ¿IP? Sí No Return ¿Tipo paquete IP ? Esperar que la NIC detecte otro paquete Test Modbus Modbus No Modbus D e b o aña d i r a q u í u n a p u n t e, y e s q u e a u n q u e n o s e h a c o m e n t a d o e n l o s r e q u i s i t o s d e u s u a r i o , e s t e p r og r a m a e s t a p e n s a do p a r a t r a b a j a r e n r e d e s c u y a b a s e s e a E t h e r n e t . “Árbol de listas dinámicas IP” “Árbol de listas dinámicas Modbus” Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort •Uso de funciones en ip_func.c: “Árbol de listas dinámicas IP”. Fig.14 ip_func.c & Modbus_func.c 15 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort •Dentro de ip_func.c y Modbus_func.c: 16 insertBranch m_insertBranch Árbol Ip Árbol Modbus ¿Tenemos dirección Ip fuente? ¿Tenemos dirección Ip destino? ¿Tenemos puerto fuente? ¿Tenemos puerto destino? Sí No Sí Sí Sí No No No Insertamos Ip fuente, Ip destino, puerto fuente y puerto destino Insertamos Ip destino, puerto fuente y puerto destino Insertamos puerto fuente y puerto destino Insertamos puerto destino ¿ Árbol vacio ? ¿Tenemos dirección Ip fuente? ¿ Árbol vacio ? ¿Tenemos dirección Ip destino? ¿Tenemos puerto fuente? ¿Tenemos puerto destino? ¿Tenemos info sobre longitud? ¿Tenemos info sobre identidad? ¿Tenemos info sobre función? Campos propios Modbus Return función recurrente Sí Sí Sí Sí Sí Sí No No No No No No No Sí Insertamos Ip fuente, Ip destino, puerto fuente, puerto destino, longitud Modbus, identidad Modbus, función Modbus. Insertamos Ip destino, puerto fuente, puerto destino, longitud Modbus, identidad Modbus, función Modbus. Insertamos puerto fuente, puerto destino, longitud Modbus, identidad Modbus, función Modbus. Insertamos puerto destino, longitud Modbus, identidad Modbus, función Modbus. Insertamos longitud Modbus, identidad Modbus, función Modbus. Insertamos identidad modbus, función Modbus. Insertamos función Modbus. Return función recurrente Cuando se dice en esta imagen “insertamos”, quiere decir que añadiremos nueva información al Árbol correspondiente a partir de dónde se ha descubierto que el paquete con el que se trabaja contiene información nueva. Fig.15 Funciones para los Árboles Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort •Funcionamiento general: Entendidas las anteriores partes podemos conectarlas y tener una visión completa del funcionamiento. Fig.16 Visión del resultado final 17 SNORT Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 4.3 Diagrama de Flujo del Funcionamiento del Programa. Haremos uso de los scripts creados para borrar y compilar. Primeramente, realizamos un borrado de ficheros, resultado de alguna ejecución previa (1.remove.sh), tras lo cual ejecutaremos el script 0.compiling, que compila y enlaza ficheros “objeto” para crear el ejecutable: sniffer.out. De este modo: Fig.17 Ejecución scripts iniciales Tras el proceso de compilación, vemos una pequeña información sobre cómo usar el programa. Como en puntos anteriores se hizo mención, el programa puede funcionar leyendo desde la interfaz de red o desde un fichero “pcap” que contenga información recogida en una captura anterior con programas del tipo wireshark o tcpdump. Los switches son bastante autodescriptivos: •“-i” : switch utilizado para indicar qué interfaz de red es la que se estudiará. •“-n” : número de paquetes que implica el estudio. Una vez “sniffados” y estudiados “n” paquetes, el programa concluirá y comenzará la etapa de creación de ficheros de información y de reglas. •“-f” : se usa para indicar la ruta del fichero “pcap” a estudiar. Diagrama de flujo para “sniffer” en modo interfaz de red: ./sniffer -i wlan0 -n 1000 En una primera fase del programa se nos presentan banners informativos (sobre instalación de Snort e inputs y outputs del sniffer). Fig.18 Banners de inicio 18 Estudiaremos el tráfico relacionado con la interfaz wlan0, en concreto 1000 paquetes de información. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort sucesión de etapas marcadas por los requisitos parciales de usuario y que culminan en un programa que es capaz de satisfacer la motivación del proyecto. De cara a un futuro, se plantea realizar mejoras al software: •Uso de un mayor número de preprocesadores en las reglas Snort que permitan una mejor definición del tráfico permitido. •Generalización del software a otros protocolos de Entorno Industrial. •Posibilidad de incluir en el diseño el desarrollo de reglas para otros IDS. •Tratamiento y estudio del “payload” del paquete Modbus. Respecto a la inclusión al diseño de técnicas para la Detección de Anomalías, se estudió la posibilidad de inclusión de estudio estadístico del paquete a través de N-gramas, alternativa que se descartó debido al gran trabajo que ésto necesitaría y lo imperfecto del método. El problema del estudio estadístico a través de N-gramas se basa en su incapacidad para distinguir entre tráfico “bueno” y “malo”, creando demasiados falsos positivos, ya que no tiene en cuenta la estructura del paquete y los diferentes campos de la cabecera del mismo. En su lugar, lo que mi diseño hace es un “Deep Packet Inspection”, comprobando las características de diversos campos del paquete, lo que además constituye una diferencia importante entre mi enfoque y otros enfoques. Snort es una herramienta de software libre, cuyo código está abierto a posibles modificaciones: una de las alternativas de las que se dispone es, precisamente, la implementación de plug-ins que funcionen con Snort, pero realizando tareas concretas, para las cuales, dicho IDS software, aún no tiene herramientas específicas. Futuras inclusiones al diseño presentado durante este trabajo, pasarían entonces por programar preprocesadores que permitan realizar estudios más detallados del paquete, siendo usados directamente en las reglas, permitiendo unas reglas más concretas. El campo de la Detección y Prevención de Intrusiones es un campo dentro de la Seguridad de Redes abierto a nuevas ideas y con un amplio horizonte de desarrollo para los jóvenes ingenieros. Es un campo complejo con continuas mejoras, pero un campo en el cual cada día surgen nuevos problemas. Un campo, que constituye un aspecto muy importante dentro de las Telecomunicaciones y que, a día de hoy, cobra una especial relevancia por lo presente que las redes de comunicaciones están en nuestras vidas, ya sea a través de nuestros ordenadores y móviles conectados a la Red, o a través de Sistemas Industriales y sistemas SCADA que buscan facilitar y mejorar nuestra calidad de vida. 25 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort ANEXO A: Código completo #! /bin/sh # 1.remove.sh rm *.o 2> /dev/null rm *~ 2> /dev/null rm sniffer 2> /dev/null rm -r ./info_docs 2> /dev/null rm ./rules/Snort.conf 2> /dev/null rm ./rules/ip_tree.rules 2> /dev/null rm ./rules/Modbus_tree.rules 2> /dev/null rm ./conf_Snort_files/*~ 2> /dev/null echo "...remove.sh done" #! /bin/sh # 0.compiling.sh gcc ip.c -c gcc ip_func.c -c gcc Modbus_func.c -c gcc merge_ip.c -c gcc ip.o ip_func.o Modbus_func.o merge_ip.o -o sniffer -lpcap echo "...compilation process done" echo "...usage:\t ./sniffer -i <interface> -n <number of packets>" echo "...usage:\t ./sniffer -f <file_name>" //ip.h #ifndef _IP_H_ #define _IP_H_ #include <time.h> #include <sys/types.h> #include <pcap/pcap.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #define BUFSIZE 2048 #define APP_NAME "ip.out" #define SIZE_ETHERNET 14 #define ETHER_ADDR_LEN 6 enum eth_type { ARP=0, RARP=1, IP=2, UNKNOWN=3, INV_IP_HEADER=4 }; enum upper_eth_type { TCP_NO_Modbus=0, TCP_Modbus=1, ICMP=2, UDP=3, UP_UNKNOWN=4, }; /* data structures for IP */ 26 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort #define ETHER_ADDR_LEN 6 /* Ethernet header */ struct sniff_ethernet { u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */ u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */ u_short ether_type; /* IP? ARP? RARP? etc */ }; /* IP header */ struct sniff_ip { u_char ip_vhl; /* version , header length */ u_char ip_tos; /* type of service */ u_short ip_len; /* total length */ u_short ip_id; /* identification */ u_short ip_off; /* fragment offset field */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src; /* source ip address */ struct in_addr ip_dst; /* dest ip address */ }; #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f) #define IP_V(ip) (((ip)->ip_vhl) >> 4) /* TCP header */ typedef uint32_t tcp_seq; struct sniff_tcp { u_short th_sport; /* source port */ u_short th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ u_char th_offx2; /* data offset, rsvd */ #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4) u_char th_flags; /* flags */ u_short th_win; /* window */ u_short th_sum; /* checksum */ u_short th_urp; /* urgent pointer */ }; /* Modbus-TCP header */ struct sniff_Modbus_tcp { u_short mtcp_trans_id; /* synchronization */ u_short mtcp_prot; /* protocol identifier */ u_short mtcp_len; /* remaining! bytes in this frame */ u_char mtcp_iden; /* identifier */ u_char mtcp_func; /* function code */ }; /* protypes */ void our_callback(u_char *,const struct pcap_pkthdr* ,const u_char* ); void print_app_banner(char *,int); void create_Statistics (struct tm *,struct tm *,double,int,int ) ; void tail_banner(void); void pantallazo(int); void merge_ip(char *); #endif // ip.c #include "ip.h" 27 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort #include "ip_node.h" #include "Modbus_node.h" /*global variables for statistics */ int packet_type[5]={0,0,0,0,0}; /* statistics of ethernet frame type in our network */ int info_type[5]={0,0,0,0,0}; /* statistics of info type inside the IP payload */ FILE *statistics; FILE *ip_tree; FILE *sniff_data; FILE *ip_tree_rules; FILE *Modbus_tree; FILE *Modbus_tree_rules; struct ip_node_t *s; struct Modbus_node_t *r; /* * MAIN * */ int main (int argc, char **argv) { /* vars */ int n_packets; /* number limit of packets we sniff */ char char_aux_i=0,char_aux_n=0; /* checking flags from the terminal process */ char errbuf[PCAP_ERRBUF_SIZE]; /* holds the error string message in pcap functions */ pcap_t *handler; /* pcap handler */ time_t timer_init,timer_end; /* for time-stamps */ struct tm *st_timer_start,*st_timer_end; /* for time-stamps */ double time_diff; /* holds the difference of time the program has used */ int i; /* for loops */ //getting options for the program int flag_n=0, flag_i=0, flag_f=0; int c; char *nvalue = NULL; char *ivalue = NULL; char *fvalue = NULL; opterr = 0; while ((c = getopt (argc, argv, "n:i:f:")) != -1) { switch(c) { case 'n': flag_n = 1; nvalue = optarg; n_packets = atoi(nvalue); break; case 'i': flag_i = 1; ivalue = optarg; break; case 'f': flag_f = 1; fvalue = optarg; break; case '?': fprintf(stderr,"usage: ./ip.out -i <interface> -n <number_of_packets>\n"); fprintf(stderr,"usage: ./ip.out -f <file_name>\n"); exit(1); 28 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort default: fprintf (stderr,"Unknown option character `\\x%x'.\n",optopt); fprintf(stderr,"usage: ./ip.out -i <interface> -n <number_of_packets>\n"); fprintf(stderr,"usage: ./ip.out -f <file_name>\n"); exit(1); } } // checking for a correct combination of switches if( !( (flag_f && !flag_i && !flag_n ) || (!flag_f && flag_i && flag_n ) ) ) { fprintf(stderr,"misuse of the program switches\n"); fprintf(stderr,"usage: ./sniffer.out -i <interface> -n <number_of_packets>\n"); fprintf(stderr,"usage: ./sniffer.out -f <file_name>\n"); exit(1); }else { if( !flag_f ) print_app_banner(ivalue,n_packets); else print_app_banner(fvalue,0); } // initialize linked list s = (struct ip_node_t *)createList(); r = (struct Modbus_node_t *)m_createList(); // opening sniff_data to hold the sniffer's output sniff_data = fopen("sniff_data.txt","w"); ip_tree_rules = fopen("ip_tree.rules","w"); Modbus_tree_rules = fopen("Modbus_tree.rules","w"); // stablishing handler for sniffing: if(!flag_f) { if( ( handler = pcap_open_live(ivalue,BUFSIZ,1,10000,errbuf)) == NULL ) { printf("\n%s %s: %s\n","Couldn't open device",ivalue,errbuf); fprintf(stderr,"\n%s\n","exiting......"); exit(1); } } else if( ( handler = pcap_open_offline(fvalue, errbuf) ) == NULL ) { printf("\n%s %s: %s\n","Couldn't open device",ivalue,errbuf); fprintf(stderr,"\n%s\n","exiting......"); exit(1); } // printing time stamp of beginning timer_init=time(NULL); st_timer_start=localtime(&timer_init); printf("\n -== %s %02d/%02d/%d at %02d:%02d:%02d ==-\n","Beginning test on", st_timer_start->tm_mday,st_timer_start->tm_mon,st_timer_start->tm_year, st_timer_start->tm_hour,st_timer_start->tm_min,st_timer_start->tm_sec ); // opening files for the linked trees ip_tree = fopen("ip_tree.txt","w"); Modbus_tree = fopen("Modbus_tree.txt","w"); 29 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort // entering in the loop if((pcap_loop(handler,n_packets,our_callback,NULL))==-1) { fprintf(stderr,"\n%s\n","error ocurred while in loop, exiting now..."); exit(1); } // exiting,printing statistics and closing files timer_end = time(NULL); st_timer_end = localtime(&timer_end); printf("\n%s %2.2lf %s\n"," -== Time test process :",time_diff = difftime(timer_end,timer_init),"segs. ==-"); //creating and closing statistics file pcap_close(handler); statistics = fopen("statistics.txt","w"); for(i=0,n_packets=0;i<5;i++) n_packets += packet_type[i]; create_Statistics(st_timer_start,st_timer_end,time_diff,n_packets,flag_f); fclose(statistics); fclose(sniff_data); //reading from the tree and free-ing the allocated space readTree_ip(s); m_readTree_Modbus(r); fclose(ip_tree); fclose(Modbus_tree); freeTree_ip(s); m_freeTree_Modbus(r); printf("\n%s\n\n"," ----statistic control finished, please, wait----"); fprintf(ip_tree_rules,"alert ip any any -> any any (msg:\"communication out of our ip-white-list\";)"); fclose(ip_tree_rules); fprintf(Modbus_tree_rules,"alert ip any any -> any any (msg:\"communication out of our Modbus-white-list\";)"); fclose(Modbus_tree_rules); // merging together the rules in order to get more compact rule files merge_ip("ip_tree.rules"); // creating folder info_docs and moving files into it tail_banner(); exit(0); } 30 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort /* * our functions */ void our_callback(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet) { static int count = 1; /* packet counter */ u_short eth_type; /* ethernet type in host byte order for switch use */ int Modbus_flag = 0; /* Modbus_flag = 1 when it detects a Modbus protocol packet */ char mybuff[50]; /* inet_ functions use statically allocated memory */ /*aux variables to help in the use of tree_linked_list */ u_short sportaux,dportaux; u_short m_lenaux; u_char m_idenaux,m_funcaux; /* declare pointers to packet headers */ const struct sniff_ethernet *ethernet; /* The ethernet header [1] */ const struct sniff_ip *ip; /* The IP header */ const struct sniff_tcp *tcp; const struct sniff_Modbus_tcp *Modbus_tcp; /* The Modbus TCP header */ /* sizes of ip frame and tcp segment */ int size_header_ip; int size_header_tcp; char test_Modbus = 0; fprintf(sniff_data,"\nPacket number %d:\n", count); fprintf(sniff_data,"--------------------- \n", count); count++; /* define ethernet header torrent*/ ethernet = (struct sniff_ethernet*)(packet); eth_type=ntohs(ethernet->ether_type); switch (eth_type) { case(0x0806): fprintf(sniff_data,"\tARP packet\n"); packet_type[ARP]++; return; case(0x8035): fprintf(sniff_data,"\tRARP packet\n"); packet_type[RARP]++; return; case(0x0800): fprintf(sniff_data,"\tIP packet\n"); packet_type[IP]++; break; default: fprintf(sniff_data,"\tnot an ARP/RARP/IP packet\n"); packet_type[UNKNOWN]++; break; } /* define/compute ip header offset */ size_header_ip = IP_HL(ip = (struct sniff_ip*)(packet + SIZE_ETHERNET))*4; if (size_header_ip < 20) 31 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort { packet_type[INV_IP_HEADER]++; packet_type[IP]--; fprintf(sniff_data,"\t Invalid IP header length: %u bytes\n", size_header_ip); return; } /* print source and destination IP addresses */ strcpy(mybuff,inet_ntoa(ip->ip_src)); fprintf(sniff_data,"\tFrom: %s To: %s\n", mybuff, inet_ntoa(ip->ip_dst)); /* determine protocol */ switch(ip->ip_p) { case IPPROTO_TCP: fprintf(sniff_data,"\t-TCP protocol\n"); info_type[TCP_NO_Modbus]++; break; case IPPROTO_UDP: fprintf(sniff_data,"\t-UDP protocol\n"); info_type[UDP]++; return; case IPPROTO_ICMP: fprintf(sniff_data,"\t-ICMP protocol\n"); info_type[ICMP]++; return; default: fprintf(sniff_data,"\t-Not a TCP/UDP/ICMP protocol\n"); info_type[UP_UNKNOWN]++; return; } /* define/compute tcp header offset */ tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_header_ip); size_header_tcp = TH_OFF(tcp)*4; if (size_header_tcp < 20) { fprintf(sniff_data,"\t-invalid TCP header\n"); return; } fprintf(sniff_data,"\t Src port: %d to Dst port: %d\n", ntohs(tcp->th_sport),ntohs(tcp->th_dport)); /* define/print Modbus header fields */ /* is it an IP packet carrying Modbus data ? */ if ( ( ntohs(ip->ip_len) - size_header_ip ) == size_header_tcp ) test_Modbus = 0; else test_Modbus = 1; Modbus_tcp = (struct sniff_Modbus_tcp*)(packet + SIZE_ETHERNET + size_header_ip + size_header_tcp); test_Modbus = test_Modbus && (Modbus_tcp->mtcp_prot == 0)&&(Modbus_tcp->mtcp_iden != 0)&&(Modbus_tcp->mtcp_len != 0 ); test_Modbus = test_Modbus && (Modbus_tcp->mtcp_iden < 256) && (Modbus_tcp->mtcp_func < 256 ); if ( test_Modbus ) { info_type[TCP_Modbus]++; fprintf(sniff_data," - Modbus: \n"); fprintf(sniff_data,"\t\t%s = %d \n","remaining bytes in this frame",ntohs(Modbus_tcp->mtcp_len) ); fprintf(sniff_data,"\t\t%s = %d \n","identifier",Modbus_tcp->mtcp_iden); fprintf(sniff_data,"\t\t%s = %d \n","function code",Modbus_tcp->mtcp_func); Modbus_flag = 1; } else { 32 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort fprintf(sniff_data,"\t\t%s \n"," ( not a Modbus_tcp protocol / or misformed Modbus_tcp packet )"); Modbus_flag = 0; } /* sending info to the linked tree list */ if (!Modbus_flag) { if ((eth_type == 0x0800)&&(ip->ip_p == IPPROTO_TCP)) { sportaux = ntohs(tcp->th_sport); dportaux = ntohs(tcp->th_dport); s = (struct ip_node_t *)insertBranch(s,(struct in_addr *)&ip->ip_src,(struct in_addr *)&ip->ip_dst, (u_short *)&sportaux,(u_short *)&dportaux); } } else { sportaux = ntohs(tcp->th_sport); dportaux = ntohs(tcp->th_dport); m_lenaux = ntohs(Modbus_tcp->mtcp_len); m_idenaux = Modbus_tcp->mtcp_iden; m_funcaux = Modbus_tcp->mtcp_func; r = (struct Modbus_node_t *)m_insertBranch(r,(struct in_addr *)&ip->ip_src,(struct in_addr *)&ip->ip_dst, (u_short *)&sportaux,(u_short *)&dportaux,(u_short *)&m_lenaux,(u_char *)&m_idenaux,(u_char *)&m_funcaux); } return; } void print_app_banner(char *v,int n) { char c = '0' ; int i ; char *snt_scrp[] = { "\n Making sure you have /var/log/Snort...\n", "./var_log_Snort.sh ", "\n Making sure you have the /opt/Snort/etc directory. \n", "./opt_Snort_etc.sh ", "\n Making sure directory /opt/Snort/rules exists. \n", "./opt_Snort_rules.sh ", " \n", "echo \"\n\"", NULL }; char *ord[] = { "more ./conf_Snort_files/important_considerations", "more ./conf_Snort_files/input", "more ./conf_Snort_files/output", NULL }; pantallazo(1); printf("Info banner: \n"); for(i = 0 ; ord[i] ; i++) { system(ord[i]); pantallazo(20); } printf("Checking the system...\n"); for( i = 0 ; snt_scrp[i] ; ) 33 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort { printf("%s",snt_scrp[i++]); system(snt_scrp[i++]); sleep(3); } pantallazo(4); if (n == 0) { printf("STARTING SNIFFING......"); sleep(1); printf(" %s\n"," -===============-"); printf(" -== %s ==- \n", APP_NAME); printf(" -== %s = %s ==-\n","interface",v); printf(" %s\n"," -===============-"); sleep(1); } else{ printf("STARTING SNIFFING......"); sleep(1); printf(" %s\n"," -===============-"); printf(" -== %s ==- \n", APP_NAME); printf(" -== %s = %s ==-\n","interface",v); printf(" -== %s = %d ==-\n","number of packets to study ", n ); printf(" %s\n"," -===============-"); sleep(1); } return; } void create_Statistics (struct tm *begin,struct tm *end,double td, int pkt,int f) { enum eth_type et_aux; /* aux through for-loops*/ enum upper_eth_type uet_aux; /* aux through for-loops*/ char *et_uet; int sum_et=0,sum_uet=0; float assess=0; fprintf(statistics,"\n -== %s %d/%d/%d at %d:%d:%d ==-\n","Beginning test on", begin->tm_mday,begin->tm_mon,begin->tm_year,begin->tm_hour, begin->tm_min,begin->tm_sec); fprintf(statistics," -=== %s ===- \n"," STATISTICS OF OUR NETWORK TRAFFIC "); fprintf(statistics,"\n\t%s \n\n"," -PROTOCOL SUPPORTED OVER ETHERNET- "); for(et_aux=ARP; et_aux<=INV_IP_HEADER; et_aux++) { switch(et_aux) { case(ARP): et_uet="ARP";break; case(RARP): et_uet="RARP";break; case(IP): et_uet="IP";break; case(UNKNOWN): et_uet="Unknown protocol";break; case(INV_IP_HEADER):et_uet="Invalid IP header";break; default: fprintf(statistics,"\t!!debug needed!!\n"); }; assess=(float)(packet_type[et_aux])/pkt; fprintf(statistics,"\t\t* %s = %d ---> %2.2f%c of our traffic\n", et_uet,packet_type[et_aux],assess*100,'%'); } fprintf(statistics,"\n\n"); fprintf(statistics,"\t%s \n\n"," -PROTOCOL SUPPORTED OVER IP- "); for(uet_aux=TCP_NO_Modbus ;uet_aux<=UP_UNKNOWN ;uet_aux++) 34 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) { aux2 = *(u_short *)aux_r->ptrdata; fprintf(ip_tree,"%5d: ",count++); fprintf(ip_tree,"Ip source: %15s, ",inet_ntoa(*in_addr_aux1)); fprintf(ip_tree,"Ip destination: %15s, ",inet_ntoa(*in_addr_aux2)); fprintf(ip_tree,"Port Source: %5d, ",aux1); fprintf(ip_tree,"Port destination: %5d \n",aux2); strcpy(mybuff,inet_ntoa(*in_addr_aux2)); fprintf(ip_tree_rules,"pass ip %s %d <> %s %d \n", inet_ntoa(*in_addr_aux1),aux1,mybuff,aux2); } } } } return; } //Modbus_node.h #ifndef Modbus_NODE_H_ #define Modbus_NODE_H_ struct Modbus_node_t { void *ptrdata; struct Modbus_node_t *ptr_r; struct Modbus_node_t *ptr_b; }; enum m_field_t { Modbus_ip_from = 0, Modbus_ip_to = 1, Modbus_src_port = 2, Modbus_dst_port = 3, Modbus_len = 4, Modbus_iden = 5, Modbus_func = 6 }; /* prototypes */ struct Modbus_node_t *m_createList (void); struct Modbus_node_t *m_createNode(void *); struct Modbus_node_t *m_insertBranch (struct Modbus_node_t *,void *,void *,void *,void *,void *,void *,void *); void m_freeTree_Modbus(struct Modbus_node_t *); void m_readTree_Modbus(struct Modbus_node_t *); #endif //Modbus_func.c #include "ip.h" #include "Modbus_node.h" extern FILE *Modbus_tree; extern FILE *Modbus_tree_rules; struct Modbus_node_t *m_createList (void) { return NULL; }; 41 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort struct Modbus_node_t *m_createNode(void *data) { struct Modbus_node_t *s; s = malloc(sizeof(struct Modbus_node_t)); if (s != NULL) { s->ptrdata = data; s->ptr_r = NULL; s->ptr_b = NULL; } return s; } struct Modbus_node_t *m_insertBranch (struct Modbus_node_t *s,void *ob1,void *ob2,void *ob3,void *ob4,void *ob5,void *ob6,void *ob7) { struct Modbus_node_t *aux,*aux1,*aux2,*aux3,*aux4,*aux5,*aux6,*prev,*prev1,*prev2,*prev3,*prev4,*prev5,*prev6; struct Modbus_node_t *aux_loop; void *ob; enum m_field_t level = Modbus_ip_from; int m_prev_int; for ( aux = s, prev = NULL ; aux != NULL ; prev = aux, aux = aux->ptr_r) { if(!memcmp(aux->ptrdata,ob1,sizeof(struct in_addr))) { level++; for( aux1 = aux->ptr_b, prev1 = NULL ; aux1 != NULL ; prev1 = aux1, aux1 = aux1->ptr_r) { if(!memcmp(aux1->ptrdata,ob2,sizeof(struct in_addr))) { level++; for( aux2 = aux1->ptr_b , prev2 = NULL ; aux2 != NULL ; prev2 = aux2, aux2 = aux2->ptr_r) { if(!memcmp(aux2->ptrdata,ob3,sizeof(u_short))) { level++; for( aux3 = aux2->ptr_b , prev3 = NULL ; aux3 != NULL ; prev3 =aux3, aux3 = aux3->ptr_r) { if(!memcmp(aux3->ptrdata,ob4,sizeof(u_short))) { level++; for( aux4 = aux3->ptr_b , prev4 = NULL ; aux4 != NULL ; prev4 =aux4, aux4 = aux4->ptr_r) { if(!memcmp(aux4->ptrdata,ob5,sizeof(u_short))) { level++; for( aux5 = aux4->ptr_b , prev5 = NULL ; aux5 != NULL ; prev5 =aux5, aux5 = aux5- >ptr_r) { if(!memcmp(aux5->ptrdata,ob6,sizeof(u_char))) { level++; for( aux6 = aux5->ptr_b , prev6 = NULL ; aux6 != NULL ; prev6 =aux6, aux6 = aux6->ptr_r) { if(!memcmp(aux6->ptrdata,ob7,sizeof(u_char))) { return s; } } } } } } } 42 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort } } } } } } } if (prev == NULL) m_prev_int = 0; else m_prev_int = 1; switch (m_prev_int) { case(0): ob = malloc(sizeof(struct in_addr)); //ip source s = m_createNode(memcpy(ob,ob1,sizeof(struct in_addr))); ob = malloc(sizeof(struct in_addr)); //ip destination s->ptr_b = m_createNode(memcpy(ob,ob2,sizeof(struct in_addr))); aux_loop = s->ptr_b; ob = malloc(sizeof(u_short)); //src port aux_loop->ptr_b = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); return s; default: switch(level) { case (Modbus_ip_from): ob = malloc(sizeof(struct in_addr)); //ip source prev->ptr_r = m_createNode(memcpy(ob,ob1,sizeof(struct in_addr))); aux_loop = prev->ptr_r; ob = malloc(sizeof(struct in_addr)); //ip destination aux_loop->ptr_b = m_createNode(memcpy(ob,ob2,sizeof(struct in_addr))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //src port aux_loop->ptr_b = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; 43 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort ob = malloc(sizeof(u_char)); //iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case (Modbus_ip_to): ob = malloc(sizeof(struct in_addr)); //ip destination prev1->ptr_r = m_createNode(memcpy(ob,ob2,sizeof(struct in_addr))); aux_loop = prev1->ptr_r; ob = malloc(sizeof(u_short)); //src port aux_loop->ptr_b = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); // iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case (Modbus_src_port): ob = malloc(sizeof(u_short)); //src port prev2->ptr_r = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_r; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); // iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case (Modbus_dst_port): ob = malloc(sizeof(u_short)); //dst port prev3->ptr_r = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_r; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); // iden Modbus 44 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case(Modbus_len): ob = malloc(sizeof(u_short)); //len Modbus prev4->ptr_r = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = prev4->ptr_r; ob = malloc(sizeof(u_char)); // iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case(Modbus_iden): ob = malloc(sizeof(u_char)); // iden Modbus prev5->ptr_r = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = prev5->ptr_r; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case(Modbus_func): ob = malloc(sizeof(u_char)); //func Modbus prev6->ptr_r = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; default: printf("DEBUG NEEDED \n"); exit(1); } } } void m_freeTree_Modbus(struct Modbus_node_t *s) { struct Modbus_node_t *aux_i,*aux_j,*aux_k,*aux_r,*aux_s,*aux_t,*aux_u; for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) for (aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) for (aux_t = aux_s->ptr_b ; aux_t != NULL ; aux_t = aux_t->ptr_r) for (aux_u = aux_t->ptr_b ; aux_u != NULL ; aux_u = aux_u->ptr_r) { free(aux_u->ptrdata); free(aux_u); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) 45 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort for (aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) for (aux_t = aux_s->ptr_b ; aux_t != NULL ; aux_t = aux_t->ptr_r) { free(aux_t->ptrdata); free(aux_t); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) for (aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) { free(aux_s->ptrdata); free(aux_s); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) { free(aux_r->ptrdata); free(aux_r); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) { free(aux_k->ptrdata); free(aux_k); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) { free(aux_j->ptrdata); free(aux_j); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) { free(aux_i->ptrdata); free(aux_i); } return; } void m_readTree_Modbus(struct Modbus_node_t *s) { struct Modbus_node_t *aux_i,*aux_j,*aux_k,*aux_r,*aux_s,*aux_t,*aux_u; int aux1,aux2,aux3; struct in_addr *in_addr_aux1, *in_addr_aux2; char aux_char1,aux_char2; int count=0; char mybuff[50]; /* inet_ functions use statically allocated memory */ for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) { in_addr_aux1 = (struct in_addr *)aux_i->ptrdata; for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) { 46 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort in_addr_aux2 = (struct in_addr *)aux_j->ptrdata; for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) { aux1 = *(u_short *)aux_k->ptrdata; for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) { aux2 = *(u_short *)aux_r->ptrdata; for(aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) { aux3 = *(u_short *)aux_s->ptrdata; for(aux_t = aux_s->ptr_b ; aux_t != NULL ; aux_t = aux_t->ptr_r) { aux_char1 = *(u_char *)aux_t->ptrdata; for(aux_u = aux_t->ptr_b ; aux_u != NULL ; aux_u = aux_u->ptr_r) { aux_char2 = *(u_char *)aux_u->ptrdata; fprintf(Modbus_tree,"%5d: ",count++); fprintf(Modbus_tree,"Ip src: %14s, ",inet_ntoa(*in_addr_aux1)); fprintf(Modbus_tree,"Ip dst: %14s, ",inet_ntoa(*in_addr_aux2)); fprintf(Modbus_tree,"Port src: %5d, ",aux1); fprintf(Modbus_tree,"Port dst: %5d, ",aux2); fprintf(Modbus_tree,"lenght_data: %5d, ",aux3); fprintf(Modbus_tree,"ident: %5d, ",(u_char)aux_char1); fprintf(Modbus_tree,"funct code: %5d \n",(u_char)aux_char2); strcpy(mybuff,inet_ntoa(*in_addr_aux2)); fprintf(Modbus_tree_rules,"pass ip %s %d <> %s %d (Modbus_func: %d ;Modbus_unit: %d;)\n", inet_ntoa(*in_addr_aux1),aux1,mybuff,aux2,(u_char)aux_char2, (u_char)aux_char1); } } } } } } } return; } // merge_ip.c #include "ip.h" void merge_ip(char *name_f) { FILE *origin_1; FILE *origin_2; FILE *copy_aux; char buff_1[200]; char buff_2[100]; char aux[100]; char pass[10],ip[5],s_add[20],s_port[10],sym[5],d_add[20],d_port[10]; fpos_t pos; char equal = 0; //opening files origin_1 = fopen(name_f,"r"); origin_2 = fopen(name_f,"r"); copy_aux = fopen("backup.txt","w"); while (!feof(origin_1)) { fgets(buff_1,sizeof(buff_1),origin_1); 47 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort fgetpos(origin_1,&pos); //pos points to the next line fscanf(origin_2,"%s %s %s %s %s %s %s",pass,ip,s_add,s_port,sym,d_add,d_port); if(!strcmp(pass,"alert")) break; fsetpos(origin_2,&pos); //origin_1 and origin_2 must point to the same position sprintf(buff_2,"%s %s %s %s %s %s %s",pass,ip,d_add,d_port,sym,s_add,s_port); while(strcmp(pass,"alert")) { fscanf(origin_1,"%s %s %s %s %s %s %s",pass,ip,s_add,s_port,sym,d_add,d_port); if( !strcmp(pass,"alert") ) break; sprintf(aux,"%s %s %s %s %s %s %s",pass,ip,s_add,s_port,sym,d_add,d_port); if(!strcmp(buff_2,aux)) { equal = 1; break; } } if ( !equal ) { fprintf(copy_aux,"%s\n",buff_2); }else equal = 0 ; fsetpos(origin_1,&pos); } fprintf(copy_aux,"%s\n",buff_1); //closing files fclose(origin_1); fclose(origin_2); fclose(copy_aux); rename("backup.txt",name_f); } #! /bin/sh # var_log_Snort.sh if [ -d /var/log/Snort ] then echo "\t\t... /var/log/Snort exists" else echo "\t\t... /var/log/Snort doesn't exists..." mkdir /var/log/Snort echo "\t\t\t\t...creating /var/log/Snort" fi #! /bin/sh # moving_conf_files.sh if [ -d ./conf_Snort_files ] then cp ./conf_Snort_files/classification.config /opt/Snort/etc/. cp ./conf_Snort_files/reference.config /opt/Snort/etc/. cp ./conf_Snort_files/Snort.conf ./rules/Snort.conf else echo " !! revise your sniffer folder, conf_Snort_files folder is missed !! " exit 1 fi #! /bin/sh # moving_rule_files.sh if [ -d ./info_docs ] then cp ./info_docs/*.rules ./rules/. cp ./conf_Snort_files/Snort.conf ./rules/Snort.conf chown $SUDO_USER ./rules/Snort.conf cd rules echo "\n" 48 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort for file in $(ls *.rules) do cp ./$file /opt/Snort/rules/$file echo "\t...$file moved into /opt/Snort/rules and included into Snort.conf" sleep 1 echo "include \$RULE_PATH/$file" >> ./Snort.conf done cp ./Snort.conf /opt/Snort/etc/. cd .. else echo "debug needed" exit 1 fi #! /bin/sh #opt_Snort_rules.sh if [ -d /opt/Snort/rules ] then echo "\t\t... /opt/Snort/rules exists" else echo "\t\t... /opt/Snort/rules doesn't exists ..." mkdir /opt/Snort/rules echo "\t\t\t...creating /opt/Snort/rules" fi #! /bin/sh # opt_Snort_etc.sh if [ -d /opt/Snort/etc ] then echo "\t\t... /opt/Snort/etc exists" else echo "\t\t... /opt/Snort/etc doesn't exists..." if [ -d /opt ] then cd /opt if [ -d /opt/Snort ] then mkdir /opt/Snort/etc else mkdir /opt/Snort mkdir /opt/Snort/etc fi else mkdir /opt mkdir /opt/Snort mkdir /opt/Snort/etc fi echo "\t\t\t...creating /opt/Snort/etc" fi 49 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort ANEXO B: English report Whitelisting Sniffer and Statistical Traffic Study for Snort (IDS) Arturo Ruiz Mañas Supervisors: Dr. Michael Schukat & Dr. Hugh Melvin OSNA Cyber Security Research Group http://www.osna-solutions.com/ 50 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Fig.22: Snort's inner workings schema …................................................................ 120 Fig.23: IDS behind the firewalls …......................................................................... 123 Fig.24: Likely scenario for a Snort sensor ….......................................................... 124 Fig.25: Our company's system administrator …..................................................... 126 Fig.26: General structure of a rule …...................................................................... 132 Fig.27: General structure of a rule's header …........................................................ 133 vii 57 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort List of Tables Table 1: Stack's layer in Modbus TCP …............................................................ 65 Table 2: Snort's modules summarize …............................................................... 123 Table 3: Flag's keywords …................................................................................. 140 Table 4: Type of ICMP packet …........................................................................ 141 Table 5: List of arguments ….............................................................................. 145 Table 6: Tag's arguments …................................................................................. 147 viii 58 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 1. INTRODUCTION 1.1 Introduction to Network Security Nowadays, we find ourselves absorbed in a world in which our communications and daily affairs pass through a large number of computer systems. Our emails, reach its destination not without previously go along the tangle of routers that conform Internet, at the moment you can “survive” without stepping in a supermarket, with just a computer, an Internet connection and after a little number of clicks you can order you weekly shopping; bank transactions, last books, clothes, social networks. All can be done, and is done, from your desk at work or in the comfort of your sofa at home. What about private companies? Personal details, industrial data or signal control, important documents... everything gets off from a computer, goes a long a cable in an intranet, and this intranet is very likely connected to the network of networks: Internet is here, and everybody should understand the important role that Network Security plays in all of this. Whether like it or not, we are already in the digital era in which everything is translated into 1's and 0's. This is why it is so important to protect the information over this new platform. Thus, I believe a good starting point for this thesis would be a definition of “network security”. What does network security refers to? According to wikipedia, network security consist on [1]: “Network security consists of the provisions and policies adopted by a network administrator to prevent and monitor unauthorized access, misuse, modification, or denial of a computer network and network-accessible resources.” Webopedia says [2]: “A specialised field in computer networking that involves securing a computer network infrastructure. Network security is typically handled by a network administrator or system administrator who implements the security policy, network software and hardware needed to protect a network and the resources accessed through the network from unauthorized access and also ensure that employees have adequate access to the network and resources to work.” One simpler definition would be the one in the digital magazine “Magazine Encyclopedia” [3]: “Protecting the computer systems in the network from unwanted intrusions.” In short, network security prevents from attacts and possible threats, protecting, computer systems that make possible the development of daily routines in Internet, from misuses. We could also 59 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort see it from the other side, and say as well that once we got hacked, network security controls and monitorizes these misuses against private networks in companies, personal businesses or your home. 1.2 Networks in Industrial Environment Let's try to make it familiar to us. Since we have never talked during our University years about Industrial Networking Protocols, the best thing to start with this topic, will be speaking about Industrial Ethernet; after all, everybody working in Telematics has come into touch with Ethernet. Industrial Ethernet refers to the use of Ethernet into industrial environments (connectors... switches...) for automation or process control. Components in these environments must work sometimes in extreme conditions of temperature, humidity or vibration; conditions, that on the other hand, exceed the ranges of usual information technology equipment [22]. This particular Ethernet reduces problems related to electrical noise and prevents from equipment damage. Although essentially both Ethernets share a common basis, there are some differences between them, for example: Industrial Ethernet uses deterministic delivery, whereas Ethernet uses collition detection. But I repeat that, essentially, they both share a common basis. Some other examples of Industrial Protocols are: Modbus and its variants, ZigBee, EtherCAT, DeviceNet... it exists a large list. To sum up, we should think of Industrial Protocols, as an adaptation of the Information Protocols to harsh environments. They help machines in situations very different to the ones we users have in our offices or homes, to develop their functionality. 60 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 2. LITERATURE REVIEW 2.1 Network Protocols “A network protocol defines rules and conventions for communication between network devices. Protocols for computer networking all generally use packet switching techniques to send and receive messages in the form of packets.” [26]. The list of Network Protocols can be huge, here we are going to make a little reference to some that we believe are important for this thesis: 2.1.1 IP Internet Protocol (IP), about this protocol, we can find big amounts of information in Internet, and with reason, since is the fundamental pillar on which Internet is sustained. Without this protocol we could not have interconnections further than our local network, it is because of this that the IP protocol represents such a fundamental intruduction into networking technologies, and resulted in the net of networks we all know nowadays. It's been so important that it has given its name to a whole protocols stack: TCP/IP. IP supports unique addressing for computers on a network, IP addresses (IPv4 and IPv6). There aren't two devices in this world, that could have the same IP address, we could compare it to the postal address of our homes. Data on the other hand, is organized into packets and all of them include both a header (with information about source and destination) and the payload with the info itself. The protocol IP, works in the 3rd layer of the OSI model. It can therefor run on top of different link layers interfaces: Ethernet, Wifi, Frame Relay, ATM … Fig.1 IP frame structure 61 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort We could speak much further about this protocol [SteRi01], and although we could fill many pages just talking about it, this is not the point of this thesis. Let's move on, and continue with another important protocol: TCP. 2.1.2 TCP Transmission Control Protocol (TCP) is one of the main protocols in the TCP/IP stack. TCP functions are about reliability, packet ordering, error-checking delivery of a stream of bytes between programs, that established a session between, running on computers connected to a network. This protocol refers to the transport layer of OSI model. Fig. 2 OSI model Some important concepts on TCP are: - TCP segment structure (TCP header) - session: data transfer. - connection diagrams: connection establishment and termination. - maximum segment size Many things could be said within TCP, and there is a lot of bibliography written about this protocol [SteRi01] and about its “unreliable” protocol partner UDP [SteRi02]. It is important to understand very well these two protocols if you want to work on networking and topics related to it. 62 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Fig.3 TCP header 2.1.3 Other IP Protocols There are other protocols included into the IP-TCP protocols stack and not only the ones named before and there are many other protocols that are gradually adapting their technology to be included inside an IP frame or an TCP segment. Just to see the IP-TCP protocols stack, we include the next figure. In it, we can differenciate between levels: application level would be the one on the top, later downward transport layer, network layer1 and link layer. Fig.4 OSI model / DARPA and TCP/IP Protocol Suite HTTP: HyperText Transfer Procotol used by the WWW (World Wide Web). Defines messages' format and how this messages are transmitted. It also defines how Web-servers and browsers should respond to commands. 1. The protocols ICMP and IGMP, although they are at the same high as UDP and TCP, they are not part of the transport level. They are encapsuled inside IP and that's why in the image they are drawn near the latter protocols. 63 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort FTP: File Transfer Protocol, built on a client-server protocol architecture, it is used to exchange files over the Internet. SMTP: Simple Mail Transfer Protocol, used for sending e-mails between servers. E-mails can be retrieved with an e-mail client. ARP: Address Resolution Protocol, a network layer protocol used to translate IP network addresses into link layer addresses (MAC addresses). UDP: a connectionless protocol associated to the transport layer in the OSI model, running on top of IP. Provides very few error recovery services, leaving this tasks normally for protocols that run on top of him. 2.1.4 Modbus As this is a completely new protocol for us in our Telecommunications Engineering education, we will delve a bit deeper into it than with the previous protocols, and since in this work, we are to deal with a solution for Industrial Control System Protocol networks (and more precisely with Modbus), a brief but good intruction to Modbus is required. Modbus is a simple and robust serial communications protocol originally published by Modicon for its use with its programmable logic controllers(PLCs). It has become an important standard communications protocol, and a commonly available way to connect electronic devices [ezTCP]. It renders possible communication between many devices, approximately 240, connected to the same network, a common example would be a system that measures temperature and humidity and communicates the results to a computer. Modbus is usally used to connect a supervisory computer with a remote terminal unit (RTU) in supervisory control and data acquisition (SCADA) systems [23][24] [25]. Fig.5 Setup example of a Modbus Network 64 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort There is software available in Internet in order to emulate set ups that work with Modbus devices, some devices are master some others slave. It's been developed as well an API Modbus that simplifies the process of creating more especific sofware and virtualization of a whole Modbus scenario. As a matter of fact, for this project, it was created a virtual network, using Virtualbox for this purpose. In this network, it was configured three virtual machines: a virtual machine representing the Modbus master and another machine for the Modbus slave, finally another machine plays the role of NIDS (Network Intrusion Detector System) sensor. There is an annexe at the end of this text explaining the process of virtualization and the Modbus software employed in it. To make things clearer, let's make a little reference to the terminology “master” and “slave”. Nowadays we know this as the server-client model. A master-device works as a client, who sends requests for the slave (server) to process them and produce answers or replies. If you know how the model server-client works, this master-slave terminology shouldn't be a problem [SteRi02]. There are several types of Modbus: Modbus RTU, Modbus ASCII, and Modbus TCP. Our solution works on TCP-Modbus. Encapsulation of Modbus inside a segment TCP it's been a great advantage to our design, since it makes easier to work with it in a much wider environment, and our design can be comfortably extendable to other protocols that are included into the IP-TCP model as application layer SDU, resulting very straightforward to add functionalities following the same procedure seen in our program code. Table 1 Stack's layer in Modbus TCP Fig.6 Modbus TCP/IP ADU 65 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Fig. 7 Modbus-TCP header 2.1.5 ZigBee Though it is not important for our thesis, learning a bit about ZigBee can help us to see clearer the idea of Industrial Network Protocols: ZigBee, is a specification for a suite of high level communication protocols using small, lowpower digital radios based on an IEEE 802 standard for personal area networks. Devices are often used in mesh network form to transmit data over longer distances, passing data through intermediate devices to reach more distant ones. This allows ZigBee networks to be formed ad-hoc, with no centralized control or high-power transmitter/receiver able to reach all of the devices. Any ZigBee device can be tasked with running the network. The list of uses its quite extensive, but some examples to consider are: - Home Entertainment and Control – Smart homes. - Wireless sensor networks - Industrial control - Embedded sensing - Medical data collection - Smoke and intruder warning - Building automation Fig.8 ZigBee specificiation's layers 66 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort will fire off an alert and log the packet. Let's go step by step: to illustrate the path followed by a packet, once it arrives to the computer's network interface, I'm including the next figure. Fig.9 Snort's inner workings As we see in this image, Snort uses a very well defined set of behaviors and for its purposes it uses several modules . Let's describe the inner workings of Snort: First, the packets arrive to the device's NIC and are decoded off the wire by the packet decoder, which will determine what protocol is in use for a given packet. Then, when using Snort as a NIDS, after the incoming packets are parsed by the packet decoders, data is sent through any preprocessor you may have enabled in your Snort.conf file. It continues through the detection engine which matches it against the rules in any ruleset enabled in your Snort.conf file. “Snort.conf”, being a configuration file, is a very important file to bear in mind then, as it is where we can configure Snort's behaviours. Afterwards, matches are sent to the alerting and logging components, to be passed through whatever plug-ins you have selected, alerting and logging the data as it has been configured to do. Some of this modules would need some further explanation as we do next: •The packet decoders Note: here alerts can be generated based on malformed protocol headers: - overly long packets - unusual or incorrect TCP options 73 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort - and other such behavior. •Preprocessors Plug-ins to Snort that allow you to parse incoming data in different ways useful for the alerting modules. Without preprocessors you will only look at each individual packet as it comes in over the wire, missing some modern attacks: - overwriting data in overlapping fragments. - deliberated IDS evasion techniques like putting part of a milicious application request in one packet and the rest in another packet. - and other similar practices. After the data is returned from the preprocessors, it is passed to the detection engine. •The detection engine It's the component of Snort that takes data from the packet decoder and preprocessors (if any enabled) and compares it against the rules in your Snort.conf. First, the detection engine will try to determine what rulesets it ought to be matching against for a given piece of data. It classifies this first by protocol: TCP, UDP, ICMP, or IP. For TCP or UDP this is source and destination port number. For ICMP: it's the ICMP type. For plain old IP packets ... •Rules and matching IMPORTANT: in general, “alert” rules will fire before “pass” rules. However, if you would rather have this behavior reversed, you can specify the -o option to Snort on the command line, making the order “pass”, “alert”, “log” instead. Since we intend to provide a whilisting feature to this detection tool, we must be careful what's the order in which Snort execute its actions otherwise we could be alerting that is intended to be allower. So, this is a very importan note to have in mind. Eventually, we can understand that the whole idea about Snort goes around files that describe network correct or wrong behavings. All Snort's modules described in this section carry out their functions having a common direction: work on the packets Snort picks from the net, and transform them in a way that alert and logging modules (next explained module) can perfectly alert and log about possible threats. If we could run a program that is able to come up with what is suppose to be acceptable, or with what is suppose to be allowable, we can automatize this powerful IDS tool and make system administrators' duties much easier. 74 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort •Alerting and Logging components After the rules have been matched against the data, we have the alerting and logging components. - The logging mechanism in Snort will archive the packets that triggered Snort rules. - While the alerting mechanism is used to notify the analyst that a rule has fired. –Pass rules will allow some behaviours, seen as acceptable-behaviours, if we have established correctly the order to be checked in the previous module. 2.4 Aim of Thesis / Motivation of the Project As we were speaking before, both security approaches, whitelisting and blacklisting, have their pros and cons separatelly, and this is why we intend to build up a solution in order to merge them into a single program and get the best from both perspectives. Hence, we propose a solution that we believe will be a very powerful tool in any system administrator's resources. During a study phase in which the user runs our program, the idea is to come up with all the possible sessions established among devices in a network, collecting its IP addresses and ports and collecting as well information about functions, identificators and lengths in Modbus packets. With this information, the application will generate file rules, being this file rules the basis for a whilelisting approach. Normally, networks in private companies, can consist in hundreds of devices, exchanging in just little time thousands of packets among them. For any system administrator, trying to register all these exchanges would represent a daunting task. In OSNA, we want to make this task much simpler for that workers, and come up with a complete study of these connections. What in a beginning can seem a very complex network, our program is designed to summarize in a file, all those sessions stablished between machines. For this, we have modified the “idea” of sniffer program, including on it some new features. A sniffer or packet analyzer is a computer program that can intercept and log traffic passing over a digital network. Ours, is able to create different files, some of them containing pass-rules, according to the network traffic it sees in the segment of the network it is connected to, for afterwards transmitting them to the Snort file system. Snort will use its own features to alert on any behaviour out of its blacklist rules file that has been set in its configuration file, and on the other hand, it will use the “pass rules” created by our 75 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort sniffer, allowing what is consider to be a “good-known” behavior. Merging then both security methods: black and white -listing. To understand the whole schema, we should get at least some smattering of Snort, and once then, we will see our design's idea a bit clearer. Since it is not our intention to speak too deeply about Snort in this thesis, an annexe talking about it has been included at the end of this text. But to get a general concept of it, we will continue into the next point with a little review on Snort. 76 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 3. DESIGN 3.1 Working Environment During this project I have been working in a Linux environment, using a Debian Linux distribution in its Xubuntu version. The programming language used is C and shell programming. The shell program used is the Bash Unix shell of the GNU project and the compiler it's been gcc - GNU project C and C++ compiler-. Steps in our work till the final result: The development of our sniffer has gone through several steps. From a simple sniffer able to sniff the packets in promiscuous mode and dump the information contained in the packet's header, to the final product in which it is able to implement all the functionality we had in mind, leaving it open to further plug-ins. Let's describe the different steps taken in our development process of our program. 3.2 PCAP Library An important concept to understand, and that I came to understand when faced this project is “what is an API?” API stands for Application Program Interface, is a protocol created to be used as an interface by software components in order to communicate among them. It's an important help for software developers allowing them to forget about particularities of the hardward they are working with. The bottom line is that once you use an API, everything can be used according to the Linux philosophy of “all is a file in Linux”. Is a library that have routines, data structures, object classes and variables that you can use into your programs. One example of it would be the PCAP (Packet CAPture) library [4] [5] [6]. Pcap (packet capture) consists of an API used for capturing network traffic, is the basis of any sniffer nowadays or Intrusion Detection Systems such as Snort. Unix-like systems implement pcap, in the libpcap library. During the section dedicated to our design's code, it is seen the statement #include <pcap/pcap.h> which “pcap.h” is the header file that allows us to use the functions, constants, macros... available in libpcap, inside our program. 77 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 3.3 How our program works with Snort The program has been designed to bring some help to Snort tasks. What firstable was a hard task for any system administrator, our program is thought to make things easier for our employees working in securiting our information systems. The idea is to take advantage from the workings of Snort, which is able to contrast the packets that arrive to the NIC (Network Interface Card) with some predefined patterns. If we could be able to come up with a representation of our segment network's behaviours and express it into a file, after moving this file into Snort's file system, we could count with a very powerful tool. Well then, the program designed during this period is able to create that file (among some other more files) with what is called “whitelist”, then takes responsibilities in checking if some important folders are within Snort's file system, and if they don't exist, our program creates them, for later on, moving the whitelists into this folders. It handles as well, some of the configuration issues within Snort. Snort bases its configuration on a configuration file called “Snort.conf”. In this files, you can find variables, defines and some other statements related to configuration of our Snort sensor. The sniffer here proposed, includes the defines statements into this file, for later moving this file into Snort folders, substituing the previous configuration file for this new one. A new one on the other hand, that is already fixed in order to indicate Snort where the rules' files are.1 3.4 Tree Linked List The Tree-Linked list is the meat and potatoes of our sniffer's intentions. At this point of the project we're not taking in to consideration if it's a Modbus packet or any other TCP packet, what we are going to focus on, is to rescue IP addresses source, IP addresses destination, TCP source ports and TCP destination ports of the packets sniffed. This point give us the starting point for further ploughing. The whole point of it, is to save all this relevant information about IPs and ports, to later elaborate (the program will) the rules that will be transmitted into Snort's file system. We should bear in mind, that it is very important to restrict the amount of data we are taking from the network. We don't 1. Rules must be contained in /opt/Snort/rules. The program creates this folder and places the blacklisting rule files and whitelisting rule files in here. 78 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort want to put unnecessary extra rules, or rules that refers to previous rules' especifications, because it will make Snort much slower. Thus, we are here dealing with a trade-off: max security versus accuracy and amount of rules. To take just the necessary info then, we will design functions that will load a modified linked lists with the combinations of IP addresses and ports of queries and replies, with repeating any. The reason to use linked lists and not arrays is because if we used arrays, we would not know how much space we should allocate for it, and since we are picking packets as they flow in the wire, we can't dynamically establish the length of an array, some times could be 1000 elements others 10000 should be necessary... We will introduce my TreeLinked list here: We will start simple. What is a linked list? A linked list is a nested list of structs linked by addresses. The struct used is as follow: struct linked_list_node { void ptr_data; struct linked_list_node *ptr; } An accurate visual representation would be: Fig.10 A single dimension linked list where 1000, 800, 712, 992 and 692 are the memory addresses of these structures containing the data and a pointer to the next structure. a1, a2, a3, a4 and a5 are the data itself. The type void allows to store any kind of data in it. These structures will be dynamically allocated, allowing users to keep big amounts of data, allowing the user to forget about stablishing sizes in arrays. But the linked list shower before is not what we have in mind, a one-dimensional linked list doesn't help us to cope with our intentions. We will develop a Tree-Linked list. At the moment, I repeat, 79 Space for data. Next node in the list. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort we are dealing just with IP header information, we haven't got yet to the point of dealing with Modbus protocol, and the “linked list of linked lists” is consisting just of information related to IP-TCP. The structure I'll be using for our purposes is this: struct ip_node_t { void *ptrdata; struct ip_node_t *ptr_r; struct ip_node_t *ptr_b; } What better way to see the idea than through an ilustration of our tree? The next figure will clarify the idea, and later we explain the fields in my structure: Fig.11 Part of a possible sample of a Tree-Linked list The data structure then is composed by: •void *ptrdata → is a pointer to data allocated dynamically by my code. •struct ip_node_t *ptr_r → pointer to the next node in the same level (horizontal arrows in the graph). •struct ip_node_t *ptr_b; → pointer to the node in the lower level (arrows pointing downwards). Let's explain the previous image: It could happen that the sniffer has picked up a packet with: IP source address: 207.102.1.5 IP destination address: 10.10.1.37 Port source address: 345 Port destination address: 80 80 Address to node's data. Next node in the same level's list. Next node into the downwards' list. 207.144.24.5 110.87.25.74 450 80 78.207.124.25 1240 21 80 1562 10.10.0.5 98.200.128.14 23 5051 1025 1110 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Later, in any moment, it picks up another one: IP source address: 207.102.1.5 IP destination address: 10.10.1.115 Port source address: 3295 Port destination address: 80 Another packet any time later: IP source address: 154.245.0.7 IP destination address: 10.10.1.37 Port source address: 1245 Port destination address: 21 Maybe after... IP source address: 207.102.1.5 IP destination address: 10.10.1.115 Port source address: 80 Port destination address: 3987 And this would continue till the moment it reaches the number of packets we have tell the sniffer to sniff in the command line of our terminal. 81 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 4. IMPLEMENTATION At this point we build the basis for the project, it consists just of a normal sniffer that picks the packets from the network in promiscuous mode. Promiscuous mode means that our NIC is able to pick not only the packets addressed to itself but packets addressed to any machine connected to that segment of the network. For this, the computer's NIC should be configurated, but normally Snort does it himself. To configure oneself the NIC in promiscuous mode we can do it through Linux terminal. arturo@arturo-laptop:~$ sudo su root@arturo-laptop:/home/arturo# ifconfig wlan0 down root@arturo-laptop:/home/arturo# iwconfig wlan0 mode monitor root@arturo-laptop:/home/arturo# iwconfig wlan0 wlan0 IEEE 802.11bgn Mode:Monitor Tx-Power=15 dBm Retry long limit:7 RTS thr:off Fragment thr:off Power Management:off To put back your NIC in managed mode (otherwise you'll not be able to use your browser): arturo@arturo-laptop:~$ sudo su root@arturo-laptop:/home/arturo# ifconfig wlan0 down root@arturo-laptop:/home/arturo# iwconfig wlan0 mode managed root@arturo-laptop:/home/arturo# ifconfig wlan0 up root@arturo-laptop:/home/arturo# iwconfig wlan0 wlan0 IEEE 802.11bgn ESSID:"UPC943203" Mode:Managed Frequency:2.437 GHz Access Point: 70:71:BC:00:83:01 Bit Rate=54 Mb/s Tx-Power=15 dBm Retry long limit:7 RTS thr:off Fragment thr:off Power Management:off Link Quality=50/70 Signal level=-60 dBm Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0 Tx excessive retries:0 Invalid misc:298 Missed beacon:0 Functionality: the packets' header information of any packet sniffed in our network segment, are dumped to the screen. Is it an IP packet? TCP over IP? Modbus over TCP-IP? Malformed IP packet? ARP? To illustrate this, next we have included a sample of the sniffed data during one of our tests: 82 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 4.2 Implementation in Modbus Right now we have a good understanding of how we can collect the info, keep it in dynamically allocated memory, and create files to store in a readable format both the info and the rules. It is time then to jump into the Modbus part. For this we have again two files: Modbus_node.h and Modbus_node.c. Modbus_node.h → header file for our Modbus linked list functions. #ifndef Modbus_NODE_H_ #define Modbus_NODE_H_ struct Modbus_node_t { void *ptrdata; struct Modbus_node_t *ptr_r; struct Modbus_node_t *ptr_b; } enum m_field_t { Modbus_ip_from = 0, Modbus_ip_to = 1, Modbus_src_port = 2, Modbus_dst_port = 3, Modbus_len = 4, Modbus_iden = 5, Modbus_func = 6 } /* prototypes */ struct Modbus_node_t *m_createList (void); struct Modbus_node_t *m_createNode(void *); struct Modbus_node_t *m_insertBranch (struct Modbus_node_t *,void *,void *,void *,void *,void *,void *,void *); void m_freeTree_Modbus(struct Modbus_node_t *); void m_readTree_Modbus(struct Modbus_node_t *); #endif And the Modbus_func.c → with all the functions we will use for the Modbus Tree-linked list: #include "ip.h" #include "Modbus_node.h" extern FILE *Modbus_tree; extern FILE *Modbus_tree_rules; struct Modbus_node_t *m_createList (void) { return NULL; }; 89 We have here a similar structure for the Tree-linked list node, but in this time it will reference modbus information. Now we have included three new types to the enumerated types: representing length of the data packet + 2, identification and function. Function to create the list's first node's address for modbus Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort struct Modbus_node_t *m_createNode(void *data) { struct Modbus_node_t *s; s = malloc(sizeof(struct Modbus_node_t)); if (s != NULL) { s->ptrdata = data; s->ptr_r = NULL; s->ptr_b = NULL; } return s; } struct Modbus_node_t *m_insertBranch (struct Modbus_node_t *s,void *ob1,void *ob2,void *ob3,void *ob4,void *ob5,void *ob6,void *ob7) { struct Modbus_node_t *aux,*aux1,*aux2,*aux3,*aux4,*aux5; struct Modbus_node_t *aux6,*prev,*prev1,*prev2,*prev3,*prev4,*prev5,*prev6; struct Modbus_node_t *aux_loop; void *ob; enum m_field_t level = Modbus_ip_from; int m_prev_int; for ( aux = s, prev = NULL ; aux != NULL ; prev = aux, aux = aux->ptr_r) { if(!memcmp(aux->ptrdata,ob1,sizeof(struct in_addr))) { level++; for( aux1 = aux->ptr_b, prev1 = NULL ; aux1 != NULL ; prev1 = aux1, aux1 = aux1->ptr_r) { if(!memcmp(aux1->ptrdata,ob2,sizeof(struct in_addr))) { level++; for( aux2 = aux1->ptr_b , prev2 = NULL ; aux2 != NULL ; prev2 = aux2, aux2 = aux2->ptr_r) { if(!memcmp(aux2->ptrdata,ob3,sizeof(u_short))) { level++; for( aux3 = aux2->ptr_b , prev3 = NULL ; aux3 != NULL ; prev3 =aux3, aux3 = aux3->ptr_r) { if(!memcmp(aux3->ptrdata,ob4,sizeof(u_short))) { level++; for( aux4 = aux3->ptr_b , prev4 = NULL ; aux4 != NULL ; prev4 =aux4, aux4= aux4->ptr_r) { if(!memcmp(aux4->ptrdata,ob5,sizeof(u_short))) { level++; for( aux5 = aux4->ptr_b , prev5 = NULL ; aux5 != NULL ; prev5 =aux5, aux5 = aux5->ptr_r) { if(!memcmp(aux5->ptrdata,ob6,sizeof(u_char))) { level++; for( aux6 = aux5->ptr_b , prev6 = NULL ; aux6 != NULL ; prev6 =aux6, aux6 = aux6->ptr_r) { if(!memcmp(aux6->ptrdata,ob7,sizeof(u_char))) 90 Function to create list's modbus nodes Same function as “insertBranch” in the ip parallel function. Here three more steps are included in order to take into account the three new info data fields: id, func, len. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort { return s; } } } } } } } } } } } } } } if (prev == NULL) m_prev_int = 0; else m_prev_int = 1; switch (m_prev_int) { case(0): ob = malloc(sizeof(struct in_addr)); //ip source s = m_createNode(memcpy(ob,ob1,sizeof(struct in_addr))); ob = malloc(sizeof(struct in_addr)); //ip destination s->ptr_b = m_createNode(memcpy(ob,ob2,sizeof(struct in_addr))); aux_loop = s->ptr_b; ob = malloc(sizeof(u_short)); //src port aux_loop->ptr_b = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); return s; default: switch(level) { case (Modbus_ip_from): ob = malloc(sizeof(struct in_addr)); //ip source prev->ptr_r = m_createNode(memcpy(ob,ob1,sizeof(struct in_addr))); aux_loop = prev->ptr_r; ob = malloc(sizeof(struct in_addr)); //ip destination aux_loop->ptr_b = m_createNode(memcpy(ob,ob2,sizeof(struct in_addr))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //src port 91 Here we include the three new fields for Modbus New enumerated type. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort aux_loop->ptr_b = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case (Modbus_ip_to): ob = malloc(sizeof(struct in_addr)); //ip destination prev1->ptr_r = m_createNode(memcpy(ob,ob2,sizeof(struct in_addr))); aux_loop = prev1->ptr_r; ob = malloc(sizeof(u_short)); //src port aux_loop->ptr_b = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); // iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case (Modbus_src_port): ob = malloc(sizeof(u_short)); //src port prev2->ptr_r = m_createNode(memcpy(ob,ob3,sizeof(u_short))); aux_loop = aux_loop->ptr_r; ob = malloc(sizeof(u_short)); //dst port aux_loop->ptr_b = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); // iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; 92 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort case (Modbus_dst_port): ob = malloc(sizeof(u_short)); //dst port prev3->ptr_r = m_createNode(memcpy(ob,ob4,sizeof(u_short))); aux_loop = aux_loop->ptr_r; ob = malloc(sizeof(u_short)); //len Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); // iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case(Modbus_len): ob = malloc(sizeof(u_short)); //len Modbus prev4->ptr_r = m_createNode(memcpy(ob,ob5,sizeof(u_short))); aux_loop = prev4->ptr_r; ob = malloc(sizeof(u_char)); // iden Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = aux_loop->ptr_b; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case(Modbus_iden): ob = malloc(sizeof(u_char)); // iden Modbus prev5->ptr_r = m_createNode(memcpy(ob,ob6,sizeof(u_char))); aux_loop = prev5->ptr_r; ob = malloc(sizeof(u_char)); //func Modbus aux_loop->ptr_b = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; case(Modbus_func): ob = malloc(sizeof(u_char)); //func Modbus prev6->ptr_r = m_createNode(memcpy(ob,ob7,sizeof(u_char))); return s; default: printf("DEBUG NEEDED \n"); exit(1); } } } void m_freeTree_Modbus(struct Modbus_node_t *s) { struct Modbus_node_t *aux_i,*aux_j,*aux_k,*aux_r,*aux_s,*aux_t,*aux_u; 93 Three new steps into this version of The function Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) for (aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) for (aux_t = aux_s->ptr_b ; aux_t != NULL ; aux_t = aux_t->ptr_r) for (aux_u = aux_t->ptr_b ; aux_u != NULL ; aux_u = aux_u->ptr_r) { free(aux_u->ptrdata); free(aux_u); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) for (aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) for (aux_t = aux_s->ptr_b ; aux_t != NULL ; aux_t = aux_t->ptr_r) { free(aux_t->ptrdata); free(aux_t); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) for (aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) { free(aux_s->ptrdata); free(aux_s); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) { free(aux_r->ptrdata); free(aux_r); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) { free(aux_k->ptrdata); free(aux_k); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) { free(aux_j->ptrdata); free(aux_j); } for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) { free(aux_i->ptrdata); free(aux_i); } 94 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort return; } void m_readTree_Modbus(struct Modbus_node_t *s) { struct Modbus_node_t *aux_i,*aux_j,*aux_k,*aux_r,*aux_s,*aux_t,*aux_u; int aux1,aux2,aux3; struct in_addr *in_addr_aux1, *in_addr_aux2; char aux_char1,aux_char2; int count=0; char mybuff[50]; /* inet_ functions use statically allocated memory */ for( aux_i = s ; aux_i != NULL ; aux_i = aux_i->ptr_r) { in_addr_aux1 = (struct in_addr *)aux_i->ptrdata; for( aux_j = aux_i->ptr_b ; aux_j != NULL ; aux_j = aux_j->ptr_r) { in_addr_aux2 = (struct in_addr *)aux_j->ptrdata; for (aux_k = aux_j->ptr_b ; aux_k != NULL ; aux_k = aux_k->ptr_r) { aux1 = *(u_short *)aux_k->ptrdata; for (aux_r = aux_k->ptr_b ; aux_r != NULL ; aux_r = aux_r->ptr_r) { aux2 = *(u_short *)aux_r->ptrdata; for(aux_s = aux_r->ptr_b ; aux_s != NULL ; aux_s = aux_s->ptr_r) { aux3 = *(u_short *)aux_s->ptrdata; for(aux_t = aux_s->ptr_b ; aux_t != NULL ; aux_t = aux_t->ptr_r) { aux_char1 = *(u_char *)aux_t->ptrdata; for(aux_u = aux_t->ptr_b ; aux_u != NULL ; aux_u = aux_u->ptr_r) { aux_char2 = *(u_char *)aux_u->ptrdata; fprintf(Modbus_tree,"%5d: ",count++); fprintf(Modbus_tree,"Ip src: %14s, ",inet_ntoa(*in_addr_aux1)); fprintf(Modbus_tree,"Ip dst: %14s, ",inet_ntoa(*in_addr_aux2)); fprintf(Modbus_tree,"Port src: %5d, ",aux1); fprintf(Modbus_tree,"Port dst: %5d, ",aux2); fprintf(Modbus_tree,"lenght_data: %5d, ",aux3); fprintf(Modbus_tree,"ident: %5d, ",(u_char)aux_char1); fprintf(Modbus_tree,"funct code: %5d \n",(u_char)aux_char2); strcpy(mybuff,inet_ntoa(*in_addr_aux2)); fprintf(Modbus_tree_rules,"pass ip %s %d <> %s %d (Modbus_func: %d ;Modbus_unit: %d;)\n", inet_ntoa(*in_addr_aux1),aux1,mybuff,aux2, (u_char)aux_char2,(u_char)aux_char1); } } } } } } } return; } Walking through this part of the code, we can see the similarities between the functions for IP and for Modbus, actually Modbus' functions are just an extension including the three more fields to study in this protocol, but the algorithm in whiche they are based is exactly the same. 95 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 4.3 Scripts shell The operative system we have been working in during this project as stated before is Linux, to be more precise it is a Debian in its Xubuntu version. Including shell scripts and using them in the code of our sniffer it's been relatively easy thanks to the system call “system()”. The shell program is one of the possitive aspects of working in Linux and it has brought useful and good results. System( ) 's man page : “man system” in our shell program. NAME system - execute a shell command SYNOPSIS #include <stdlib.h> int system(const char *command); DESCRIPTION system() executes the command specified in command by calling “ /bin/sh -c command ”, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored. We wanted to make automatic the inclusion of the rule files created by our program into Snort's file system, and add the possibility for our users to include, through our program as well, other blacklisting rule files into Snort's workings. For this, and considering that Snort has been installed through a process of “configure && install” from a source code, our sniffer will detect if the proper folders exists in Snort's file system and will copy the rules files inside. At the same time, it will add automatically the corresponding “include” states in Snort configuration file allowing the system administrator to forget about his issues. This scripts are: #! /bin/sh if [ -d ./conf_Snort_files ] then cp ./conf_Snort_files/classification.config /opt/Snort/etc/. cp ./conf_Snort_files/reference.config /opt/Snort/etc/. cp ./conf_Snort_files/Snort.conf ./rules/Snort.conf else echo " !! revise your sniffer folder, conf_Snort_files folder is missed !! " exit 1 fi #! /bin/sh if [ -d ./info_docs ] then cp ./info_docs/*.rules ./rules/. 96 Folder “conf_snort_files” inside our program's structure. It contains configuration files for Snort and some other files related to information about how to use our sniffer. If this info_docs exists then it carries out the commands listed here, if not, there's some missed stuff and you should revise the contents of your programm Once the program has finished, folder “info_docs” should have been created, containing info texts and rules files created by it. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort cp ./conf_Snort_files/Snort.conf ./rules/Snort.conf chown $SUDO_USER ./rules/Snort.conf cd rules echo "\n" for file in $(ls *.rules) do cp ./$file /opt/Snort/rules/$file echo "\t...$file moved into /opt/Snort/rules and included into Snort.conf" sleep 1 echo "include \$RULE_PATH/$file" >> ./Snort.conf done cp ./Snort.conf /opt/Snort/etc/. cd .. else echo "debug needed" exit 1 fi #! /bin/sh if [ -d /opt/Snort/etc ] then echo "\t\t... /opt/Snort/etc exists" else echo "\t\t... /opt/Snort/etc doesn't exists..." if [ -d /opt ] then cd /opt if [ -d /opt/Snort ] then mkdir /opt/Snort/etc else mkdir /opt/Snort mkdir /opt/Snort/etc fi else mkdir /opt mkdir /opt/Snort mkdir /opt/Snort/etc fi echo "\t\t\t...creating /opt/Snort/etc" fi #! /bin/sh if [ -d /opt/Snort/rules ] then echo "\t\t... /opt/Snort/rules exists" else echo "\t\t... /opt/Snort/rules doesn't exists ..." mkdir /opt/Snort/rules echo "\t\t\t...creating /opt/Snort/rules" fi #! /bin/sh 97 Folder “rules” is a folder created to keep the rules generated by our sniffer and some other blacklisting rules add by the user. This for-loop is an interesting feature: It goes along all the files in “rules” folder copying them into the right place into Snort file system and including an “include” statement into snort.conf configuration file. The next three scripts are run at the beginning of the main code of our sniffer, they will check for the existence of: - /opt/snort/etc - /opt/snort/rules - /var/log/snort This are important folders into Snort's file system, and they will house the files related to configuration, rules and logs. This is why is so important to check if they exists and if they don't, this scripts will create them. Actually, the previous scripts copy their files into these folders. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort if [ -d /var/log/Snort ] then echo "\t\t... /var/log/Snort exists" else echo "\t\t... /var/log/Snort doesn't exists..." mkdir /var/log/Snort echo "\t\t\t\t...creating /var/log/Snort" fi 4.4 Putting it all together: Main Code and Callback Function First we show the header file: ip.h #ifndef _IP_H_ #define _IP_H_ #include <time.h> #include <sys/types.h> #include <pcap/pcap.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #define BUFSIZE 2048 #define APP_NAME "ip.out" #define SIZE_ETHERNET 14 #define ETHER_ADDR_LEN 6 enum eth_type { ARP=0, RARP=1, IP=2, UNKNOWN=3, INV_IP_HEADER=4 }; enum upper_eth_type { TCP_NO_Modbus=0, TCP_Modbus=1, ICMP=2, UDP=3, UP_UNKNOWN=4, }; /* data structures for IP */ #define ETHER_ADDR_LEN 6 /* Ethernet header */ struct sniff_ethernet { u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */ u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */ u_short ether_type; /* IP? ARP? RARP? etc */ }; 98 Includes with all header files needed. Constants. Enumeration data type for protocols over the link layer. Enumeration data type for protocols over IP. Data structure for Ethernet, this sniffer is designed to work over Ethernet. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort /* sending info to the linked tree list */ if (!Modbus_flag) { if ((eth_type == 0x0800)&&(ip->ip_p == IPPROTO_TCP)) { sportaux = ntohs(tcp->th_sport); dportaux = ntohs(tcp->th_dport); s = (struct ip_node_t *)insertBranch(s,(struct in_addr *)&ip->ip_src, (struct in_addr *)&ip->ip_dst, (u_short *)&sportaux,(u_short *)&dportaux); } } else { sportaux = ntohs(tcp->th_sport); dportaux = ntohs(tcp->th_dport); m_lenaux = ntohs(Modbus_tcp->mtcp_len); m_idenaux = Modbus_tcp->mtcp_iden; m_funcaux = Modbus_tcp->mtcp_func; r = (struct Modbus_node_t *)m_insertBranch(r,(struct in_addr *)&ip->ip_src, (struct in_addr *)&ip->ip_dst, (u_short *)&sportaux,(u_short *)&dportaux, (u_short *)&m_lenaux,(u_char *)&m_idenaux,(u_char *)&m_funcaux); } return; } void print_app_banner(char *v,int n) { char c = '0' ; int i ; char *snt_scrp[] = { "\n Making sure you have /var/log/Snort...\n", "./var_log_Snort.sh ", "\n Making sure you have the /opt/Snort/etc directory. \n", "./opt_Snort_etc.sh ", "\n Making sure directory /opt/Snort/rules exists. \n", "./opt_Snort_rules.sh ", " \n", "echo \"\n\"", NULL }; char *ord[] = { "more ./conf_Snort_files/important_considerations", "more ./conf_Snort_files/input", "more ./conf_Snort_files/output", NULL }; pantallazo(1); printf("Info banner: \n"); for(i = 0 ; ord[i] ; i++) { system(ord[i]); pantallazo(20); } printf("Checking the system...\n"); for( i = 0 ; snt_scrp[i] ; ) { printf("%s",snt_scrp[i++]); system(snt_scrp[i++]); sleep(3); } 105 In case of Modbus, we call the modbus Tree-linked list functions. At this point we have an IP packet carrying a simple TCP protocol that doesn't wrap inside any Modbus data. Secondary function that is used to display a banner at the beginning of our program when run. Use of “system” system call. Using the scripts shell. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort pantallazo(4); if (n == 0) { printf("STARTING SNIFFING......"); sleep(1); printf(" %s\n"," -===============-"); printf(" -== %s ==- \n", APP_NAME); printf(" -== %s = %s ==-\n","interface",v); printf(" %s\n"," -===============-"); sleep(1); } else{ printf("STARTING SNIFFING......"); sleep(1); printf(" %s\n"," -===============-"); printf(" -== %s ==- \n", APP_NAME); printf(" -== %s = %s ==-\n","interface",v); printf(" -== %s = %d ==-\n","number of packets to study ", n ); printf(" %s\n"," -===============-"); sleep(1); } return; } void create_Statistics (struct tm *begin,struct tm *end,double td, int pkt,int f) { enum eth_type et_aux; /* aux through for-loops*/ enum upper_eth_type uet_aux; /* aux through for-loops*/ char *et_uet; int sum_et=0,sum_uet=0; float assess=0; fprintf(statistics,"\n -== %s %d/%d/%d at %d:%d:%d ==-\n","Beginning test on", begin->tm_mday,begin->tm_mon,begin->tm_year,begin->tm_hour, begin->tm_min,begin->tm_sec); fprintf(statistics," -=== %s ===- \n"," STATISTICS OF OUR NETWORK TRAFFIC "); fprintf(statistics,"\n\t%s \n\n"," -PROTOCOL SUPPORTED OVER ETHERNET- "); for(et_aux=ARP; et_aux<=INV_IP_HEADER; et_aux++) { switch(et_aux) { case(ARP): et_uet="ARP";break; case(RARP): et_uet="RARP";break; case(IP): et_uet="IP";break; case(UNKNOWN): et_uet="Unknown protocol";break; case(INV_IP_HEADER):et_uet="Invalid IP header";break; default: fprintf(statistics,"\t!!debug needed!!\n"); }; assess=(float)(packet_type[et_aux])/pkt; fprintf(statistics,"\t\t* %s = %d ---> %2.2f%c of our traffic\n", et_uet,packet_type[et_aux],assess*100,'%'); } fprintf(statistics,"\n\n"); fprintf(statistics,"\t%s \n\n"," -PROTOCOL SUPPORTED OVER IP- "); for(uet_aux=TCP_NO_Modbus ;uet_aux<=UP_UNKNOWN ;uet_aux++) { switch(uet_aux) { case(TCP_NO_Modbus): et_uet="TCP";break; 106 This function creates: - Time statistics. - Packet number statistics. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort case(UDP): et_uet="UDP";break; case(ICMP): et_uet="ICMP";break; case(TCP_Modbus): et_uet="\t* of which TCP_Modbus";break; case(UP_UNKNOWN): et_uet="Unknown protocol over IP";break; default: fprintf(statistics,"\t!!debug needed!!\n"); } assess=(float)(info_type[uet_aux])/pkt; fprintf(statistics,"\t\t* %s = %d ---> %2.2f%c of our traffic\n", et_uet,info_type[uet_aux],assess*100,'%'); } /* when data dumped from a file, there's no sense in time statistics, the file takes 0 secs for the program to be examined, resulting in divisions by 0 in our next piece of code*/ if ( f ) { fprintf(statistics,"\n\n\t...when studying from a pcap file there's no TIME STATISTICS\n\n"); return; } fprintf(statistics,"\n%s %f %s\n\n"," -== TIME STATISTICS : the tests has taken ",td," segs. ==-"); fprintf(statistics,"\t%s \n"," -PROTOCOL SUPPORTED OVER ETHERNET- "); for(et_aux=ARP; et_aux<=INV_IP_HEADER; et_aux++) { switch(et_aux) { case(ARP): et_uet="ARP";break; case(RARP): et_uet="RARP";break; case(IP): et_uet="IP";break; case(UNKNOWN): et_uet="Unknown protocol";break; case(INV_IP_HEADER):et_uet="Invalid IP header";break; default: fprintf(statistics,"\t!!debug needed!!\n"); } fprintf(statistics,"\t\t* %s has %2.3lf packets/sec.\n",et_uet,(double)(packet_type[et_aux])/(int)td); } fprintf(statistics,"\n\n"); fprintf(statistics,"\t%s \n"," -PROTOCOL SUPPORTED OVER IP- "); for(uet_aux=TCP_NO_Modbus ;uet_aux<=UP_UNKNOWN ;uet_aux++) { switch(uet_aux) { case(TCP_NO_Modbus): et_uet="TCP";break; case(UDP): et_uet="UDP";break; case(ICMP): et_uet="ICMP";break; case(TCP_Modbus): et_uet="\t* of which TCP_Modbus";break; case(UP_UNKNOWN): et_uet="Unknown protocol over IP";break; default: fprintf(statistics,"\t!!debug needed!!\n"); } fprintf(statistics,"\t\t* %s has %2.3lf packets/sec.\n",et_uet,(double)(info_type[uet_aux])/(int)td); } fprintf(statistics,"\n -== %s %02d/%02d/%d at %02d:%02d:%02d ==-\n\n -== %s %02d/%02d/%d at %02d:%02d: %02d ==-\n", "Test start:",begin->tm_mday,begin->tm_mon,begin->tm_year, begin->tm_hour,begin->tm_min, begin->tm_sec,"Test finish:",end->tm_mday,end->tm_mon,end->tm_year,end->tm_hour,end->tm_min, end->tm_sec); fprintf(statistics,"\t -=== %s ===- \n"," ------ END OF OUR STATISTICS FILE ------- "); return; } 107 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort void tail_banner(void) { char c = '0'; int i ; char *sentences[] = { "Files created: \n", "\t - sniff_data.txt :\t holds the sniffer's output\n", "\t - statistics.txt :\t holds statistical information\n", "\t - ip_tree.txt :\t holds all the combinations of ip @ and ports observed into our network traffic\n", "\t - Modbus_tree.txt :\t holds all the combinations of ip @, ports and Modbus fiels observed into our network traffic\n", "\t - ip_tree.rules :\t holds the ip rules to whitesniff our network, placed in ' /opt/Snort/rules ' \n", "\t - Modbus_tree.rules :\t holds the Modbus rules to whitesniff our network, placed in ' /opt/Snort/rules ' \n", NULL }; char *orders[] = { "mkdir info_docs","\nCreating folder info_docs...\n", "mv ./ip_tree.txt ./info_docs/.","\t...Moving ip_tree.txt into folder info_docs\n", "mv ./Modbus_tree.txt ./info_docs/.","\t...Moving Modbus_tree.txt into folder info_docs\n", "mv ./statistics.txt ./info_docs/.","\t...Moving statistics.txt into folder info_docs\n", "mv ./sniff_data.txt ./info_docs/.","\t...Moving sniff_data.txt into folder info_docs\n", "mv ./ip_tree.rules ./info_docs/.","\t...Moving ip_tree.rules into info_docs\n", "mv ./Modbus_tree.rules ./info_docs/.","\t...Moving Modbus_tree.rules into info_docs\n\n", "./moving_conf_files.sh","... moving 'classification.config' and 'reference.config' into /opt/Snort/etc\n", NULL }; char *more_sentences[] = { "\n\n\nPay attention: in this same directory, there's a folder named 'rules',\n", "you should load this directory with the black-listing rules you want for Snort. \n", "This program will include automatically the names into Snort.conf, releasing you from this task.\n", "Include now, if you need, some .rules files or PRESS LETTER c(lower case) + ENTER (case sensitive) to continue: ", NULL }; char *last_sentences[] = { "\n\nNow you can go to info_docs folder contained in this same directory, and consult the data gathered.\n", "...The appropiate rule file has been created and located in /opt/Snort/rules as well.\n\n\n\n", NULL }; pantallazo(5); system("rm -r ./info_docs 2> /dev/null"); for (i = 0 ; sentences[i] ; i++) { printf("%s",sentences[i]); sleep(1); } for(i = 0; orders[i] ; ) { if(system(orders[i++]) != -1 ) printf("%s",orders[i++]); sleep(2); } for ( i = 0; more_sentences[i] ; i++ ) { printf("%s",more_sentences[i]); sleep(2); } 108 When the program has kept all the important information into the Tree lists, now it's moment to sort out all the different files into the program's file system and specially in Snort's file system. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort fflush(stdin); for ( ; c != 'c' ; ) { scanf("%c",&c); if( c != 'c' ) printf("\nPRESS LETTER C (case sensitive) + ENTER to continue: "); fflush(stdin); } if(system("./moving_rule_files.sh") != -1) { printf("\n\t...Copying our whilelist compliant rules into /opt/Snort/rules\n"); sleep(1); printf("\t...Moving black-list compliant rules from our folder 'rules'into /opt/Snort/rules\n"); printf("\t...Moving Snort.conf configuration file with our 'includes' into /opt/Snort/etc \n"); } sleep(2); for ( i = 0; last_sentences[i] ; i++ ) { printf("%s",last_sentences[i]); sleep(2); } return; } void pantallazo (int j) { sleep (j); system("clear"); return; } 109 Clears the screen to keep writing information to the user. Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort 5. DEPLOYMENT AND TEST Our program's file system is composed by 2 directories and 31 files . From this 31 files, 4 are pcap files that are useful to test the functionality of the whitelisting-sniffer. . ├── 0.compiling.sh ├── 1.remove.sh ├── conf_Snort_files │ ├── classification.config │ ├── important_considerations │ ├── input │ ├── output │ ├── reference.config │ └── Snort.conf ├── DOC_README.odt ├── DOC_README.pdf ├── FC1-permit.pcap ├── Modbus_FC_1_Coil.pcap ├── http.cap ├── Modbus.pcap ├── ip.c ├── ip_func.c ├── ip.h ├── ip_node.h ├── merge_ip.c ├── Modbus_func.c ├── Modbus_node.h ├── rules │ ├── backdoor.rules │ ├── community-virus.rules │ ├── dos.rules │ ├── ftp.rules │ └── icmp.rules ├── moving_conf_files.sh ├── moving_rule_files.sh ├── opt_Snort_etc.sh ├── opt_Snort_rules.sh └── var_log_Snort.sh Explanation of the different files: •0.compiling.sh : script shell to compile the program. The program must be compiled previous use. •1.remove.sh : script shell that remove not needed files in the program's file system. It's positive to use it before to compile the program but not after it. It would erase the 110 Folder conf_snort_files Folder: rules Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort executable files and you would have to compile back. •Folder “conf_Snort_files ” : it contains important configuration program files. The most important among them is “Snort.conf”. Over this file, our sniffer with write the “include” statements, and after that, it will move this file into Snort's file system, overwriting the previous existing Snort.conf in there. •DOC_README.odt && DOC_README.pdf : contain information about the whitelisting-sniffer. •Next “.pcap” files: FC1-permit.pcap , Modbus_FC_1_Coil.pcap, http.cap, Modbus.pcap are files downloaded from Internet in order to test the correct function of the program. •ip.c , ip_func.c, ip.h, ip_node.h, merge_ip.c, Modbus_func.c, Modbus_node.h have already been explained along this text in previous points. •Folder “rules” : it conforms an important feature to our whitelisting program. During its execution, at the end of it, there's a moment in which the program informs you that rule files created are going to be moved into Snort's file system, advicing you and giving time to include inside this folder some other blacklisting file rules that the user could consider to be useful for Snort to use. •moving_conf_files.sh , moving_rule_files.sh, opt_Snort_etc.sh , opt_Snort_rules.sh, var_log_Snort.sh have also already been explained. They interact with Snort's file system contributing to a more automatic use of this program with Snort. Let's go through an example of execution: 1. Let's lists the contents of our folder: arturo@arturo-laptop:~/....../pcap/9. sniffer_ip_Modbus$ ls -l total 272 -rwxr--r-x 1 arturo arturo 289 May 6 13:39 0.compiling.sh -rwxr--r-x 1 arturo arturo 284 May 3 16:03 1.remove.sh drwxrwxr-x 2 arturo arturo 4096 May 6 13:10 conf_Snort_files -rw-rw-r-- 1 arturo arturo 20850 May 6 13:28 DOC_README.odt -rw-rw-r-- 1 arturo arturo 29415 May 6 13:29 DOC_README.pdf -rw-rw-r-- 1 arturo arturo 3138 May 2 18:48 FC1-permit.pcap -rw-r--r-- 1 arturo arturo 25803 May 2 13:37 http.cap -rw-r--r-- 1 arturo arturo 17864 May 6 13:15 ip.c -rw-r--r-- 1 arturo arturo 5846 May 11 16:28 ip_func.c -rw-rw-r-- 1 arturo arturo 4204 May 14 20:25 ip_func.o -rw-r--r-- 1 arturo arturo 2561 May 6 13:02 ip.h -rw-r--r-- 1 arturo arturo 481 May 1 19:11 ip_node.h -rw-rw-r-- 1 arturo arturo 17572 May 14 20:25 ip.o -rw-r--r-- 1 arturo arturo 1340 May 3 15:33 merge_ip.c -rw-rw-r-- 1 arturo arturo 2464 May 14 20:25 merge_ip.o -rw-rw-r-- 1 arturo arturo 4670 May 2 18:08 Modbus_FC_1_Coil.pcap -rw-r--r-- 1 arturo arturo 11957 May 11 16:35 Modbus_func.c -rw-rw-r-- 1 arturo arturo 6976 May 14 20:25 Modbus_func.o -rw-r--r-- 1 arturo arturo 633 Apr 30 15:11 Modbus_node.h -rw-rw-r-- 1 arturo arturo 8337 May 2 16:24 Modbus.pcap -rwxr--r-x 1 arturo arturo 322 Apr 30 18:28 moving_conf_files.sh -rwxr--r-x 1 arturo arturo 501 May 3 15:47 moving_rule_files.sh -rwxr--r-x 1 arturo arturo 433 May 11 21:48 opt_Snort_etc.sh 111 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort -rwxr--r-x 1 arturo arturo 211 May 11 21:48 opt_Snort_rules.sh drwxrwxr-x 2 arturo arturo 4096 May 13 23:00 rules -rwxrwxr-x 1 arturo arturo 29950 May 14 20:25 sniffer -rwxr--r-x 1 arturo arturo 208 May 3 16:06 var_log_Snort.sh 2. Use of the removing script shell: arturo@arturo-laptop:~/....../pcap/9. sniffer_ip_Modbus$ ./1.remove.sh ...remove.sh done 3. Compilation process: arturo@arturo-laptop:~/....../pcap/9. sniffer_ip_Modbus$ sudo su [sudo] password for arturo: root@arturo-laptop:/home/arturo/...../pcap/9. sniffer_ip_Modbus# ./0.compiling.sh ...compilation process done ...usage: ./sniffer -i <interface> -n <number of packets> ...usage: ./sniffer -f <file_name> 4. Execution of “sniffer” in the form of ./sniffer -f <file_name> root@arturo-laptop:/home/arturo/..../pcap/9. sniffer_ip_Modbus# ./sniffer -f Modbus_FC_1_Coil.pcap Modbus_FC_1_Coil.pcap is a pcap file downloaded from Internet that contains precollected information from a sniffing session. 5.1 Different Screens in the Execution Process Fig. 14 Brief note about Snort's intallation 112 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Fig. 15 Contents of the program's file system Fig.16 Files resulting from the execution of the sniffer 113 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Fig.17 Checking / creating folders in Snort's file system Fig.18 Sniffing process (no results dumped directly into screen) 114 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort example: • “scripts/./iisadmin” • “scripts/examples/../iisadmin” • “scripts\iisadmin” • “scripts/.\iisadmin” To complicate the situation, hackers can also insert in the web Uniform Resource Identifier (URI) hexadecimal characters or Unicode characters which are perfectly legal as far as the web server is concerned. Note that the web servers usually understand all of these strings and are able to preprocess them to extract the intended string “scripts/ iisadmin”. However if the IDS is looking for an exact match, it is not able to detect this attack. A preprocessor can rearrange the string so that it is detectable by the IDS. Preprocessors are also used for packet defragmentation. Receiving systems are capable of reassembling these smaller units again to form the original data packet. On IDS, before you can apply any rules or try to find a signature, you have to reassemble the packet. For example, half of the signature may be present in one segment and the other half in another segment. To detect the signature correctly you have to combine all packet segments. Hackers use fragmentation to defeat Intrusion Detection Systems. The preprocessors are used to safeguard against these attacks. Preprocessors in Snort can defragment packets, decode HTTP URI, re-assemble TCP streams and so on. These functions are a very important part of the Intrusion Detection System. The Detection Engine : is the most important part of Snort. Its responsibility is to detect if any intrusion activity exists in a packet. The detection engine employs Snort rules for this purpose. The rules are read into internal data structures or chains where they are matched against all packets. If a packet matches any rule, appropriate action is taken; otherwise the packet is dropped. Appropriate actions may be logging the packet or generating alerts. 121 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort This is the time-critical part of Snort. Depending upon some factors, it may take different amounts of time to respond to different packets or you may even drop some packets and may not get a true real-time response: • Number of rules • Power of the machine on which Snort is running • Speed of internal bus used in the Snort machine • Load on the network The detection system can dissect a packet and apply rules on different parts of the packet. These parts may be: • The IP header of the packet. • The Transport layer header. (TCP, UDP) or other transport layer headers. It may also work on the ICMP header. • The application layer level header. Application layer headers include, but are not limited to, DNS header, FTP header, SNMP header, and SMTP header. You may have to use some indirect methods for application layer headers, like offset of data to be looked for. • Packet payload. This means that you can create a rule that is used by the detection engine to find a string inside the data that is present inside the packet. In Snort version 2 all rules are matched against a packet before generating an alert. After matching all rules, the highest priority rule is selected to generate the alert. Logging and Alerting System: depending upon what the detection engine finds inside a packet, the packet may be used to log the activity or generate an alert. Logs are kept in simple text files, tcpdump-style files or some other form. All of the log files are stored under /var/log/ Snort folder by default. You can use –l command line options to modify the location of generating logs and alerts. Output Modules : output modules or plug-ins can do different operations depending on how you want to save output generated by the logging and alerting system of Snort. Depending on the configuration, output modules can do things like the following: 122 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort • Simply logging to /var/log/Snort/alerts file or some other file • Sending SNMP traps • Sending messages to syslog facility • Logging to a database like MySQL or Oracle. • Generating eXtensible Markup Language (XML) output • Modifying configuration on routers and firewalls. • Sending Server Message Block (SMB) messages to Microsoft Windows-based machines Other tools can also be usedto send alerts in other formats such as e-mail messages or viewing alerts using a web interface. Table 2 Snort's modules summarize. A.2 Setting up of our Snort sensor Depending upon the type of switches used, you can use Snort on a switch port. Some switches, allow you to replicate all ports traffic on one port where you can attach the Snort machine. These ports are usually referred to as spanning ports. The best place to install Snort is right behind the firewall or router so that all of the Internet traffic is visible to Snort before it enters any switch or hub. Fig 23 IDS behind the firewall 123 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort You can also connect the IDS to a small HUB or a Network TAP right behind the firewall, i.e., between firewall and the switch. Fig.24 Likely scenario for a Snort sensor Note that when the IDS is connected as shown in this last figure, data flowing among the company servers is not visible to the IDS. The IDS can see only that data which is coming from or going to the Internet. This is useful if you expect attacks from outside and the internal network is a trusted one. Supported Platforms : Snort is supported on a number of hardware platforms and operating systems. Currently Snort is available for the following operating systems: • Linux • OpenBSD • FreeBSD • NetBSD • Solaris (both Sparc and i386) • HP-UX • AIX • IRIX 124 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort • MacOS • Windows For a current list of supported platforms, refer to the Snort home page at http:// www.Snort.org. How to Protect IDS Itself: One major issue is how to protect the system on which your Intrusion Detection software is running. If security of the IDS is compromised, you may start getting false alarms or no alarms at all. The intruder may disable IDS before actually performing any attack. There are different ways to protect your system, starting from very general recommendations to some sophisticated methods. Some of these are mentioned below. • The first thing that you can do is not to run any service on your IDS sensor itself. Network servers are the most common method of exploiting a system. • New threats are discovered and patches are released by vendors. This is almost a continuous and non-stop process. The platform on which you are running IDS should be patched with the latest releases from your vendor. For example, if Snort is running on a Microsoft Windows machine, you should have all the latest security patches from Microsoft installed. • Configure the IDS machine so that it does not respond to ping (ICMP Echotype) packets. • If you are running Snort on a Linux machine, use netfilter/iptable to block any unwanted data. Snort will still be able to see all of the data. • You should use IDS only for the purpose of intrusion detection. It should not be used for other activities and user accounts should not be created except those that are absolutely necessary. Following are two special techniques that can be used with Snort to protect it from being attacked: •Snort on Stealth Interface . •Snort with no IP Address Interface . The advantage is that when the Snort host doesn’t have an IP address itself, nobody can access 125 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort it. You can configure an IP address on eth1 that can be used to access the sensor itself. A.3 Installing of Snort and Getting Started A simple Snort installation consists of a single Snort sensor run from terminal or from system start up as a daemon. To install Snort for this purpose, you can get a pre-compiled version or compile it yourself from the source code: http://www.Snort.org Putting the sensor behind a router or firewall will enable you to detect the activity of intruders into the system. However, if you are really interested in scanning all Internet traffic, you can put the sensor outside the firewall as well. Single Sensor with Database and Web Interface : the most common use of Snort should be with integration to a database. The data-base is used to log Snort data where it can be viewed and analyzed later on, using a web-based interface. A typical setup of this type consists of three basic components: 1. Snort sensor 2. A database server 3. A web server Snort logs data into the database. You can view the data using a web browser connected to the sensor. Different types of database servers like MySQL, PostgresSQL, Oracle, Microsoft SQL server and other ODBC-compliant databases can be used with Snort. This setup provides a very good and omprehensive IDS which is easy to manage and user friendly. Fig.25 Our company's system administrator. 126 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort Installation: - Snort's installation from sources: * some development tools & libraries we need: •flex •bison •checkinstall •libpcap0.8 •libnet1.0 apt-get install flex bison build-essential checkinstall libpcap0.8-dev libnet1-dev * we must download the next components for our installation: •libpcap1.3 (updated) •daq0.2 •pcre8.32 •libdnet1.12 (updated) •zlib1.2.7 •Snort2.9.4 cd libpcap1.3 ./configure && make && checkinstall dpkg -i libpcap0.8*.deb cd daq-0.2 ./configure && make && checkinstall dpkg -i daq_0.2-1_i386.deb cd pcre-8.32 ./configure && make && checkinstall dpkg -i pcre*.deb 127 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort cd libdnet-1.12 ./configure && make && checkinstall dpkg -i libdnet*.deb cd zlib-1.2.7 ./configure && make && checkinstall dpkg -i zlib*.deb And now we are already able to install our Snort sensor: cd Snort-2.9.4 ./configure && make && checkinstall dpkg -i Snort_*.deb Available command line options with the configure script can be listed using the “./configure – help” , “./configure –prefix=/opt/Snort --enable-smbalerts --enable-flexresp --with-mysql --with-snmp --with-openssl ” would an example of how to enable build in support for mysql database or snmp. Automatic Startup and Shutdown You can configure Snort to start at boot time automatically and stop when the system shuts down. On UNIX-type machines, this can be done through a script that starts and stops Snort. The script is usually created in the /etc/init.d directory on Linux. A link to the startup script may be created in /etc/rc3.d directory and shutdown links may be present in /etc/rc2.d, /etc/rc1.d and /etc/rc0.d directories. Snort Command Line Options Snort has many command line options that are very useful for starting Snort in different 128 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort situations. As you have already seen, command line options are helpful in running multiple versions of Snort on the same system. You can use “Snort -?” command to display command line options. Snort Modes Snort operates in two basic modes: packet sniffer mode and NIDS mode. It can be used as a packet sniffer, like tcpdump or snoop. When sniffing packets, Snort can also log these packets to a log file. The file can be viewed later on using Snort or tcpdump. No Intrusion Detection activity is done by Snort in this mode of operation. Using Snort for this purpose is not very useful as there are many other tools available for packet logging. For example, all Linux distributions come with the tcpdump program which is very efficient. When you use Snort in network Intrusion Detection (NIDS) mode, it uses its rules to find out if there is any network Intrusion Detection activity. Logging Snort Data in Text Format You can log Snort data in text mode by adding -l <directory name> on the command line. The following command logs all Snort data in /var/log/Snort directory in addition to displaying it on the console: Snort -dev -l /var/log/Snort Logging Snort in Binary Format On high-speed networks, logging data in ASCII format in many different files may cause high overhead. Snort allows you to log all data in a binary file in tcpdump format and view it later on. In this case, Snort logs all data to a single file in raw binary form. A typical command for this type of log is : Snort -l /tmp -b Snort will create a file in /tmp directory. To view this raw binary data, you can use Snort. The -r command line switch is used to specify a file name with Snort. The following command will display the captured data from file Snort.log.1037 Snort -dev -r /tmp/Snort.log.1037 | more The output of this command will show data in exactly the same way if you are looking at it on 129 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort the console in real time. You can use different switches to display different levels of detail with this data. You can also display a particular type of data from the log file. The following command displays all TCP type data from the log file: Snort -dev -r / tmp/Snort.log.1037840339 tcp Similarly, ICMP and UDP types of data can also be displayed. You can also use the tcpdump program to read files generated by Snort when logging in this mode. The following command reads the Snort files and displays captured packets in the file: tcpdump -r /tmp/Snort.log.1037 Network Intrusion Detection Mode In Intrusion Detection mode, Snort does not log each captured packet as it does in the network sniffer mode. Instead, it applies rules on all captured packets. If a packet matches a rule, only then is it logged or an alert is generated. If a packet does not match any rule, the packet is dropped silently and no log entry is created. When you use Snort in Intrusion Detection mode, typically you provide a configuration file on the command line: Snort -c /opt/Snort/etc/Snort.conf This configuration file contains Snort rules or reference to other files that contain Snort rules. In addition to rules, the configuration file also contains information about input and output plug-ins. The typical name of the Snort configuration file is Snort.conf. Other command line options and switches can be used when Snort is working in IDS mode. For example, you can log data into files as well as display data on the command line. The following command will log data to /var/log/Snort directory and will display it on the console screen in addition to acting as NIDS: Snort -dev -l /var/log/Snort -c /etc/Snort/Snort.conf However in most real-life situations, you will use -D command line switch with Snort so that it does not log on the console but runs as a daemon. In a typical scenario, you will also want to log Snort data into a database. Logging data into MySQL database could be an example. Snort Alert Modes When Snort is running in the Network Intrusion Detection (NID) mode, it generates alerts when a captured packet matches a rule. Snort can send alerts in many modes. These modes are configurable 130 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort • A <> symbol shows that the rule will be applied to packets traveling on either direction. This symbol is useful when you want to monitor data packets for both client and server. Rule options: Rule options follow the rule header and are enclosed inside a pair of parentheses. There may be one option or many and the options are separated with a semicolon. If you use multiple options, these options form a logical AND. The action in the rule header is invoked only when all criteria in the options are true. In general, an option may have two parts: a keyword and an argument. msg: "Detected confidential"; In this option msg is the keyword and “Detected confidential” is the argument to this keyword. * The ack Keyword : the TCP header contains an Acknowledgement Number field which is 32 bits long. The field shows the next sequence number the sender of the TCP packet is expecting to receive. This field is significant only when the ACK flag in the TCP header is set. Tools like nmap use this feature of the TCP header to ping a machine. For example, among other techniques used by nmap, it can send a TCP packet to port 80 with ACK flag set and sequence number 0. Since this packet is not acceptable by the receiving side according to TCP rules, it sends back a RST packet. When nmap receives this RST packet, it learns that the host is alive. This method works on hosts that don’t respond to ICMP ECHO REQUEST ping packets. To detect this type of TCP ping, you can have a rule like the following that sends an alert message: alert tcp any any -> 192.168.1.0/24 any (flags: A; ack: 0; msg: "TCP ping detected";) This rule shows that an alert message will be generated when you receive a TCP packet with the A flag set and the acknowledgement contains a value of 0. Generally when the A flag is set, the ACK value is not zero. 137 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort * The classtype Keyword : rules can be assigned classifications and priority numbers to group and distinguish them. To fully understand the classtype keyword, first look at the file classification.config which is included in the Snort.conf file using the include keyword. Each line in the classification.config file has the following syntax: config classification: name,description,priority for example: config classification: DoS,Denial of Service Attack,2 To fully understand the classtype keyword, first look at the file classification.config which is included in the Snort.conf file using the include keyword. Now let us use this classification in a rule. The following rule uses default priority with the classification DoS: alert udp any any -> 192.168.1.0/24 6838 (msg:"DoS"; content: "server"; classtype:DoS;) The following is the same rule but we override the default priority used for the classification. alert udp any any -> 192.168.1.0/24 6838 (msg:"DoS"; content: "server"; classtype:DoS; priority:1) Using classifications and priorities for rules and alerts, you can distinguish between highand low-risk alerts. This feature is very useful when you want to escalate high-risk alerts or want to pay attention to them first. Classifications are used in ACID , if you look at the ACID browser window, you will see the classification screens. * The content Keyword : One important feature of Snort is its ability to find a data pattern inside a packet. The pattern may be presented in the form of an ASCII string or as binary data in the form of hexadecimal characters. Like viruses, intruders also have signatures and the content keyword is used to find these signatures in the packet. The following rule detects a pattern “GET” in the data part of all TCP packets that are leaving 192.168.1.0 network and going to an address that is not part of that network. 138 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort alert tcp 192.168.1.0/24 any -> ![192.168.1.0/24] any (content: "GET"; msg: "GET matched";) alert tcp 192.168.1.0/24 any -> ![192.168.1.0/24] any (content: "|47 45 54|"; msg: "GET matched";) Hexadecimal number 47 is equal to ASCII character G, 45 is equal to E, and 54 is equal to T. * The offset Keyword : the offset keyword is used in combination with the content keyword. Using this keyword, you can start your search at a certain offset from the start of the data part of the packet. Use a number as argument to this keyword. The following rule starts searching for the word “HTTP” after 4 bytes from the start of the data. alert tcp 192.168.1.0/24 any -> any any (content: "HTTP"; offset: 4; msg: "HTTP matched";) * The depth Keyword : The depth keyword is also used in combination with the content keyword to specify an upper limit to the pattern matching. Using the depth keyword, you can specify an offset from the start of the data part. Data after that offset is not searched for pattern matching. If you use both offset and depth keywords with the content keyword, you can specify the range of data within which pattern matching should be done. The following rule tries to find the word “HTTP” between characters 4 and 40 of the data part of the TCP packet. alert tcp 192.168.1.0/24 any -> any any (content: "HTTP"; offset: 4; depth: 40; msg: "HTTP matched";) This keyword is very important since you can use it to limit searching inside the packet. For example, information about HTTP GET requests is found in the start of the packet. There is no need to search the entire packet for such strings. * The content-list Keyword : the content-list keyword is used with a file name. The file name, which is used as an argument to this keyword, is a text file that contains a list of strings to be searched 139 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort inside a packet. Each string is located on a separate line of the file. For example, a file named “porn” may contain the following three lines: “porn” “hardcore” “under 18” The following rule will search these strings in the data portion of all packets matching the rule criteria.: alert ip any any -> 192.168.1.0/24 any (content-list: "porn"; msg: "Porn word matched";) You can also use the negation sign ! with the file name if you want to generate an alert for a packet where no strings match. * The dsize Keyword: the dsize keyword is used to find the length of the data part of a packet. Many attacks use buffer overflow vulnerabilities by sending large size packets. Using this keyword, you can find out if a packet contains data of a length larger than, smaller than, or equal to a certain number. The following rule generates an alert if the data size of an IP packet is larger than 6000 bytes: alert ip any any -> 192.168.1.0/24 any (dsize: > 6000; msg: "Large size IP packet detected";) * The flags Keyword : The flags keyword is used to find out which flag bits are set inside the TCP header of a packet. Table 3 Flags' keywords 140 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort You can also use !, +, and * symbols just like IP header flag bits ! symbol is used for NOT, + is used for AND, and * is used for OR operation. alert tcp any any -> 192.168.1.0/24 any (flags: SF; msg: “SYNC-FIN packet detected”;) * The fragbits Keyword : The IP header contains three flag bits that are used for fragmentation and reassembly of IP packets. - DF: Don't Fragment Bit - MF: More Fragments Bit Sometimes these bits are used by hackers for attacks and to find out information related to your network. For example, the DF bit can be used to find the minimum and maximum MTU for a path from source to destination. Using the fragbits keyword, you can find out if a packet contains these bits set or cleared. The following rule is used to detect if the DF bit is set in an ICMP packet: alert icmp any any -> 192.168.1.0/24 any (fragbits: D; msg: "Don’t Fragment bit set";) In this rule, D is used for DF bit. You can use R for reserved bit and M for MF bit. You can also use the negation symbol ! in the rule. The following rule detects if the DF bit is not set, although this rule is of little use. alert icmp any any -> 192.168.1.0/24 any (fragbits: !D; msg: "Don’t Fragment bit not set";) * The icmp_id Keyword : The icmp_id option is used to detect a particular ID used with ICMP packet. Read texts related to ICMP header for further information. For example: alert icmp any any -> any any (icmp_id: 100; msg: "ICMP ID=100";) Table 4 Type of ICMP packet 141 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort * The icmp_seq Keyword for example: alert icmp any any -> any any (icmp_seq:100; msg: "ICMP Sequence=100";) * The itype Keyword : The ICMP header comes after the IP header and contains a type field. for example: alert icmp any any -> any any (itype: 4; msg: "ICMP Source Quench Message received";) alert icmp any any -> any any (itype: 4; msg: "ICMP Source Quench Message received";) * The icode Keyword : In ICMP packets, the ICMP header comes after the IP header. It contains a code field . The type field in the ICMP header shows the type of ICMP message. • If code field is 0, it is a network redirect ICMP packet. • If code field is 1, it is a host redirect packet. • If code is 2, the redirect is due to the type of service and network. • If code is 2, the redirect is due to type of service and host. The icode keyword in Snort rule options is used to find the code field value in the ICMP header. The following rule generates an alert for host redirect ICMP packets. alert icmp any any -> any any (itype: 5; icode: 1; msg: "ICMP ID=100";) Both itype and icode keywords are used. Using the icode keyword alone will not do the job because other ICMP types may also use the same code value. * The id Keyword : The id keyword is used to match the fragment ID field of the IP packet header. Its purpose is to detect attacks that use a fixed ID number in the IP header of a packet. Its format is as follows: id: "id_number" If the value of the id field in the IP packet header is zero, it shows that this is the last fragment of an IP packet (if the packet was fragmented). The value 0 also shows that it is the only fragment if the 142 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort packet was not fragmented. The id keyword in the Snort rule can be used to determine the last fragment in an IP packet. * The ipopts Keyword : A basic IPv4 header is 20 bytes long. You can add options to this IP header at the end. The length of the options part may be up to 40 bytes. These options can be used by some hackers to find information about your network. Using Snort rules, you can detect such attempts with the ipopts keyword. The fol lowing rule detects any attempt made using Loose Source Routing: alert ip any any -> any any (ipopts: lsrr; msg: "Loose source routing attempt";) * The ip_proto Keyword : The ip_proto Keyword The ip_proto keyword uses IP Proto plug-in to determine protocol number in the IP header. alert ip any any -> any any (ip_proto: ipip; msg: "IP-IP tunneling detected";) For further information about protocol numbers, consult the /etc/protocols file in your linux system. * The logto Keyword : The logto keyword is used to log packets to a special file. The general syntax is as follows: logto:logto_log Consider the following rule: alert icmp any any -> any any (logto:logto_log; ttl: 100;) This rule will log all ICMP packets having TTL value equal to 100 to file logto_log, a file that later you can open with your “more”, “cat” or any other tool used to display a file into console. 143 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort * The msg Keyword : The msg keyword in the rule options is used to add a text string to logs and alerts. You can add a message inside double quotations after this keyword. The msg keyword is a common and useful keyword and is part of most of the rules. The general form for using this keyword is as follows: msg: "Your message text here"; If you want to use some special character inside the message, you can escape them by a backslash character. * The nocase Keyword : The nocase keyword is used in combination with the content keyword. It has no arguments. Its only purpose is to make a case insensitive search of a pattern within the data part of a packet . * The priority Keyword : The priority keyword assigns a priority to a rule. Priority is a number argument to this keyword. Number 1 is the highest priority. The keyword is often used with the classtype keyword. alert ip any any -> any any (ipopts: lsrr; msg: "Loose source routing attempt"; priority: 10;) The priority keyword can be used to differentiate high priority and low priority alerts. * The react Keyword : The react keyword is used with a rule to terminate a session to block some sites or services. Not all options with this keyword are operational. The following rule will block all HTTP connections originating from your home network 192.168.1.0/24. To block the HTTP access, it will send a TCP FIN and/or FIN packet to both sending and receiving hosts every time it detects a packet that matches these criteria. The rule causes a connection to be closed: alert tcp 192.168.1.0/24 any -> any 80 (msg: "Outgoing HTTP connection"; react: block;) 144 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort In the above rule, “block” is the basic modifier. You can also use the “warn” modifier to send a visual notice to the source. You can also use the additional modifier “msg ” which will include the msg string in the visual notification on the browser. The following is an example of this additional modifier. alert tcp 192.168.1.0/24 any -> any 80 (msg: "Outgoing HTTP connection”; react: warn, msg;) Note: In order to use the react keyword, you should compile Snort with --enableflexresp command line option in the configure script. For a discussion of the compilation process. The react should be the last keyword in the options field. * The reference Keyword : * The resp Keyword: The resp keyword is a very important keyword. It can be used to knock down hacker activity by sending response packets to the host that originates a packet matching the rule. The keyword is also known as Flexible Response or simply FlexResp and is based on the FlexResp plug-in. The plug-in should be compiled into Snort using the command line option (--with-flexresp) in the configure script. The following rule will send a TCP Reset packet to the sender whenever an attempt to reach TCP port 8080 on the local network is made. alert tcp any any -> 192.168.1.0/24 8080 (resp: rst_snd;) You can send multiple response packets to either sender or receiver by specifying multiple responses to the resp keyword. The arguments are separated by a comma. The list of arguments that can be used with this keyword is found in the following table. Table 5 List of arguments 145 Arturo Ruiz Mañas Desarrollo de un 'sniffer' para la generación de listas blancas para Snort * The rev Keyword : * The rpc Keyword : * The sameip Keyword : The sameip keyword is used to check if source and destination IP addresses are the same in an IP packet. It has no arguments. Some people try to spoof IP packets to get information or attack a server. The following rule can be used to detect these attempts: alert ip any any -> 192.168.1.0/24 any (msg: "Same IP"; sameip;) * The seq Keyword : The seq keyword in Snort rule options can be used to test the sequence number of a TCP packet. The argument to this keyword is a sequence number. The general format is as follows: seq: "sequence_number"; Sequence numbers are a part of the TCP header. * The flow Keyword : The flow keyword is used to apply a rule on TCP sessions to packets flowing in a particular direction. You can use options with the keyword to determine direction. The following options can be used with this keyword determine direction: • to_client • to_server • from_client • from_server Other options are also available which are used to apply the rule to different states of a TCP connection. • The stateless option is used to apply the rule without considering the state of a TCP session. • The established option is used to apply the rule to established TCP sessions only. • The no_stream option enables rules to be applied to packets that are not built from a stream. 146