Protocolo S7Comm: analizamos su seguridad

Techpapers

El protocolo S7 Communication (en adelante S7Comm), es un protocolo propietario de Siemens que aparece por primera vez en 1994 con el lanzamiento de los productos Simatic S7 como fueron S7-200, S7-300 y S7-400, aunque actualmente está integrado por todos los dispositivos CPU SIMATIC S7 y C7 y es independiente del bus utilizado, pues este protocolo se puede utilizar tanto a través de Industrial Ethernet, como a través de otras capas físicas o de red como sobre RS-485 para MPI (Multi-Point-Interface) o Profibus [1].

Este protocolo se utiliza principalmente para intercambio de datos, así como para el acceso desde otros dispositivos como HMI o SCADA.

 

Al ser este un protocolo propietario, no existe mucha información disponible acerca del mismo de forma pública, aunque sí existen diversos proyectos que pueden ayudar a su comprensión como por ejemplo Snap7 [2], que es una librería de código abierto que puede ser utilizada para interactuar con los productos S7 de Siemens e incluye una amplia documentación técnica sobre el funcionamiento de este protocolo.

Otro gran proyecto de código abierto que incluye información sobre este protocolo S7 es PLC4X [3], que incluye un set de librerías para implementar comunicación entre PLCs con distintos protocolos industriales a través de su API y entre los cuales se encuentra S7. 

Cuando hablamos del protocolo S7Comm, realmente podríamos referirnos tanto a S7Comm como a su versión más reciente, S7Comm Plus, de la cual existe muy poca información e incluye, como novedad, una capa de cifrado. A lo largo de este artículo, hablaremos únicamente del protocolo S7Comm, que es el utilizado principalmente para las conexiones entre los PLCs y estaciones de PC.

Figura 1. Profinet vs S7Comm Plus vs S7 Comm

 

Descripción técnica

Generalmente, la comunicación diseñada por Siemens sigue el modelo tradicional de maestro-esclavo (o cliente-servidor)

donde un PC maestro (o cliente) envía solicitudes S7 al dispositivo PLC esclavo (o servidor).

La implementación del protocolo S7 sobre TCP/IP está basada en el servicio de transporte ISO orientado a bloques.

Este protocolo está encapsulado en los protocolos TPKT e ISO-COTP, lo que permite transferir la PDU (Protocol Data Unit) a través de TCP, utilizando por defecto el puerto TCP/102 para las comunicaciones.

Cada uno de los bloques de datos que se transmiten son los llamados PDUs y cuya longitud se negocia durante la configuración de la conexión.

El protocolo está orientado al envío de funciones y/o comandos, lo que significa que generalmente la transmisión consta de una solicitud S7 y una respuesta a dicha solicitud. Cada uno de estos comandos constan de los siguientes campos, siendo los dos últimos opcionales:

  • Cabecera
  • Conjunto de parámetros (y datos de parámetros)
  • Datos

Para comprender mejor el encapsulado de S7 se puede ver en la siguiente imagen cómo este se encapsula en primer lugar en ISO sobre TCP y posteriormente en TCP/IP:

Figura 2. Encapsulado de protocolos

 

Cabecera: contiene información de longitud e identificación de la PDU, y constante del tipo de mensaje.

Estas cabeceras tienen una longitud de entre 10 y 12 bytes; los mensajes de ACK contienen dos bytes adicionales de código de error. A parte de esto, el formato de la cabecera es siempre el mismo en todas las PDUs.

Figura 3. Cabecera PDU S7

 

Protocol ID: Identificador del protocolo. Es constante, siempre será 0x32.

Message Type: Tipo del mensaje; a veces es referido como ROSCTR (Remote Operating Service Control) 0x01-Job Request: Solicitud enviada por el máster (por ejemplo, read/write memory, read/write blocks, start/stop device, setup communication).

  • 0x02-Ack: ACK simple enviado por el esclavo sin campo de datos.
  • 0x03-Ack-Data: ACK con campo de datos opcional, contiene la respuesta a una job request.
  • 0x07-Userdata: Una extensión del protocolo original; el campo de parámetro contiene el ID de solicitud/respuesta. Se utiliza para, por ejemplo, tareas de programación o debugging, SZL reads, funciones de seguridad, configuraciones de tiempo, lecturas cíclicas, etc.)

Reserved: Siempre es 0x0000 (ignorado).

PDU reference: Generado por el máster; se incrementa en cada nueva transmisión y es utilizado para unir las respuestas con sus solicitudes, es decir, para la trazabilidad de las tramas, Little-Endian.

