Entendiendo el tráfico de red industrial, disectores y Lua y Kaitai
Análisis de tráfico de protocolos industriales
El análisis de tráfico o de tramas es una técnica muy valiosa para comprobar la seguridad en las comunicaciones y en los protocolos involucrados. El objetivo principal es obtener la mayor cantidad de información y conocimiento posible de las comunicaciones, pero ¿qué sucede si el analizador utilizado no dispone de los medios para interpretar los campos del protocolo?
En la industria, muchas veces nos enfrentamos a protocolos de los que no siempre disponemos de un analizador para sus tramas, bien porque sean propietarios o porque, aun siendo estándares, no tienen un uso muy extendido. Son estos protocolos los que requerirán un esfuerzo extra en su análisis para crear un nuevo disector (un plugin que permite al programa principal descomponer un paquete de datos siguiendo unas características) que permita su tratamiento de forma automatizada por las principales herramientas analizadoras de red.
Sin embargo, no todos los protocolos son igual de sencillos de interpretar. La primera clasificación la podemos hacer de acuerdo con la existencia o no de especificación del mismo. Como ya se ha comentado, por un lado, los protocolos con poco uso, aun disponiendo de especificación, pueden no estar soportados, mientras que por otro lado, los protocolos propietarios, no disponen de ningún tipo de información.
La segunda clasificación se realiza por complejidad de los protocolos. La división lógica se hace entre protocolos sencillos, donde cada trama puede analizarse de forma independiente ya que contienen toda la información, y complejos, donde una trama depende de información de tramas anteriores y requiere de reensamblado o de la interpretación (descompresión o descifrado) de determinados campos.
La gran mayoría de protocolos industriales antiguos están orientados al mensaje, por lo que encajarían dentro del grupo de simples. Estos protocolos utilizan de forma habitual un cable serie (principalmente bajo el estándar RS-485) como medio físico. La trasformación de estos protocolos al mundo ethernet hizo que su complejidad se elevase, si bien es cierto que muchos de ellos siguen siendo orientados al mensaje, los nuevos protocolos suelen ser más complejos y encajan más en el segundo grupo. Como ya se ha comentado en múltiples ocasiones, el número de protocolos industriales de tipo propietario es bastante superior al existente en entornos corporativos, lo que también dificulta la creación de disectores al no existir documentación pública al respecto.
Herramientas para crear nuevos disectores: LUA y Kaitai
Las herramientas de análisis de tráfico se basan en disectores específicos que permiten entender los protocolos y delimitar los campos de información que contienen las tramas de dichos protocolos. Lo más habitual es que los usuarios puedan añadir nuevos disectores que permitan la interpretación de protocolos no soportados inicialmente.
Así, la herramienta Wireshark, dispone de varios disectores predefinidos, entre los que se incluyen un elevado número para protocolos industriales, incluyendo Modbus/TCP, DNP3, IEC104, etc. Además, por si fuera necesario, dispone de la posibilidad de integrar nuevos disectores basados en scripts escritos en LUA.
Sin embargo, Wireshark no es la única herramienta de análisis, aunque sí una de las más extendidas y conocidas, por lo que desarrollar un script exclusivamente para esta herramienta puede ser contraproducente. Por este motivo, han surgido otras alternativas, como Kaitai Struct, que permiten la definición de parseadores para estructuras binarias y posteriormente su exportación a diferentes lenguajes para su integración en un gran número de aplicaciones.
Pasos para crear un disector
Para poder llevar cabo un buen análisis del protocolo que se traduzca posteriormente en un correcto disector, se deben llevar a cabo una serie de fases para la obtención de la mayor cantidad de información posible.
Documentación
La información referente a los protocolos y los campos que lo definen es lo primero que debe obtenerse. Si el protocolo es abierto, existirá una especificación técnica con todos los detalles. Estas especificaciones suelen ser documentos de pago, pero el coste puede compensarse con el valor obtenido del análisis, en el caso de ser una empresa dedicada a la seguridad, o por otras motivaciones que pueda tener el desarrollador.
Si no se dispone de especificación hay que intentar conseguir información de fuentes alternativas, como foros técnicos, presentaciones, etc., donde se haya podido desgranar un poco el formato de la trama y alguno de los campos que la componen. Normalmente, esta información será bastante genérica, poco detallada, y sobre aspectos generales del protocolo, por ejemplo, rara vez se verán descritas todas las posibles funciones.
Toda esta información es determinante a la hora de conseguir una interpretación adecuada del protocolo y los campos que lo definen.
Recopilar tramas del protocolo a diseccionar
Si se dispone de la especificación técnica o se ha conseguido toda la información del protocolo, esta fase de recopilación de tramas no será necesaria, en caso contrario, disponer de tramas de tráfico real del protocolo en cuestión, será la única forma de completar nuestro conocimiento sobre dicho protocolo.
El objetivo de esta fase será disponer del mayor número de paquetes capturados del protocolo a diseccionar, tratando de que el tráfico capturado sea acotado y conocido para poder realizar una correcta clasificación de las mismas. Lo ideal sería poder disponer de capturas de todos los tipos de tramas existentes en el protocolo, pero eso no siempre es posible.
Para la recopilación de las tramas se puede utilizar cualquier herramienta de captura de tráfico y evitar que la captura se vea contaminada por tramas de otros protocolos. Para ello, hay que aislar los equipos involucrados en la comunicación que se pretende capturar. La captura puede hacerse mediante un puerto mirror o espejo/span de un switch o router o utilizando un hardware específico denominado network tap.
Identificar partes comunes generales
A la hora de iniciar el disector hay que identificar las partes comunes entre todas las tramas y las no comunes, de forma que permita ir haciendo una primera identificación de las tramas que las separen del resto de protocolos.
Estos primeros campos a identificar son:
- Puerto de comunicaciones: Define el puerto o puertos típicos por los que se realiza la comunicación (TCP o UDP). Este puerto puede ser fijo y estar reservado para el protocolo (como el 502/TCP para el protocolo Modbus/TCP).
- Cabecera del protocolo industrial: Es importante identificar el tamaño de la cabecera del protocolo, no confundir con la cabecera del paquete ethernet y los campos que alberga. Algunos de los campos más típicos son:
- Identificación de protocolo: habitualmente los primeros bytes de la trama.
- Identificación de estación o nodo de conexión: sobre todo en protocolos de tipo cliente/servidor.
- Tamaño del paquete de datos: Identifica la longitud de los datos propios del protocolo.
- Datos: Definido a partir del tamaño de datos alojado en la cabecera del paquete, esta parte de la trama suele ser la más diferente y es difícil encontrar partes comunes. Puede ocurrir que dentro del campo de datos exista una parte final que comprende un CRC/hash para verificar la integridad de los datos.
Identificar partes comunes específicas
Una vez que se ha definido la estructura general de la trama, es hora de identificar partes comunes entre diferentes tramas. Lo más fácil es separar en primer lugar las peticiones de las respuestas y tratar de ver partes comunes dentro de cada grupo. Algunos campos o características que se pueden buscar son:
- Identificación de acción/función: Los protocolos industriales se suelen basar en un código de acción que define la acción a realizar. Hay que tratar de identificar este campo y todos aquellos códigos posibles para dicho campo, ya que esto permitirá definir el campo siguiente.
- Campo de datos: De forma habitual contendrá las variables involucradas en la acción y el valor. Aquí hay que identificar el modo de definir las variables, que puede ser:
- listar todas las variables,
- listar inicio y fin,
- marcar el inicio e indicar la cantidad.
Seguidamente vendrán los valores, que dependerán del número de variables, aunque puede tener alguna característica concreta, como definir un número de bytes determinado por valor, por ejemplo.
Una vez que se dispone de toda la información que define al protocolo, solo queda escribirlo en un lenguaje adecuado de acuerdo con el analizador de tráfico que se vaya a utilizar.
Ejemplo de disector
Se va a tomar como ejemplo para la creación de un disector, el protocolo de formación por excelencia, es decir, Modbus/TCP. Aunque la gran mayoría de analizadores ya incluyen un disector para este protocolo, como ejemplo es válido.
El protocolo Modbus se caracteriza por ser abierto, como ya se contó en el estudio Protocolos y seguridad de red en infraestructuras SCI.
La trama Modbus está completamente definida en la especificación, por lo que se puede empezar directamente a realizar la parametrización del disector sin un análisis de tramas.
Para este ejemplo se va a partir de Kaitai para hacer la definición de la parametrización del protocolo, y, luego, a través del script kaitai-to-wireshark se hace la traducción a Lua para poder incorporarlo a Wireshark.
Kaitai hace uso de lenguaje YAML para la creación de los ficheros binarios o .ksy. El fichero para el protocolo modbus puede ser como se muestra a continuación.
Si pasamos el fichero .ksy al script de conversión se obtiene el siguiente fichero en formato .lua.
Del que, haciendo pocas modificaciones, como es la inclusión del puerto (en la sección
El script resultante de las modificaciones debe incluirse en la ruta de plugins propia de Wireshark. En versiones anteriores de Wireshark era necesario modificar un fichero de configuración, pero en las últimas versiones, con la simple inclusión en el directorio Plugins ya se carga de manera automática al iniciar el programa.