Industrial Control System protocols
Industrial Control Systems (ICS) are made up of various assets/components connected by an industrial control network. ICS networks are similar to typical business networks. Both are mainly Ethernet-based and rely on wired/wireless connectivity. However, legacy serial connectivity (RS-232/422/485) is still used in industrial communication. Architecturally, industrial networks are more complex. They are mainly organized in three to four hierarchical levels, such as:
-
Field level
-
Process level
-
Control level
-
Supervision level
Each level has its own set of communication protocols and communication media.
High availability is a critical requirement for industrial control networks. Industrial applications often operate in real-time mode that depends on deterministic communication with precise timing requirements. A network failure can negatively affect industrial control processes, resulting in potentially dangerous consequences, such as material or human loss. Thus bandwidth and latency are critical in ICS networks. For this reason, network performance is considered more important than data integrity and confidentiality, making these networks more vulnerable and prone to attacks. Consequently, ICS networks need to be constantly monitored in order to detect potential compromises in a timely manner. Countermeasures to avoid disruption to the network or a data breach are only effective when such early detection mechanisms are in place.
NXLog is a small-footprint log collection agent with minimal system requirements. It can collect and parse network traffic by capturing packets from a network interface or processing captured packet data from a file. In conjunction with a System Information and Event Management (SIEM) solution, it can help detect, analyze, or even prevent potentially malicious activity on your network. This guide covers various ICS protocols commonly used by industrial systems and how to process network packets with NXLog.
Modbus
In 1979 Modicon created the Modbus protocol to enable communication between industrial devices. It remains one of the most popular protocols used in ICS architectures. Due to its simplicity and efficiency, it has become the de facto standard for the automation industry. Modbus is an application layer messaging protocol for client/server communication positioned at level 7 of the OSI model. This allows Modbus to be easily adapted to different types of buses or network architectures.
The most common Modbus implementations are:
- Modbus ASCII
-
Messages are coded in hexadecimal, using 4-bit ASCII characters. It is the slowest Modbus implementation, used mostly for wireless communication, like radio or telephone modems that allow long time intervals between characters without causing errors.
- Modbus RTU
-
Modbus standard for asynchronous serial transmission mostly over RS-232, RS-422, or RS-485
- Modbus Plus
-
A high-speed, token-passing network
- Modbus RTU over TCP
-
The original Modbus RTU ADU is applied to the Modbus Application Protocol (MBAP) header to create a new frame, including all original error checking and addressing information.
- Modbus TCP
-
Modbus over Ethernet using the TCP/IP standard. Data is encapsulated inside a TCP/IP packet. This more common implementation removes the legacy address and error checking while placing the Modbus PDU together with an MBAP header into a new frame.
Security concerns
- Authentication
-
Modbus doesn’t support verification, enabling cyberattacks such as man-in-the-middle (MitM) and replay-style attacks. Attackers can distort the Modbus PDU by analyzing the network or device configuration. Additionally, Modbus supports specific function codes (e.g., function code 43) that can be used without specific knowledge about the target.
- Encryption
-
The lack of encryption in Modbus makes it possible for attackers to capture, spoof, or replay packets.
- Message checksum (Modbus/TCP only)
-
Since the checksum is generated at the transmission level and not the application layer, a command within the Modbus TCP ADU can easily be distorted.
Configuration example
This configuration uses the im_pcap module to capture only Modbus packets from the network interface specified below. Captured messages are then converted to JSON.
<Extension json>
Module xm_json (1)
</Extension>
<Input pcap>
Module im_pcap
# Name of a network device/interface
Dev \Device\NPF_{E8451A5D-5676-4BEF-8ED5-68911C97D953} (2)
<Protocol> (3)
# Protocol type
Type modbus
</Protocol>
# Conversion to JSON
Exec to_json(); (4)
</Input>
1 | Load the xm_json module by creating an instance of it. |
2 | Use the Dev directive of the im_pcap module for specifying the network interface. |
3 | Create a Protocol group and use the Type directive to specify which protocol im_pcap should be capturing. |
4 | The Exec directive is required for single statements. In this case, it facilitates calling the to_json() procedure for converting the captured messages to JSON. |
{
"modbus.function_code": "Read Holding Registers (03)",
"modbus.length": "6",
"modbus.prot_id": "0",
"modbus.query.read_holding_regs.qty_of_regs": "3",
"modbus.query.read_holding_regs.starting_address": "0",
"modbus.trans_id": "844",
"modbus.unit_id": "1",
"EventTime": "2022-04-30T02:34:08.606328-07:00",
"EventReceivedTime": "2022-04-30T02:34:09.241839-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"modbus.function_code": "Read Holding Registers (03)",
"modbus.length": "9",
"modbus.prot_id": "0",
"modbus.response.read_holding_regs.byte_count": "6",
"modbus.response.read_holding_regs.registers": "3260, 2937, 3152",
"modbus.trans_id": "844",
"modbus.unit_id": "1",
"EventTime": "2022-04-30T02:34:08.623539-07:00",
"EventReceivedTime": "2022-04-30T02:34:09.241839-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
PROFINET
PROFINET is an open Ethernet-based communication standard of PROFIBUS & PROFINET International (PI) for automation and cross-vendor communication. It uses TCP/IP and IT standards, and provides seamless integration of field bus systems. PROFINET is widely used by major industrial equipment manufacturers such as Siemens, Phoenix Contact, and General Electric.
PROFINET describes the overall data exchange, including parameterization and diagnostic data between PROFINET controllers and PROFINET devices. It follows the provider/consumer model for data exchange since all Ethernet devices operate with equal rights on the network. The PROFINET controller and PROFINET device can send cyclic data independently.
- PROFINET Controller
-
Typically a PLC (Programmable Logic Controller) performing automation tasks. It addresses connected PROFINET devices, exchanges the IO data between the assigned field devices, and receives alarms from IO devices. It also initiates device identification, establishes the connection, and performs parameterization of the respective devices. The PROFINET controller provides the output data for connected devices and acts as a consumer of input data.
- PROFINET Device
-
A distributed field device (e.g., remote IO, drive, switch) assigned to and controlled by one or more PROFINET controllers. It consists of multiple modules that transmit process data, configuration data, and alarms. A PROFINET device provides input data and is the consumer of output data from the PROFINET controller.
- PROFINET Supervisor
-
An engineering tool for the configuration and diagnostics of PROFINET devices. The PROFINET supervisor, a programming device, personal computer, or human-machine interface, has access to all process and parameterization data in parallel with the PROFINET controller and is used temporarily for commissioning or troubleshooting.
Security concerns
- Port stealing
-
Consider a control system consisting of a PROFINET IO-Controller and several PROFINET IO-Devices networked in a star topology with a network switch. The network switch determines what device is connected to the hardware port using a lookup table. The lookup table is automatically updated when new devices are connected.
An attacker with access to the local network can change the lookup table by sending Ethernet-based packets with the same source MAC address as one of the IO-Devices. The network switch, in this case, sends all traffic destined to the IO-Device to the attacker’s port. To prevent the lookup table from recovering, if an IO-Device can send packets back to the IO-Controller, an attacker can send port stealing packets more frequently than the mentioned IO-Devices can. Meanwhile, the attacker can send packets directly to the IO-Device.
- Reconfiguration using DCP
-
PROFINET uses PROFINET names to identify PROFINET devices instead of IP addresses. An engineering tool assigns a name to every IO-Device during the engineering phase using the DCP protocol. An attacker can reconfigure each device without any authentication. Several options are available, such as changing the IP address or the PROFINET name. Changing the PROFINET name of an IO-Device terminates the connection with the IO-Controller.
Configuration example
This configuration uses the im_pcap module to dissect PROFINET network packets, namely the pn_dcp
, pn_mrp
, and pn_io
protocols.
Captured messages are then converted to JSON.
<Extension _json>
Module xm_json (1)
</Extension>
<Input pcap>
Module im_pcap
# Path to the file with capture packet data
File C:\...\example.pcap (2)
# Protocol type
<Protocol> (3)
Type pn_dcp
</Protocol>
<Protocol> (4)
Type pn_mrp
</Protocol>
<Protocol> (5)
Type pn_io
</Protocol>
# Conversion to JSON
Exec to_json(); (6)
</Input>
1 | Load the xm_json module by creating an instance of it. |
2 | The File directive specifies the path to the file containing the captured network traffic. |
3 | Create an im_pcap Protocol group and set the Type directive to capture pn_dcp packets. |
4 | Create an im_pcap Protocol group and set the Type directive to capture pn_mrp packets. |
5 | Create an im_pcap Protocol group and set the Type directive to capture pn_io packets. |
6 | The Exec directive is required for single statements. In this case, it facilitates calling the to_json() procedure for converting the captured messages to JSON. |
{
"pn_dcp.blocks": [
{
"option": "dev-properties",
"block_info": 0,
"suboption": "station-name",
"name_of_station": "ilc-131-eth1"
},
{
"option": "dev-properties",
"block_info": 0,
"suboption": "dev-options",
"types": [
{
"option": "dev-properties",
"suboption": "manuf"
},
{
"option": "dev-properties",
"suboption": "station-name"
},
{
"option": "dev-properties",
"suboption": "dev-ven"
},
{
"option": "dev-properties",
"suboption": "dev-role"
},
{
"option": "dev-properties",
"suboption": "dev-options"
},
{
"option": "dev-properties",
"suboption": "reserved"
},
{
"option": "ip",
"suboption": "mac"
},
{
"option": "ip",
"suboption": "ip"
},
{
"option": "dhcp",
"suboption": "dhcp-client-id"
}
]
},
{
"option": "dev-properties",
"block_info": 0,
"suboption": "manuf",
"manuf": "ILC 131 ETH"
},
{
"option": "dev-properties",
"block_info": 0,
"suboption": "dev-ven",
"dev_id": 125,
"ven_id": 176
},
{
"option": "dev-properties",
"block_info": 0,
"suboption": "dev-role",
"dev_role": 256
},
{
"option": "ip",
"block_info": 1,
"suboption": "ip",
"ip": "192.168.1.101",
"subnet_mask": "255.255.255.0",
"standard_gateway": "192.168.1.10"
}
],
"pn_dcp.data_length": "96",
"pn_dcp.frame_id": "65279",
"pn_dcp.reserved16": "0",
"pn_dcp.service_id": "identify",
"pn_dcp.service_type": "response",
"pn_dcp.xid": "41878144",
"EventTime": "2022-04-30T11:52:50.477141+03:00",
"EventReceivedTime": "2022-04-30T12:52:54.474424+03:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
S7Comm
S7Comm (S7 Communication, S7 Protocol) is a proprietary Siemens protocol used for communication with SIMATIC CPUs. It supports PG/PC station interaction with Programmable Logic Controllers (PLC) and communication between SIMATIC S7 PLCs. All SIMATIC S7 CPUs support S7 communication services for data exchange regardless of the bus system, industrial Ethernet, PROFIBUS, or MPI.
S7Comm is a function-oriented protocol, which means that every telegram contains a service request or response. It supports the following communication services:
- Information services
-
Provides connection status data and information about communication partners
- Variable services
-
Provides easy access to S7 variables, such as data blocks, instance data blocks, inputs/outputs, peripheral inputs/outputs, memory bits, timers, and counters
- Buffer send/receive services
-
Permit the transfer of large data blocks up to 65534 bytes
- Block management services
-
Allows downloading, uploading, deleting, and linking blocks in the PLC program during operation, dynamic modification of program, and parameters
- Event services
-
Allows receiving PLC alarms and event messages
- Security services
-
Manages access to S7 connections and data blocks
- Server services
-
Allows a PC station to act as an S7 server providing a data block that can be read and written locally and remotely (PUT/GET)
Security concerns
Siemens is a major vendor in the field of industrial automation with over 30% of the global automation equipment market share. Due to the widespread implementation of Siemens communication protocols, it is likely that cybercriminals would target them for exploitation.
The S7Comm protocol is not encrypted or authenticated. Therefore, like most ICS protocols, S7Comm is sensitive to cyberattacks such as session hijacking, Denial of Service (DoS), spoofing, and man-in-the-middle attacks.
An attacker with access to the network can gather information about the PLC’s internal data blocks, including inputs, outputs, and internal PLC variables. This information enables an intruder to modify certain setpoints to trigger specific actions, e.g., a software regulator setpoint that controls a pressure value. Additionally, internal variables can also be altered for malicious purposes. Repetitively overwriting variables within a short period (e.g., <20 ms) may cause unexpected behavior on the PLC.
Configuration example
This configuration uses the im_pcap module to capture only S7Comm network packets from the network interface specified below. Captured messages are then converted to JSON.
<Extension _json>
Module xm_json (1)
</Extension>
<Input pcap>
Module im_pcap
# Name of a network device/interface
Dev \Device\NPF_{5CD8F91A-C041-43EE-9238-412A96B11204} (2)
<Protocol> (3)
# Protocol type
Type s7comm
</Protocol>
# Conversion to JSON
Exec to_json(); (4)
</Input>
1 | Load the xm_json module by creating an instance of it. |
2 | Use the Dev directive of the im_pcap module for specifying the network interface. |
3 | Create a Protocol group and use the Type directive to specify which protocol im_pcap should be capturing. |
4 | The Exec directive is required for single statements. In this case, it facilitates calling the to_json() procedure for converting the captured messages to JSON. |
{
"s7comm.header.data_len": "0",
"s7comm.header.function": "Read Variable",
"s7comm.header.param_len": "14",
"s7comm.header.pduref": "1147",
"s7comm.header.protid": "0x32",
"s7comm.header.reserved": "0x0000",
"s7comm.header.rosctr": "Job Request",
"s7comm.itemcount": "1",
"s7comm.read_param_array": [
{
"s7comm.item.type": "Variable specification",
"s7comm.item.length": 10,
"s7comm.item.syntax": "S7Any",
"s7comm.s7any.transp_size": "BYTE",
"s7comm.s7any.length": 880,
"s7comm.s7any.db": 2,
"s7comm.s7any.area": "Data blocks (DB)",
"s7comm.s7any.address.byte": 0,
"s7comm.s7any.address.bit": 0
}
],
"EventTime": "2022-03-18T13:23:36.666931-07:00",
"EventReceivedTime": "2022-03-18T13:23:37.334810-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"s7comm.data_item_array": [
{
"s7comm.data.return_code": "Success",
"s7comm.data.transport_size": "BYTE / WORD / DWORD",
"s7comm.data.length_bits": 7040,
"s7comm.data.octets": "002000400060008000a000c000e00100012001400160018001a001c001e002000220024002600280..."
}
],
"s7comm.header.data_len": "884",
"s7comm.header.error.class": "No error",
"s7comm.header.error.code": "No error",
"s7comm.header.function": "Read Variable",
"s7comm.header.param_len": "2",
"s7comm.header.pduref": "1147",
"s7comm.header.protid": "0x32",
"s7comm.header.reserved": "0x0000",
"s7comm.header.rosctr": "Ack Data",
"s7comm.itemcount": "1",
"EventTime": "2022-03-18T13:23:36.667225-07:00",
"EventReceivedTime": "2022-03-18T13:23:37.334810-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"s7comm.data_item_array": [
{
"s7comm.data.return_code": "Reserved",
"s7comm.data.transport_size": "BYTE / WORD / DWORD",
"s7comm.data.length_bits": 7040,
"s7comm.data.octets": "002000400060008000a000c000e00100012001400160018001a001c001e002000220024002600280..."
}
],
"s7comm.header.data_len": "884",
"s7comm.header.function": "Write Variable",
"s7comm.header.param_len": "14",
"s7comm.header.pduref": "1146",
"s7comm.header.protid": "0x32",
"s7comm.header.reserved": "0x0000",
"s7comm.header.rosctr": "Job Request",
"s7comm.itemcount": "1",
"s7comm.write_param_array": [
{
"s7comm.item.type": "Variable specification",
"s7comm.item.length": 10,
"s7comm.item.syntax": "S7Any",
"s7comm.s7any.transp_size": "BYTE",
"s7comm.s7any.length": 880,
"s7comm.s7any.db": 2,
"s7comm.s7any.area": "Data blocks (DB)",
"s7comm.s7any.address.byte": 0,
"s7comm.s7any.address.bit": 0
}
],
"EventTime": "2022-03-18T13:23:36.666123-07:00",
"EventReceivedTime": "2022-03-18T13:23:37.334810-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"s7comm.header.data_len": "1",
"s7comm.header.error.class": "No error",
"s7comm.header.error.code": "No error",
"s7comm.header.function": "Write Variable",
"s7comm.header.param_len": "2",
"s7comm.header.pduref": "1146",
"s7comm.header.protid": "0x32",
"s7comm.header.reserved": "0x0000",
"s7comm.header.rosctr": "Ack Data",
"s7comm.itemcount": "1",
"s7comm.write_result_array": [
{
"s7comm.data.return_code": "Success"
}
],
"EventTime": "2022-03-18T13:23:36.666416-07:00",
"EventReceivedTime": "2022-03-18T13:23:37.334810-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
DNP3
Distributed Network Protocol (DNP3) was originally developed by Westronic (now GE-Harris Canada) and was released for public use in 1993. It is based on the early versions of the IEC 60870-5 standard. DNP3 is a multi-point communication protocol for interaction between a control system and one or more Intelligent Electronic Devices (IED). It was initially developed for electric utilities companies but is now used in other industries as well, such oil & gas, the water/wastewater industry, etc.
DNP is based on the Enhanced Performance Architecture (EPA) model, a simplified version of the 7-layer Open System Interconnection (OSI) model. It consists of the following layers:
- Physical layer
-
Defines the operation in network environments and a collision management mechanism. Most of the DNP3 implementation is based on serial communication, such as RS-232 or RS-485. However, Ethernet is currently the most widely used medium for DNP3, allowing it to be tunneled over packet-oriented networks such as TCP/IP and UDP.
- Data link layer
-
Responsible for data reliability, including error checking and duplicate frame detection. The data link layer frame (LPDU) header and data section contain a Cycling Redundancy Check (CRC) to detect communication errors.
- Pseudo transport layer
-
Although the DNP3 protocol is based on the EPA model, the transmission of large application layer messages requires additional functionality, such as data segmentation and data reassembling. These functions constitute a Pseudo Transport layer in the DNP3 protocol model.
- Application layer
-
Responsible for performing operations on data objects defined by the device, such as reading actual values, writing new values if the object represents control points, and clearing counters. Application layer messages are broken into fragments if the message is large.
Security concerns
DNP3 focuses on data integrity and lacks authentication or encryption, making it vulnerable to man-in-the-middle (MITM) attacks and replay attacks. It also makes it possible for attackers to capture and spoof data. Authentication and encryption are only available in Secure DNP3.
Additionally, DNP3 defines static function codes and data types, allowing attackers to manipulate messages in different ways.
Configuration example
This configuration uses the im_pcap module to capture only DNP3 packets from the network interface specified below. Captured messages are then converted to JSON.
<Extension _json>
Module xm_json (1)
</Extension>
<Input pcap>
Module im_pcap
# Name of a network device/interface
Dev \Device\NPF_{B89D13DD-37BB-4799-BFCD-6C9D326C481A} (2)
<Protocol> (3)
# Protocol type
Type dnp3
</Protocol>
# Conversion to JSON
Exec to_json(); (4)
</Input>
1 | Load the xm_json module by creating an instance of it. |
2 | Use the Dev directive of the im_pcap module for specifying the network interface. |
3 | Create a Protocol group and use the Type directive to specify which protocol im_pcap should be capturing. |
4 | The Exec directive is required for single statements. In this case, it facilitates calling the to_json() procedure for converting the captured messages to JSON. |
{
"dnp3.application_layer.control.con": "0",
"dnp3.application_layer.control.fin": "1",
"dnp3.application_layer.control.fir": "1",
"dnp3.application_layer.control.sequence": "14",
"dnp3.application_layer.control.uns": "0",
"dnp3.application_layer.function_code": "Read",
"dnp3.application_layer.object0.count": "0",
"dnp3.application_layer.object0.group": "60",
"dnp3.application_layer.object0.name": "Class objects - Class 1 data",
"dnp3.application_layer.object0.variation": "2",
"dnp3.application_layer.object1.count": "0",
"dnp3.application_layer.object1.group": "60",
"dnp3.application_layer.object1.name": "Class objects - Class 2 data",
"dnp3.application_layer.object1.variation": "3",
"dnp3.application_layer.object2.count": "0",
"dnp3.application_layer.object2.group": "60",
"dnp3.application_layer.object2.name": "Class objects - Class 3 data",
"dnp3.application_layer.object2.variation": "4",
"dnp3.data_layer.control": "0xC4",
"dnp3.data_layer.control.dir": "1",
"dnp3.data_layer.control.fcb": "0",
"dnp3.data_layer.control.fcv": "0",
"dnp3.data_layer.control.function_code": "Unconfirmed User Data",
"dnp3.data_layer.control.prm": "1",
"dnp3.data_layer.destination": "4",
"dnp3.data_layer.length": "17",
"dnp3.data_layer.source": "3",
"dnp3.data_layer.start_bytes": "0x0564",
"dnp3.transport.fin": "1",
"dnp3.transport.fir": "1",
"dnp3.transport.sequence": "6",
"EventTime": "2022-04-10T02:08:56.986131-07:00",
"EventReceivedTime": "2022-04-10T02:08:57.210239-07:00",
"SourceModuleName": "pcap_dnp3",
"SourceModuleType": "im_pcap"
}
{
"dnp3.application_layer.control.con": "0",
"dnp3.application_layer.control.fin": "1",
"dnp3.application_layer.control.fir": "1",
"dnp3.application_layer.control.sequence": "14",
"dnp3.application_layer.control.uns": "0",
"dnp3.application_layer.function_code": "Response",
"dnp3.application_layer.internal_indications.already_executing": "0",
"dnp3.application_layer.internal_indications.broadcast": "0",
"dnp3.application_layer.internal_indications.class1_events": "0",
"dnp3.application_layer.internal_indications.class2_events": "0",
"dnp3.application_layer.internal_indications.class3_events": "0",
"dnp3.application_layer.internal_indications.config_corrupt": "0",
"dnp3.application_layer.internal_indications.device_restart": "0",
"dnp3.application_layer.internal_indications.device_trouble": "0",
"dnp3.application_layer.internal_indications.events_buffer_overflow": "0",
"dnp3.application_layer.internal_indications.local_control": "0",
"dnp3.application_layer.internal_indications.need_time": "0",
"dnp3.application_layer.internal_indications.no_func_code_support": "0",
"dnp3.application_layer.internal_indications.object_unknown": "0",
"dnp3.application_layer.internal_indications.parameter_error": "0",
"dnp3.application_layer.internal_indications.reserved": "0 (expected 0)",
"dnp3.data_layer.control": "0x44",
"dnp3.data_layer.control.dir": "0",
"dnp3.data_layer.control.fcb": "0",
"dnp3.data_layer.control.fcv": "0",
"dnp3.data_layer.control.function_code": "Unconfirmed User Data",
"dnp3.data_layer.control.prm": "1",
"dnp3.data_layer.destination": "3",
"dnp3.data_layer.length": "10",
"dnp3.data_layer.source": "4",
"dnp3.data_layer.start_bytes": "0x0564",
"dnp3.transport.fin": "1",
"dnp3.transport.fir": "1",
"dnp3.transport.sequence": "11",
"EventTime": "2022-04-10T02:08:56.986861-07:00",
"EventReceivedTime": "2022-04-10T02:08:57.210239-07:00",
"SourceModuleName": "pcap_dnp3",
"SourceModuleType": "im_pcap"
}
{
"dnp3.application_layer.control.con": "1",
"dnp3.application_layer.control.fin": "1",
"dnp3.application_layer.control.fir": "1",
"dnp3.application_layer.control.sequence": "7",
"dnp3.application_layer.control.uns": "1",
"dnp3.application_layer.function_code": "Unsolicited Response",
"dnp3.application_layer.internal_indications.already_executing": "0",
"dnp3.application_layer.internal_indications.broadcast": "0",
"dnp3.application_layer.internal_indications.class1_events": "0",
"dnp3.application_layer.internal_indications.class2_events": "0",
"dnp3.application_layer.internal_indications.class3_events": "0",
"dnp3.application_layer.internal_indications.config_corrupt": "0",
"dnp3.application_layer.internal_indications.device_restart": "0",
"dnp3.application_layer.internal_indications.device_trouble": "0",
"dnp3.application_layer.internal_indications.events_buffer_overflow": "0",
"dnp3.application_layer.internal_indications.local_control": "0",
"dnp3.application_layer.internal_indications.need_time": "0",
"dnp3.application_layer.internal_indications.no_func_code_support": "0",
"dnp3.application_layer.internal_indications.object_unknown": "0",
"dnp3.application_layer.internal_indications.parameter_error": "0",
"dnp3.application_layer.internal_indications.reserved": "0 (expected 0)",
"dnp3.application_layer.object0.count": "1",
"dnp3.application_layer.object0.group": "32",
"dnp3.application_layer.object0.name": "Analog input event - single-precision, floating-point with time",
"dnp3.application_layer.object0.point0.flags": "[ONLINE]",
"dnp3.application_layer.object0.point0.index": "1",
"dnp3.application_layer.object0.point0.time_of_occurance": "1649592492",
"dnp3.application_layer.object0.point0.value": "11876.329102",
"dnp3.application_layer.object0.range": "2-octet count of objects",
"dnp3.application_layer.object0.variation": "7",
"dnp3.data_layer.control": "0x44",
"dnp3.data_layer.control.dir": "0",
"dnp3.data_layer.control.fcb": "0",
"dnp3.data_layer.control.fcv": "0",
"dnp3.data_layer.control.function_code": "Unconfirmed User Data",
"dnp3.data_layer.control.prm": "1",
"dnp3.data_layer.destination": "3",
"dnp3.data_layer.length": "28",
"dnp3.data_layer.source": "4",
"dnp3.data_layer.start_bytes": "0x0564",
"dnp3.transport.fin": "1",
"dnp3.transport.fir": "1",
"dnp3.transport.sequence": "12",
"EventTime": "2022-04-10T02:08:57.076909-07:00",
"EventReceivedTime": "2022-04-10T02:08:57.210239-07:00",
"SourceModuleName": "pcap_dnp3",
"SourceModuleType": "im_pcap"
}
IEC 60870-5-104
IEC 60870-5-104 (IEC104) is a communication standard for telecontrol in electrical engineering and power system automation applications. It is also widely used in water/wastewater and oil & gas applications. IEC 60870-5-104 defines a communication profile for data transmission in TCP/IP-based networks for monitoring and controlling geographically distributed processes.
The IEC 60870-5-104 protocol combines the application layer of IEC 60870-5-101 and TCP/IP transport functions. IEC 60870-5-101 is a companion standard that defines a complete communication protocol using all options described in sections 1-5 of the IEC 60870-5 standard.
The standard IEC 60870-5 (Telecontrol equipment and systems. Part 5: Transmission protocols) is a series of standards developed by the International Electrotechnical Commission for telemetry control and data acquisition in the electrical and related industries. It is based on the three-layer Enhanced Performance Architecture (EPA) model and consists of the following layers:
- Physical layer
-
Defines a communication interface (RS-232/485, Ethernet) specification for the IEC 60870-5-101/IEC 60870-5-104 standards and network configuration (point-to-point, multiple point-to-point, multi-point star, multi-party line, and multi-point-ring)
- Data link layer
-
Specifies frame formats, order of information, and transmission procedures
- Application layer
-
Defines the overall message structure and a structure of its different internal parts (Application Service Data Unit (ASDU), message addressing and routing, information objects, set of ASDUs)
Security concerns
IEC 60870-5-104 does not specify any security mechanisms, such as access passwords, authentication, or encryption, which makes it extremely vulnerable, especially when transmitted over an unsecured IP layer. Possible attacks on IEC 60870-5-104 communications may include:
-
Changing the value of an ASDU transmitted in the IEC 104 packet
-
Inserting spoofed ASDU messages into the network
-
DDoS attacks on IEC 104 master or slave stations
-
Inserting a rogue control station into the network
-
Interception of the transmitted data
Passive monitoring for anomalies and prompt action can reduce the impact of such attacks.
Configuration example
This configuration uses the im_pcap module to capture only IEC 60870-5-104 packets, namely the iec104apci
and iec104asdu
protocols from the network interface specified below.
Captured messages are then converted to JSON.
<Extension _json>
Module xm_json (1)
</Extension>
<Input pcap>
Module im_pcap
# Name of a network device/interface
Dev \Device\NPF_{E8451A5D-5676-4BEF-8ED5-68911C97D953} (2)
<Protocol> (3)
# Protocol types
Type iec104apci
</Protocol>
<Protocol> (4)
Type iec104asdu
</Protocol>
# Conversion to JSON
Exec to_json(); (5)
</Input>
1 | Load the xm_json module by creating an instance of it. |
2 | Use the Dev directive of the im_pcap module for specifying the network interface. |
3 | Create an im_pcap Protocol group and set the Type directive to iec104apci for capturing IEC 104 packets using the APCI format. |
4 | Create an im_pcap Protocol group and set the Type directive to iec104asdu for capturing IEC 104 packets using the ASDU format. |
5 | The Exec directive is required for single statements. In this case, it facilitates calling the to_json() procedure for converting the captured messages to JSON. |
{
"iec104.apci.receive_sequence_number": "24589",
"iec104.apci.send_sequence_number": "12552",
"iec104.apci.type": "Information (I)",
"iec104.asdu.data": {
"io": [
{
"ioa": 1020
}
],
"ios": 1
},
"iec104.asdu.dui.cause_of_transmission": "Request or requested (5)",
"iec104.asdu.dui.coa": "1",
"iec104.asdu.dui.num_records": "1",
"iec104.asdu.dui.org": "0",
"iec104.asdu.dui.pn": "0",
"iec104.asdu.dui.sq": "FALSE",
"iec104.asdu.dui.test_bit": "0",
"iec104.asdu.dui.type": "C_RD_NA_1",
"EventTime": "2022-04-19T13:07:54.073324-07:00",
"EventReceivedTime": "2022-04-19T13:07:54.886786-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"iec104.apci.receive_sequence_number": "12553",
"iec104.apci.send_sequence_number": "24589",
"iec104.apci.type": "Information (I)",
"iec104.asdu.data": {
"io": [
{
"ioa": 1020,
"ie": [
{
"type": "R32",
"value": 10243
},
{
"type": "QDS",
"invalid": false,
"not-topical": false,
"substituted": false,
"blocked": false,
"overflow": false
},
{
"type": "CP56Time2A",
"milliseconds": 54006,
"minutes": 7,
"hours": 13,
"day-of-week": 0,
"day-of-month": 19,
"month": 7,
"year": 21
}
],
"ies": 3
}
],
"ios": 1
},
"iec104.asdu.dui.cause_of_transmission": "Request or requested (5)",
"iec104.asdu.dui.coa": "1",
"iec104.asdu.dui.num_records": "1",
"iec104.asdu.dui.org": "0",
"iec104.asdu.dui.pn": "0",
"iec104.asdu.dui.sq": "FALSE",
"iec104.asdu.dui.test_bit": "0",
"iec104.asdu.dui.type": "M_ME_TF_1",
"EventTime": "2022-04-19T13:07:54.078755-07:00",
"EventReceivedTime": "2022-04-19T13:07:54.887761-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
IEC 61850
IEC 61850 is an international communication standard for industrial control systems used mainly in the power industry. The main focus of the standard is on the interaction between vendor-independent components such as IEDs (Intelligent Electronic Device) used in electrical substations.
IEC 61850 defines the object-oriented data model for IEDs, associated services, and communication interfaces used for data transfer. The object-oriented data model relies on abstract objects (logical nodes, data objects) accessed via the Abstract Communication Service Interface (ACSI). All data and services are mapped to various protocols, each having different functions:
- Manufacturing Message Specification (MMS)
-
Used for client-server communication between IEDs and higher-level devices (SCADA, gateway) over Ethernet. It supports complex naming and services and is perfectly suitable for IEC 61850.
- Generic Object-Oriented Substation Event (GOOSE)
-
Implements the transfer of time-critical events between IEDs over an IEEE 802.3 network. GOOSE messages are mapped directly to the data link layer of the OSI model and transmitted as multicast messages across the LAN. The GOOSE protocol employs a publish–subscribe messaging pattern, where one IED (publisher) is responsible for creating messages delivered to a group of IEDs (subscribers).
- Sampled Values (SV)
-
Provides publisher-subscriber communication to transmit instantaneous power system data between merging units (MU) and IEDs within a substation over Ethernet. It is typically used to exchange sampled current and voltage measurements. The SV protocol runs over the data link layer of the OSI model and provides high-speed transmission of data samples encapsulated in multicast Ethernet frames.
Security concerns
Substation automation systems or other systems that use the IEC 61850 protocol allow interaction with external systems using standard IT networks. Thus, power networks are sensitive to the same vulnerabilities of IT systems.
IEC 61850 has several security flaws that can be used to compromise the system, leading to undesirable or even dangerous consequences. Since IEC 61850 offers powerful functions, using them maliciously can cause undesirable events to occur. This leads to creating complex access control levels, potentially reducing device security.
The GOOSE and SV protocols cannot authenticate a publisher and define their message types as plain-text messages. Additional latency through cryptography and message authentication is the main barrier to implementing these security mechanisms. While authentication is available in the MMS protocol, it is not widely supported and uses plain-text passwords.
Configuration example
This configuration uses the im_pcap module to dissect IEC 61850 network packets of various protocols of the IEC 61850 standard, such as MMS, GOOSE, and SV. Captured messages are then converted to JSON.
<Extension _json>
Module xm_json (1)
</Extension>
<Input pcap>
Module im_pcap
# Path to the file with capture packet data
File C:\...\example.pcap (2)
<Protocol> (3)
# Protocol type
Type iec61850iso
</Protocol>
<Protocol> (4)
# Protocol type
Type iec61850goose
</Protocol>
<Protocol> (5)
# Protocol type
Type iec61850gsem
</Protocol>
<Protocol> (6)
# Protocol type
Type iec61850sv
</Protocol>
<Protocol> (7)
# Protocol type
Type iec61850mms
</Protocol>
# Conversion to JSON
Exec to_json(); (8)
</Input>
1 | Load the xm_json module by creating an instance of it. |
2 | The File directive specifies the path to the file containing the captured network traffic. |
3 | Create an im_pcap Protocol group and set the Type directive to capture iec61850iso packets. |
4 | Create an im_pcap Protocol group and set the Type directive to capture iec61850goose packets. |
5 | Create an im_pcap Protocol group and set the Type directive to capture iec61850gsem packets. |
6 | Create an im_pcap Protocol group and set the Type directive to capture iec61850sv packets. |
7 | Create an im_pcap Protocol group and set the Type directive to capture iec61850mms packets. |
8 | The Exec directive is required for single statements. In this case, it facilitates calling the to_json() procedure for converting the captured messages to JSON. |
{
"iec61850-mms.APPID": "0xA135",
"iec61850-mms.confirmed_response_pdu.confirmed_service_response.read.list_of_access_result0.success.structure0.structure0.integer": "0",
"iec61850-mms.confirmed_response_pdu.confirmed_service_response.read.list_of_access_result0.success.structure0.structure1.floating_point": "0",
"iec61850-mms.confirmed_response_pdu.confirmed_service_response.read.list_of_access_result0.success.structure1.structure0.integer": "147",
"iec61850-mms.confirmed_response_pdu.confirmed_service_response.read.list_of_access_result0.success.structure1.structure1.floating_point": "134.150391",
"iec61850-mms.confirmed_response_pdu.confirmed_service_response.read.list_of_access_result0.success.structure2.integer": "0",
"iec61850-mms.confirmed_response_pdu.confirmed_service_response.read.list_of_access_result0.success.structure3.bit_string": "0000000000000",
"iec61850-mms.confirmed_response_pdu.confirmed_service_response.read.list_of_access_result0.success.structure4.utc_time": "2022-05-06 13:31:47.434555053",
"iec61850-mms.confirmed_response_pdu.invoke_id": "854",
"iec61850-mms.length": "514",
"iso8327.data": "{\"spdus\":[{\"give-token\":{\"spdu-identifier\":1,\"length-indicator\":0}},{\"data-transfer\":{\"spdu-identifier\":1,\"length-indicator\":0}}",
"iso8823.user_data.user_data": "1 (Fully-encoded-data)",
"iso8823.user_data.user_data.fully_encoded_data.items": "1",
"iso8823.user_data.user_data.fully_encoded_data.list.item.presentation_context_identifier": "3",
"iso8823.user_data.user_data.fully_encoded_data.list.item.presentation_data_values": "0",
"EventTime": "2022-05-06T16:31:50.346972+03:00",
"EventReceivedTime": "2022-05-06T17:04:26.350438+03:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"iec61850-goose.APPID": "0x2000",
"iec61850-goose.goose_pdu.all_data0.integer": "1",
"iec61850-goose.goose_pdu.all_data1.integer": "1",
"iec61850-goose.goose_pdu.all_data2.integer": "3",
"iec61850-goose.goose_pdu.all_data3.structure0.integer": "1",
"iec61850-goose.goose_pdu.all_data3.structure1.bit_string": "0000000000000",
"iec61850-goose.goose_pdu.all_data3.structure2.utc_time": "2022-05-06 13:05:14.391586303",
"iec61850-goose.goose_pdu.all_data4.structure0.integer": "2",
"iec61850-goose.goose_pdu.all_data4.structure1.bit_string": "0000000000000",
"iec61850-goose.goose_pdu.all_data4.structure2.utc_time": "2022-05-06 13:04:42.723617553",
"iec61850-goose.goose_pdu.all_data5.structure0.boolean": "true",
"iec61850-goose.goose_pdu.all_data5.structure1.bit_string": "0000000000000",
"iec61850-goose.goose_pdu.all_data5.structure2.utc_time": "2022-05-06 13:04:33.411117553",
"iec61850-goose.goose_pdu.all_data6.structure0.integer": "1",
"iec61850-goose.goose_pdu.all_data6.structure1.bit_string": "0000000000000",
"iec61850-goose.goose_pdu.all_data6.structure2.utc_time": "2022-05-06 13:06:32.758773803",
"iec61850-goose.goose_pdu.all_data7.structure0.boolean": "true",
"iec61850-goose.goose_pdu.all_data7.structure1.bit_string": "0000000000000",
"iec61850-goose.goose_pdu.all_data7.structure2.utc_time": "2022-05-06 13:04:10.559555053",
"iec61850-goose.goose_pdu.all_data8.structure0.boolean": "true",
"iec61850-goose.goose_pdu.all_data8.structure1.bit_string": "0000000000000",
"iec61850-goose.goose_pdu.all_data8.structure2.utc_time": "2022-05-06 13:04:18.543930053",
"iec61850-goose.goose_pdu.all_data9.structure0.boolean": "true",
"iec61850-goose.goose_pdu.all_data9.structure1.bit_string": "0000000000000",
"iec61850-goose.goose_pdu.all_data9.structure2.utc_time": "2022-05-06 13:04:26.676742553",
"iec61850-goose.goose_pdu.conf_rev": "1",
"iec61850-goose.goose_pdu.dat_set": "SGWDeviceA1/LLN0$LNStatusSet",
"iec61850-goose.goose_pdu.go_id": "GOOSEStatus",
"iec61850-goose.goose_pdu.gocb_ref": "SGWDeviceA1/LLN0$GO$gocbSTATUS",
"iec61850-goose.goose_pdu.nds_com": "false",
"iec61850-goose.goose_pdu.num_dat_set_entries": "10",
"iec61850-goose.goose_pdu.simulation": "true",
"iec61850-goose.goose_pdu.sq_num": "114",
"iec61850-goose.goose_pdu.st_num": "32",
"iec61850-goose.goose_pdu.t": "2022-05-06 13:06:32.758773803",
"iec61850-goose.goose_pdu.time_allowedto_live": "2000",
"iec61850-goose.length": "271",
"EventTime": "2022-05-06T16:08:20.811924+03:00",
"EventReceivedTime": "2022-05-06T16:38:35.286594+03:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"iec61850-sv.APPID": "0x4000",
"iec61850-sv.length": "108",
"iec61850-sv.sav_pdu.no_asdu": "1",
"iec61850-sv.sav_pdu.seq_asdu0.conf_rev": "1",
"iec61850-sv.sav_pdu.seq_asdu0.seq_data": "07228C9F00000000FE70B21A00000000FA6CC148000000000000000000000000005C872F00000000FFEBC5B700000000FFB7B31B000000000000000000000000",
"iec61850-sv.sav_pdu.seq_asdu0.smp_cnt": "2664",
"iec61850-sv.sav_pdu.seq_asdu0.smp_synch": "1",
"iec61850-sv.sav_pdu.seq_asdu0.sv_id": "TKVLMU0101",
"EventTime": "2022-05-06T16:32:32.248770+03:00",
"EventReceivedTime": "2022-05-06T17:11:39.443025+03:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
BACNet
BACnet is a communications protocol for building automation and control networks. It was designed to allow communication of building automation systems (BAS) for heating, ventilating, air-conditioning control, lighting control, access control, fire detection systems, and associated equipment. BACnet is an ASHRAE, ANSI, and ISO standard protocol that provides mechanisms for exchanging BAS information between devices from different manufacturers regardless of the particular service they perform.
BACnet is based on a four-layer architecture corresponding to the OSI model’s physical, data link, network, and application layers. It is a client/server protocol that defines a set of services used to communicate between building devices. The functions of any device within BACnet are defined as a collection of objects, such as Analog Input, Analog Output, Analog Value, Binary Input, Binary Output, Binary Value, Multi-State Input, Multi-State Output, Device, etc.
BACnet messages can be transmitted over the following network types:
-
Ethernet
-
ARCnet
-
Master-Slave/Token-Passing (MS/TP)
-
Point-to-Point (PTP)
-
LON
-
BACnet/IP
Security concerns
BACnet was designed without security requirements since it was originally planned to be used in systems operating in isolated networks without any external connection. As a result, traditional BACnet security relied on virtual separation, such as VPN access and VLAN, physical separation, and proprietary protocol solutions.
In addition to lacking built-in security functionality such as encryption, authentication, and authorization, BACnet/IP networks face issues of IT friendliness, i.e., unsecured UDP ports, BBMD broadcasts, dedicated static IP addresses, etc.
Configuration example
This configuration uses the im_pcap module to capture only BACnet packets from the network interface specified below. Captured messages are then converted to JSON.
<Extension _json>
Module xm_json (1)
</Extension>
<Input pcap_bacnet>
Module im_pcap
# Name of a network device/interface
Dev \Device\NPF_{E8451A5D-5676-4BEF-8ED5-68911C97D953} (2)
<Protocol> (3)
# Protocol type
Type bacnet
</Protocol>
# Conversion to JSON
Exec to_json(); (4)
</Input>
1 | Load the xm_json module by creating an instance of it. |
2 | Use the Dev directive of the im_pcap module for specifying the network interface. |
3 | Create a Protocol group and use the Type directive to specify which protocol im_pcap should be capturing. |
4 | The Exec directive is required for single statements. In this case, it facilitates calling the to_json() procedure for converting the captured messages to JSON. |
{
"bacnet.apdu.bacnet_confirmed_request.invoke_id": "159",
"bacnet.apdu.bacnet_confirmed_request.max_resp": "1476",
"bacnet.apdu.bacnet_confirmed_request.max_segs": "16",
"bacnet.apdu.bacnet_confirmed_request.more_segments_follow": "false",
"bacnet.apdu.bacnet_confirmed_request.segmented": "false",
"bacnet.apdu.bacnet_confirmed_request.segmented_accepted": "true",
"bacnet.apdu.bacnet_confirmed_request.service_choice": "Read Property (12)",
"bacnet.apdu.bacnet_confirmed_request.service_request.records.0.object_identifier.instance_number": "0",
"bacnet.apdu.bacnet_confirmed_request.service_request.records.0.object_identifier.type": "analog-input (0)",
"bacnet.apdu.bacnet_confirmed_request.service_request.records.1.property_identifier": "present-value (85)",
"bacnet.apdu.pdu_type": "BACnet-Confirmed-Request-PDU (0x00)",
"bacnet.bvlc.function": "Original-Unicast-NPDU (0x0A)",
"bacnet.bvlc.length": "27",
"bacnet.bvlc.type": "BACnet/IP (Annex J) (0x81)",
"bacnet.npdu.control": "0x0024",
"bacnet.npdu.control.contains": "BACnet APDU message (0)",
"bacnet.npdu.control.dst_spec": "DNET, DLEN, Hop Count present (1)",
"bacnet.npdu.control.prio": "Normal message",
"bacnet.npdu.control.reply_expected": "Yes (1)",
"bacnet.npdu.control.src_spec": "SNET, SLEN, SADR absent (0)",
"bacnet.npdu.version": "0x0001",
"EventTime": "2022-04-27T13:39:36.318342-07:00",
"EventReceivedTime": "2022-04-27T13:39:38.714328-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}
{
"bacnet.apdu.bacnet_complexack.more_segments_follow": "false",
"bacnet.apdu.bacnet_complexack.original_invoke_id": "159",
"bacnet.apdu.bacnet_complexack.segmented": "false",
"bacnet.apdu.bacnet_complexack.service_ack.records.0.object_identifier.instance_number": "0",
"bacnet.apdu.bacnet_complexack.service_ack.records.0.object_identifier.type": "analog-input (0)",
"bacnet.apdu.bacnet_complexack.service_ack.records.1.property_identifier": "present-value (85)",
"bacnet.apdu.bacnet_complexack.service_ack.records.2.records.0": "Opening Tag (3)",
"bacnet.apdu.bacnet_complexack.service_ack.records.2.records.1": "963000.125000",
"bacnet.apdu.bacnet_complexack.service_ack.records.2.records.2": "Closing Tag (3)",
"bacnet.apdu.bacnet_complexack.service_choice": "Read Property (12)",
"bacnet.apdu.pdu_type": "BACnet-Complex-ACK-PDU (0x03)",
"bacnet.bvlc.function": "Original-Unicast-NPDU (0x0A)",
"bacnet.bvlc.length": "32",
"bacnet.bvlc.type": "BACnet/IP (Annex J) (0x81)",
"bacnet.npdu.control": "0x0008",
"bacnet.npdu.control.contains": "BACnet APDU message (0)",
"bacnet.npdu.control.dst_spec": "DNET, DLEN, DADR, Hop Count absent (0)",
"bacnet.npdu.control.prio": "Normal message",
"bacnet.npdu.control.reply_expected": "No (0)",
"bacnet.npdu.control.src_spec": "SNET, SLEN, SADR present (1)",
"bacnet.npdu.version": "0x0001",
"EventTime": "2022-04-27T13:39:36.647469-07:00",
"EventReceivedTime": "2022-04-27T13:39:38.777825-07:00",
"SourceModuleName": "pcap",
"SourceModuleType": "im_pcap"
}