Parameter length: El tamaño del campo parámetro, Big Endian.

Data length: El tamaño del campo datos, Big-Endian.

Error class: Únicamente presente en los mensajes Ack-Data.

Error Code: Únicamente presente en los mensajes Ack-Data.

Parámetros y datos: El encabezado del parámetro es específico del tipo mensaje y para los mensajes Job y Ack Data comenzará con un código de función (function code). La estructura del resto de los campos depende de este valor. Este código de función determina la finalidad del mensaje y sirve de base los intercambios de mensajes que tendrán lugar.

Funciones

Setup Communication

Figura 4. Cabecera Setup Comm SEQ

 

Antes de poder intercambiar cualquier mensaje, cliente y servidor (máster y esclavo) se intercambian el par de mensajes Job y ACK Data al principio de cada sesión. Su función es negociar el tamaño de la cola ACK y la longitud máxima de la PDU. La longitud de la cola ACK determina el número de Jobs paralelos que pueden iniciarse simultáneamente sin confirmación. Tanto los campos de longitud de cola ACK como de PDU son Big Endian.

Read/Write Variable [0x04/0x05]

El protocolo S7 soporta múltiples queries de lectura/escritura de variables en un solo mensaje con diferentes modos de direccionamiento. Hay tres modos principales:

Any-type: Este es el modo de direccionamiento por defecto y se utiliza para hacer queries de variables arbitrarias. Los tres parámetros (área, dirección, tipo) se especifican para cada variable direccionada.

Db-type: Este es un modo especial diseñado para direccionar variables de Base de Datos. Es más compacto que el direccionamiento any-type.

Symbolic-addressing: Este modo es utilizado por los dispositivos de la serie S7-1200/1500 y permite el direccionamiento de ciertas variables con sus nombres simbólicos predefinidos. Este modo es poco frecuente.

Block Upload/Download [0x1a-1f]

En los dispositivos Siemens, el código del programa y la mayoría de los datos del programa se almacenan en bloques. Estos bloques tienen su propio encabezado y formato de codificación, que se pueden consultar con más detalle en la documentación oficial de Siemens. [4]

La secuencia de intercambio de mensajes puede ser de tipo upload block o download block. La diferencia principal entre ambas es que en download block, la dirección de la comunicación cambia y “el esclavo se convierte en el maestro”, es decir, es el esclavo el que envía los datos al máster.

 

Figura 5. Secuencia upload block.

 

Figura 6. Secuencia download block.

 

PLC Control [0x28]

Los mensajes de PLC Control se utilizan para ejecutar diferentes rutinas en el dispositivo esclavo que modifican su estado de ejecución/memoria. Estos comandos se utilizan para iniciar o detener la ejecución del programa de control del PLC, activar o eliminar bloques de programa en el dispositivo o guardar su configuración en la memoria persistente.

 

PLC Stop [0x29]

El mensaje de PLC Stop es esencialmente el mismo que el mensaje de control del PLC con la diferencia de que el mensaje no tiene ningún parámetro y la parte de la rutina siempre está establecida como P_PROGRAM.

MSG Type – Userdata [5]

En los casos en los que el campo tipo de mensage es 0x07-Userdata, el formato de la trama que contiene el campo parámetro y campo datos cambia respecto a los casos en los que se envía una Job request o un Ack data. Los campos son los siguientes:

Parámetros:

  • Parameter Head
    • Parameter length: longitud del campo parámetros 
    • Method: Request/Response(0x11/0x12)
    • Type: Request (4)/Response(8)
    • Function Group:
      • Programmer commands
      • Cyclic data 
      • Block functions
      • CPU functions 
      • Security 
      • Time functions
    • Subfunction: dependen del valor del campo Function Group”; para el caso de CPU Functions:
      • Read SZL
      • Message service 
      • Transition to stop 
      • Alarm was acknowledged in HMI/SCADA 1
      • Alarm was acknowledged in HMI/SCADA 2
      • PLC is indicating a ALARM message 
      • HMI/SCADA initiating ALARM subscription
  • Sequence number
  • Data unit reference number: (solo para Response)
  • Last data unit: (solo para Response) 
  • Yes (0x00)
  • No (0x01)
  • Error code: (solo para Response)
  • Datos
  • Return code:
  • 0x00 – Reserved 
  • 0x01 – Hardware fault 
  • 0x03 – Accessing the object not allowed 
  • 0x05 – Address out of range 
  • 0x06 – Data type not supported 
  • 0x07 – Data type inconsistent 
  • 0x0a – Object does not exist 
  • 0xff – Success
  • Transport size: 
    • 0x00 – NULL 
    • 0x03 – BIT 
    • 0x04 – BYTE/WORD/DWORD 
    • 0x05 – INTEGER 
    • 0x07 – REAL 
    • 0x09 – OCTET STRING
  • Length
  • SZL-ID
  • SZL-Index: Con ciertas listas parciales o extractos de listas parciales se debe especificar un ID de tipo de objeto o un número de objeto.
  • Length of a data record of the partial list in bytes: (solo para Response)
  • Number of data records contained in the partial list: (solo para Response)

