SNMP ¿Es tan Simple como el nombre indica?
El protocolo SNMP, del inglés “Simple Network Management Protocol”, fue creado con la idea de administrar, de una manera común, todos los dispositivos en una red, independientemente del tipo de dispositivo. Esto, en la industria, supuso una ventaja a la hora de administrar los dispositivos conectados a una red Ethernet, debido a su heterogeneidad, por lo que la mayoría de dispositivos industriales disponen de un agente SNMP configurable.
Este protocolo se usa para el intercambio de información de configuración de red de un dispositivo. Debido a la gran variedad de dispositivos industriales, no siempre de un mismo fabricante, implicados en los diferentes niveles de la pirámide de automatización, el uso de este protocolo está muy extendido.
Digamos que SNMP es un protocolo que permite intercambiar información, mensajes SNMP, relevante sobre la configuración del dispositivo, entre el Gestor o controlador y el Agente o controlado. Los mensajes SNMP se pueden englobar en mensajes de monitorización o lectura (get) y mensajes de control o escritura (set). Una funcionalidad especial de SNMP, muy valorada por los administradores de sistemas, son los TRAPS. Este tipo de trama SNMP Trap, fue diseñada para mandar alertas desde un dispositivo o agente, al receptor de alarmas (SNMP TRAPS). Permite enviar varios tipos de alarmas ‘start’, ‘stop’, ‘warm start’, ‘failure’, etc… Permite configurar un gran número de eventos para ser enviados mediante este tipo de trama SNMP, dependiendo del dispositivo en concreto.
El protocolo SNMP se implementa en la capa 7 del modelo OSI o capa de aplicación, y es enviado normalmente por UDP/IP por los puertos 161 y 162. Dispone actualmente de varias versiones diferenciadas principalmente por la seguridad que aplican.
SNMP en detalle
Para entender el detalle de una trama SNMP lo mejor es verla como un conjunto de campos anidados. El principal fragmento de información es el OID, que identifica exactamente el valor a leer (get) o a escribir (set). El conjunto de OID (Object IDentifier) que tiene disponible un dispositivo se conoce como MIB (Management Information Base) y es como un índice en forma de árbol donde podemos encontrar la referencia que buscamos. Los tipos de datos de los OID están definidos por ASN.1 y usan una codificación específica denominada BER (Basic Encoding Rules).
Por ejemplo, mediante el envío de una trama SNMP get, con un OID .1.3.6.1.2.1.1.1 correspondiente a descripción del dispositivo sysDesc(), representada en la imagen del árbol MIB, recibiremos una respuesta por parte del dispositivo con su valor:
- Ejemplo respuesta de un dispositivo ante petición sysDesc() OID .1.3.6.1.2.1.1.1 -
- Árbol representativo de MIB y representación de OID -
Si pensamos en la estructura de carpetas de ficheros de un ordenador, un fichero con su ruta sería un OID y el conjunto de carpetas y ficheros de una unidad sería un MIB. Un dispositivo puede tener varias unidades de disco (Varios MIB). En cada unidad, todos los ficheros (OID) son conocidos de antemano, están escritos y bien definidos. Su contenido es almacenado mediante el estándar SMI (Structure of Management Information).
- Ejemplo de estructura de información SMI y sus campos, de un OID contenido en un fichero MIB -
ASN.1
Al hablar de tipos de datos, como sucede en los diferentes lenguajes de programación, pueden variar en el número de bits empleados para su codificación. Para evitar diferentes interpretaciones cuando se hable, por ejemplo, de Integer, se define un identificador y un tamaño de longitud variable. Esto nos asegura que siempre que aparezca un identificador sepamos exactamente su equivalencia en codificación y ésta sea única. En SNMP existen dos conjuntos diferentes de datos: los datos primitivos y los datos complejos, como se muestra en la tabla siguiente.
- Tabla con ejemplos de tipos de datos primitivos y complejos -
La longitud para estos tipos de datos es variable, por lo que para resolver este problema se define una regla BER (Basic Encoding Rules). Un BER define un formato estándar para codificar los tipos de datos, tanto primitivos como complejos. Los campos que se definen son:
- Tipo: Corresponde con el identificador mostrado en la tabla.
- Longitud: Longitud o tamaño del campo datos.
- Datos: Valor del tipo de dato.
Los tipos complejos son definidos como una secuencia anidada de campos.
- Estructura de la codificación de un dato primitivo -
El campo longitud, que nos indica la longitud en bytes del tipo de datos, puede necesitar un valor mayor de 127. La codificación de la longitud se hace de una forma especial. A continuación, se describe cómo codifica el campo longitud, para valores por encima de 127.
Para codificar un número alto, por ejemplo, el 1002, se emplea un primer octeto formado por ‘bit más significativo’ cuyo valor es puesto a ‘1’ para indicar que el valor de la longitud está formado por un número largo, y los 7 siguientes bits ‘menos significativos’ son usado para indicar el número de octetos siguientes, que es donde realmente se codifica el número largo. En el caso que nos ocupa, para representar 1002 se van a necesitar 2 octetos, por lo que este primer octeto se codificará como 10000010 (0x82), indicando como se muestra en la imagen, que es un número grande y que va seguido por 2 Octetos. Los dos siguientes octetos codifican el valor del número, tal cual, empleando todos los bits de los octetos en su codificación.
- Regla para la codificación de números grandes en bytes para Campo Longitud SNMP -
No confundir con la codificación de un número grande dentro de un campo OID, ya que se realiza de una manera diferente:
- Estructura de la codificación de datos complejos -
- Captura de tráfico de petición get-response SNMP en wireshark -
Dos matices necesarios para entender por completo la forma de codificación de valores en un OID:
- Los “Object Identifier”: Los dos primeros números de un OID (x.y….) se codifican de una forma especial usando la fórmula (40×x)+y, así los dos primeros números del OID (1.3….) = (40×1)+3=43=0x2B, enviándose (0x2B), el resto se codifica por su correspondencia hexadecimal del número entero. Para un OID = 1.3.6.1.2.1.1.5.0, su codificación será:
- Regla para la codificación de un OID en bytes para SNMP -
- Los números enteros por encima de 127 son codificados de manera especial en los OID, ya que se necesita más de un byte debido a que el primer bit (el de mayor peso) está reservado. La regla específica para la codificación de números grandes que pueden aparecer en un OID es como se explica a continuación: El primer bit del primer octeto (byte) puesto a 1 indica que es un número grande, y solo se utilizan los 7 bits restantes para formar el número. Empezando a crear octetos con los 7 bits menos significativos, empleando el bit más significativo como ‘FLAG’, indicando, con un ‘1’ si continúan octetos para delimitar el número o con un ‘0’ indicando que son los últimos 7 bits del número que vamos a representar. Supongamos que tenemos dentro de un OID un número grande (mayor de 127) que necesitamos codificar, por ejemplo, el número 1002. Este se codificará de la siguiente manera (0x87 0x6A), como vemos en la imagen:
- Regla para la codificación de números grandes en bytes para SNMP -
Las tramas SNMP se pueden dividir en dos secciones:
- Cabecera SNMP o Header: Esta sección incluye todos los campos de control necesarios para procesar dicha trama, así como todos los campos que incluyen seguridad (versión, comunidad, tipo de cifrado si existe, etc…).
- Cuerpo SNMP o Data PDU: Contiene todos los campos de información referentes al protocolo (tipo de petición, ID, Error, OID, Valor, etc…).
Análisis de un mensaje SNMP completo:
- Captura de tráfico y explicación de todos los bytes de una trama SNMP en wireshark -
- Bytes enviados en Cabecera y Cuerpo de un mensaje SNMP -
La propia trama SNMP, como vemos en la imagen, se considera una “sequence”, que comienza con ‘0x30’ seguido de la longitud completa de la trama ‘0x32’ (50 bytes). Esta trama es transmitida por el protocolo UDP/IP:
- Encapsulado UDP de un mensaje SNMP -
MIB PROPIETARIOS… ¿SABEMOS LO QUE PERMITEN?
Todas las normativas de SNMP resaltan como buena praxis no usar el protocolo para configuraciones que puedan afectar el comportamiento del dispositivo en la red. Los estándares de SNMP no contienen prácticamente variables cuyo “ACCESS”, variable que define el modo de acceder a los datos (Lectura, Lectura/Escritura), este en modo ‘Read-Write’. No es una norma de obligado cumplimiento, y muchos fabricantes industriales aprovechan estas facilidades de configuración para incluir ciertas funcionalidades en sus dispositivos industriales. Estas funcionalidades extra son descritas en MIB privados de los fabricantes.
Lo primero que debemos realizar antes de un correcto bastionado de nuestros agentes SNMP es un análisis de los MIB de nuestros dispositivos, concretar si disponen de MIB privados, analizar el alcance de éstos y realizar un informe de riesgos.
Los ficheros MIB son parecidos a las librerías de programación, donde se almacenan funciones OID que al ser llamadas devuelven un resultado.
Los OID están diseñados para mostrar una información, pero también se emplean por algunos fabricantes para cambiar de un estado a otro, por ejemplo, o para reconfigurar la forma en la que se accede a la red. Las funciones que se le pueden dar a los OID son infinitas, de ahí la importancia de conocerlas. Una opción normal de un OID estándar puede ser mostrar la información sobre la manera de acceder a la red DHCP, BOOTP…, pero si un fabricante, para facilitarse ciertas tareas, le añade la posibilidad de cambiar este estado mediante dicho OID, cambiando una variable a Read-write, este pasa a ser un OID de control a tener muy en cuenta.
- Ejemplo de OIDs permite habilitar DHCP, BOOTP o desactivar perteneciente a un MIB privado -
Los fabricantes diseñan los MIB privados para facilitar la configuración entre sus productos, suponiendo siempre un correcto bastionado de todos los elementos de la red, y sin tener en cuenta las funcionalidades expuestas del dispositivo ante una configuración SNMP no bastionada de manera correcta.
- Ejemplos reales de OIDs con funcionalidades “extra” en MIB privados -
Los fabricantes han aprovechado esta característica de SNMP para crear verdaderas API a modo de ficheros MIB privados, que permiten a un dispositivo en algunos casos demasiadas opciones de configuración sensible no contraladas, que muchas veces desconocen los propios usuarios de los mismos.
- Ejemplos de OIDs con funcionalidades “extra” en MIB privados -
BASTIONADO
Una vez realizado nuestro informe de riesgos, basado en los MIB usados por nuestro dispositivo industrial, vamos a proceder con el correcto bastionado del agente SNMP. Tener siempre en mente las siguientes buenas prácticas:
- Si no se necesita, desactívalo.
- No usar nunca la configuración por defecto, dedica el tiempo necesario para configurar de forma correcta el agente SNMP.
- Usar la versión más segura de SNMP que permitan los dispositivos.
- Si el informe de riesgo aconseja un nivel de seguridad superior al que permite la configuración del dispositivo, aplicar medidas adicionales, cuando sea posible, fuera del propio bastionado del dispositivo.
Normalmente nos encontraremos con diferentes entornos de configuración de SNMP. Pero todos, en mayor o menor medida, deberán contener ciertos campos comunes que son la clave de un correcto bastionado.
- Campo de configuración referente a la selección de la versión de SNMP -
Hay que asegurarse elegir la opción de versión más alta que acepten nuestros dispositivos. Se puede considerar que SNMPv1 y SNMPv2c no tienen suficientes opciones de seguridad, por lo que evitaremos utilizar estas versiones en la medida de lo posible, permitiendo al agente la comunicación por SNMPv3.
- Campo de configuración referente a las IP permitidas para gestionar el agente SNMP -
Disponer de configuraciones lo más restrictivas posibles IP individuales/únicas, no habilitar IPs por rangos o mascaras de red, y sobre todo nunca dejar configuraciones por defecto.
- Campo de configuración referente a la selección de las claves de comunidad para SNMP -
Las opciones dependerán del dispositivo y del fabricante, pudiendo variar significativamente de unas a otras. La opción de “Desactivar” es la mejor opción si realmente no lo necesitamos. Nunca dejar la clave por defecto, ya que esta clave suele aparecer en todos los manuales del dispositivo. Dentro de las restricciones de longitud que establezca el fabricante, intentar crear claves robustas.
Los siguientes campos suelen ser opciones extra de seguridad ofrecidas dependiendo de la versión elegida de SNMP. En la medida de lo posible se recomienda siempre su uso.
- Campo de configuración referente a la selección de las claves de autenticación para SNMPv2 y posteriores -
- Campo de configuración referente a cifrados del mensaje SNMP -
Estas medidas de seguridad fueron introducidas en la versión SNMPv2u User-Based Security Model (USM), y mantenidas en la versión SNMPv3.
- Campo de configuración referente al modelo VACM (View-Based Access Control Model) para SNMPv3 -
El modelo VACM (View-Based Access Control Model) es parte del estándar de SNMPv3, dependiendo del modelo y del fabricante nos ofrecerá unas opciones u otras, pero el trasfondo es el mismo: crear accesos a ciertos OID agrupados por usuarios o roles, creando así vistas para los diferentes perfiles del proceso industrial.
MI AGENTE SNMP_007 NO ES TAN BUENO…
Existen ocasiones en las que las medidas de bastionado proporcionadas por el fabricante no son lo suficientemente robustas. En estos casos debemos pensar en medidas adicionales, como las que se proponen a continuación:
Añadir cortafuegos delante de los dispositivos industriales menos robustos creando reglas para aceptar o rechazar tráfico SNMP.
El conocimiento de las tramas SNMP nos puede ayudar tanto para realizar análisis de tráfico pasivo y alertar de comportamientos extraños en la red, como para crear reglas de descarte de tramas mediante inspección profunda de paquetes (Deep packet Inspection). Para mejorar la seguridad en dispositivos que no la ofrezcan en su configuración se pueden usar también herramientas IDS/IPS específicas para rechazar tramas SNMP de tipo SET, o más específicas dentro la trama SNMP como puede ser detener el tráfico de OID específicos, especialmente delicados.
El conocimiento en profundidad de nuestros protocolos, así como de las funcionalidades ofrecidas por nuestros dispositivos, son claves a la hora de realizar un informe de riesgos. La configuración de cualquier dispositivo debe ser entendida, analizada y metódica, nunca dejar las configuraciones por defecto. El flujo de información entre el fabricante y operadores de todos los niveles (Operador de campo, Sistemas, Supervisión, etc…) debe ser constante. Estas son las bases para un correcto bastionado, en cualquier dispositivo.