Denegación de servicio a un PLC Omron con comandos legítimos en FINS

Hace poco leí un artículo en el blog de Shodan titulado “Why control systems are on the Internet” escrito por John Matherly (fundador de Shodan), en el que comentaba un párrafo de la documentación oficial de Omron donde se explica porqué la conexión a internet de los PLCs de esta marca es completamente segura.

Su robusta teoría se basa (o se basaba, desconozco si han cambiado su punto de vista) en que sus PLCs no tenían un sistema operativo basado en Windows ni se comunicaban a través de un puerto conocido con un protocolo estándar de Ethernet, lo que los haría invisibles a los malvados ojos de los atacantes.

Según esta curiosa pero extendida manera de concebir la seguridad, sería extremadamente extraño que, por ejemplo, alguien se descargara la especificación oficial del protocolo FINS (protocolo industrial de Omron) de la página web oficial e intentara comunicarse con un PLC.

Para ponernos en contexto, la manera legítima de configurar y trabajar con los componentes industriales de la marca Omron es con el software de esta marca CX-One, que comprende distinto software como el CX-Programmer, diseñado para la configuración y programación de los PLCs.

Aunque estos PLCs pueden disponer de diferentes módulos de comunicación como Ethernet, están diseñados con la idea de que bajo cualquier problema que surja, siempre sea posible una conexión en serie de manera física.

En las siguientes imágenes tenemos una instancia del CX-Programmer monitorizando uno de los programas cargados en un PLC Omron CJ2M, el cual está conectado en serie al PC con el CX-Programmer y por Ethernet a la red. En la imagen estamos cambiando el modo operativo del PLC de monitorización a programación o lo que es lo mismo, lanzando un comando FINS de stop.

Ilustración 1 – Programa cargado en PLC en modo monitorización. CX-Programmer

Ilustración 2 – Resultado del PLC en modo programación (stop)

Como podemos observar, han desparecido las líneas verdes, lo que indica que la orden se ha ejecutado correctamente y la ejecución del programa ha parado. Buceando en la especificación oficial del protocolo, nos podemos encontrar con 3 comandos que a primera vista nos pueden parecer curiosos:

  • 0C01: ACCESS RIGHT ACQUIRE.
  • 0C02: ACCESS RIGHT FORCED ACQUIRE.
  • 0C03: ACCESS RIGHT RELEASE.

Si investigamos un poquito más sobre estos comandos sacamos las siguientes conclusiones:

  • Es posible obtener un derecho de acceso para ejecutar órdenes sin ser interrumpidos, el cual impide a otras unidades ejecutar ciertos comandos (tabla 1) que puedan inferir en el correcto funcionamiento de estas órdenes.
  • El uso correcto de este derecho de acceso es el siguiente: Cuando se necesita ejecutar una secuencia de comandos sin ser interrumpido, se ejecuta ACCESS RIGHT ACQUIRE, cuando hemos terminado, liberamos el derecho de acceso ejecutando ACCESS RIGHT RELEASE.
  • Si el derecho de acceso lo tiene otra unidad, ACCESS RIGHT ACQUIRE no funcionará hasta que se liberen los derechos de acceso con ACCESS RIGHT RELEASE.
  • Si se necesita ejecutar una operación con máxima prioridad y otro dispositivo tiene el derecho de acceso, es posible cancelárselo y obtenerlo nosotros mediante el comando ACCESS RIGHT FORCED ACQUIRE.

Ilustración 3 – Comandos prohibidos si otro host tiene el derecho de acceso

Conociendo ya el funcionamiento y con la especificación del protocolo en la mano, lo primero que se nos ocurre es: ¿qué pasaría si le enviamos un FORCE GET RIGHT ACQUIRE desde una máquina sin venir a cuento? Y nos entra la siguiente duda: ¿seremos capaces de ejecutar un GET RIGHT ACQUIRE sin utilizar las herramientas proporcionadas por Omron? O por el contrario, al ver que no está basado en un sistema Windows, daremos media vuelta y finalizaremos este artículo aquí mismo?

Lo primero que hacemos es estudiar la estructura de un comando de FINS:

Ilustración 4 – Estructura de un comando FINS

No entraré en más detalles sobre la cabecera, siguiendo las explicaciones en la especificación se pueden rellenar los campos vacíos.

A continuación consultamos el Command Code de la orden que queremos enviar (ACCESS RIGHT FORCED ACQUIRE):

Ilustración 5 – Command Block de ACCESS RIGHT FORCED ACQUIRE

Sabiendo esto, la IP del PLC y sabiendo que FINS escucha en el puerto 9600, creamos una función en Python para enviar este paquete al PLC.

Ilustración 6 – script de Python para enviar el paquete FINS

Ejecutamos la función force( ), que envía el paquete FINS:

Ilustración 7 – Envío y respuesta del comando

Como podemos ver por la respuesta 00 00, el comando se ha ejecutado correctamente, y para ver las consecuencias, intentaremos ejecutar como en el ejemplo del inicio, un cambio de modo del PLC de monitorización a programación (stop), ya que este es uno de los comandos que no se pueden ejecutar si otro dispositivo tiene el derecho de acceso.

Ilustración 8 – Cambio de modo operativo

Ilustración 9 – Fallo en el cambio de operación

Como podemos observar en el resultado, se ha producido un fallo al cambiar el modo de operación. Este fallo, como hemos comentado, es debido a que no se puede ejecutar la función STOP si algún otro dispositivo acapara el derecho de acceso.

Supongo que estaréis pensando: bueno, pero si nosotros podemos obtener los derechos de acceso, el software legítimo también podrá, ¿no?

Evidentemente sí. Mediante una operación manual podemos liberar los derechos de acceso como vemos en la siguiente imagen, lo cual significa que ya podremos ejecutar la orden de cambio de modo del PLC.

Ilustración 10 – Liberar derechos de acceso

Ilustración 11 – Derechos de acceso liberados

Ahora bien, ¿y si le enviamos comandos ACCESS RIGHT FORCED ACQUIRE continuamente?

Ilustración 12 – Envío continuo

Observamos que el PLC no parece tener ninguna limitación en la recepción de este comando, por lo que si enviamos este comando con la frecuencia suficiente y al tener que ejecutar la función de liberación de derechos de acceso manualmente, no dejaremos tiempo suficiente entre la liberación de los derechos de acceso y el envío de la orden que se quiere ejecutar, ya que entre estas dos acciones nos habremos apropiado del derecho de acceso, provocando una denegación de servicio.

Conclusiones

Hemos visto que sin complicaciones técnicas y haciendo un uso correcto pero malintencionado de funciones legítimas y NECESARIAS para asegurar un correcto funcionamiento y mantenimiento del proceso de control, podemos causar un comportamiento indeseado de este.

Lo que la experiencia nos ha demostrado es que más allá de las vulnerabilidades propiamente dichas, el gran problema que nos encontramos frente a la seguridad de un sistema de control industrial son las propias funcionalidades y requisitos de este, lo cual nos sitúa en una situación mucho más delicada, en la que para buscar soluciones realmente factibles, se hace necesaria la colaboración de los profesionales de la seguridad con los profesionales que trabajan día a día en con los procesos de control.

Comments

  1. Espectacular, Gonzalo. Efectivamente, el uso LEGÍTIMO PERO MALINTENCIONADO puede ser suficiente en este tipo de sistemas. Excelente artículo.

  2. Antonio Chulvi says

    Me parece un artículo muy interesante dada la gran cantidad de instalaciones con redes ethernet que hoy en día ofrecen acceso vía internet.

    Supongo que este mismo planteamiento será válido para otras marcas de plc. ¿Es así?