SZL-ID

Las SZL o SSL (System Status List) son listas que describen el estado actual de un PLC, cuyo contenido se puede leer, pero no se puede modificar.

Estas listas son listas virtuales que se crean por el sistema operativo de la CPU cuando se les solicita [5]. La información que se puede extraer a través de estas SSL es la siguiente:

  • Datos del sistema 
    • Configuración de CPU
    • Estado de clases de prioridad
    • Comunicación
  • Datos de estado de los módulos de la CPU
  • Datos de diagnóstico de los módulos
  • Búfer de diagnóstico

Analizando los campos contenidos dentro de los SZL, encontramos lo siguiente:

Figura 7. Campos SZL-ID

 

Formado por tres campos principales:

  • Module class (4 bits)

  • Number of the partial list extract (4 bits): El número de extractos de lista parcial y su significado dependen de la lista de estado del sistema particular a la que pertenecen. Con el número del extracto de lista parcial, se especifica qué subconjunto de una lista parcial se desea leer.
  • Number of the partial list (8 bits): Usando el número de la lista parcial, especifica qué lista parcial de la lista de estado del sistema se desea leer.
  • SZL-Index: Con ciertas listas parciales o extractos de listas parciales se debe especificar un ID de tipo de objeto o un número de objeto.

o Length of a data record of the partial list in bytes: (solo para Response)

o Number of data records contained in the partial list: (solo para Response)

 

Análisis de tráfico

Para comprender los riesgos que supone el uso de este protocolo cuando no se acompaña de una capa adicional de seguridad, se analiza a continuación una muestra de tráfico S7 mostrando algunos de los tipos de información que se puede llegar a obtener. Para ello, se ha recurrido al repositorio de Wireshark [6] para analizar uno de los .pcaps existentes, s7comm_reading_plc_status.pcap: Connecting and viewing the S7-300 PLC status

Observando los paquetes en el fichero desde Wireshark, se puede comprobar que se trata de una comunicación entre dos dispositivos en la cual, El dispositivo ASUSTekC, con dirección IP 192.168.1.10 inicia la comunicación con el dispositivo Siemens que tiene como dirección IP 192.168.1.40.

Figura 8. Captura de tráfico.

 

Tal y como se puede comprobar en la Figura 8, paquetes 10 y 11, lo primero que se hace antes de intercambiar mensajes a través de S7 es intercambiar el par de mensajes Job y ACK Data para establecer el tamaño de la cola ACK y la longitud máxima de la PDU. 

Figura 9. Job Request (máster-ASUSTekC)

 

Figura 10. ACK Data (esclavo-Siemens)

 

Se puede comprobar en las imágenes anteriores los parámetros descritos anteriormente para la función Setup Communication, como el Protocol ID=0x32, y las funciones Job (0x01) y Ack_Data (0x03).

Tras el establecimiento de la conexión, se empiezan a intercambiar funciones Request – Response con un MSG Type

0x07 Userdata, a través de los cuales el cliente realiza funciones “Read SZL” o System Status List. En base a lo comentado en el capítulo anterior acerca del funcionamiento de las SSL (o SZL), se puede deducir qué operaciones se están realizando en la captura seleccionada y extraer información de la misma. Además, el propio Wireshark identifica qué operación se corresponde con ca una de las SSL-ID:

En el paquete 17 (Figura 8), el cliente envía un SZL-ID (SSL-ID)=0x0000, por lo que se obtienen todos los IDs de las listas que dispone el PLC:

SZL-ID: 0x0000, Diagnostic type: CPU, Number of the partial list extract: All SZL partial lists of the module, Number of the partial list: List of all the SZL-IDs of a module.

A continuación, se puede ver una muestra de las listas que devuelve el servidor:

Figura 11. SZL-IDs (SSL-IDs) disponibles en el esclavo.

 

A partir de aquí se puede extraer información importante como se puede comprobar a continuación; tras realizar la anterior consulta de todos los SSL-IDs existentes, uno de ellos es el SSL-ID=0x111, que se corresponde con Diagnostic type: CPU, Number of the partial list extract: A single identification data record, Number of the partial list: Module identification.

Figura 12. ZL-ID=0x111.

 

Figura 13. Solicitud información del módulo del esclavo.

 

Figura 14. Información del módulo devuelta por el esclavo.

 

Tal y como se puede comprobar en las dos figuras anteriores, el esclavo devuelve información del hardware: 6ES7151-8AB01-0AB0. Si se realiza una búsqueda rápida en Google, se puede extraer qué dispositivo concreto es el que se está comunicando, pues además devuelve el valor de la versión del OS (3). Según la búsqueda, el dispositivo involucrado es el siguiente: SIMATIC DP, IM151-8 PN/DP CPU para ET 200S, Memoria de trabajo de 192 KB, interfaz PROFINET int. (con tres puertos RJ45) como controlador IO, sin batería Se necesita MMC. [7]

Se puede comprobar en la Figura 16 que efectivamente el nombre del módulo es IM151-8 PN/DP CPU. 

Figura 15. Versión de firmware.

 

Figura 16. Nombre del módulo.

 

Figura 17. Número de serie, módulo y tarjeta de memoria.

 

También se hace una lectura del estado de los LEDs del sistema:

Figura 18. Estado LEDs.

 

Además, se han podido leer los relojes internos del sistema:

Figura 19. Reloj interno.

 

Se puede incluso leer un extracto de los logs de diagnóstico del dispositivo:

Figura 20. Logs de diagnóstico.

 

Además, como se puede comprobar en la Figura 20, a través del SZL-ID=0x00a0 se puede incluso extraer las entradas existentes en el búfer de diagnóstico y leer cada una de ellas; en este caso concreto, se puede ver que un 20 de agosto 2014 a las 11:53, se generó un evento “Mode transition from STARTUP to RUN”. En la figura siguiente se incluyen más eventos existentes en el búfer:

Figura 21. Logs de diagnóstico.

 

Conclusiones

Aunque la última versión del protocolo S7 (S7 Comm Plus) dispone de mecanismos de cifrado y autenticación,

su uso todavía no está muy extendido y es habitual encontrarse todavía el protocolo S7-ISOonTCP. (S7 que ha sido objeto de análisis en este artículo).

Tal y como se pudo comprobar en el análisis de la captura, la información intercambiada entre máster y esclavo está en texto plano por lo que se puede capturar toda la información que se envíe entre ambos.

Este protocolo, al no disponer de autenticación, permite que un atacante que tenga acceso a la red en la que se encuentren el máster y el esclavo (PC y PLC), pueda estar esnifando tráfico de la red obteniendo información de valor de dicho PLC de forma que, una vez identificada la dirección IP de este y el modelo y/o versión de firmware, se pueda realizar una búsqueda de vulnerabilidades que puedan afectar a este dispositivo.

Además, los dispositivos de Siemens por defecto utilizan el puerto tcp 102 para ejecutar sus servicios, por lo que además se podría utilizar una consulta con nmap dirigida únicamente a los puertos 102 de toda una red para obtener información de los dispositivos que se puedan encontrar detrás de este puerto.

Referencias

[1] https://support.industry.siemens.com/cs/document/26483647/what-properties-advantages-and-special-features-does-the-s7-protocoloffer-?dti=0&lc=en-WW

[2] http://snap7.sourceforge.net/

[3] https://plc4x.incubator.apache.org/protocols/s7/index.html

[4] https://support.industry.siemens.com/cs/document/45531107/simatic-programming-with-step-7-v5-5?dti=0&lc=en-WW

[5] System Software for S7-300/400 System and Standard Functions Volume ½, https://readthedocs.web.cern.ch/download/attachments/21177680/SIEMENS%20S7%20-%20SZL%20addresses%20guide.pdf?version=1&modificationDate=1403874207000&api=v2

[6] https://wiki.wireshark.org/SampleCaptures#s7comm-s7-communication

[7] https://mall.industry.siemens.com/mall/es/es/Catalog/Product/6ES7151-8AB01-0AB0

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Rellena este campo
Rellena este campo
Por favor, introduce una dirección de correo electrónico válida.
Tienes que aprobar los términos para continuar

keyboard_arrow_up