Path: blob/master/modules/auxiliary/scanner/misc/ibm_mq_enum.rb
19534 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::Scanner8include Msf::Auxiliary::Report910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Identify Queue Manager Name and MQ Version',15'Description' => 'Run this auxiliary against the listening port of an IBM MQ Queue Manager to identify its name and version. Any channel type can be used to get this information as long as the name of the channel is valid.',16'Author' => [ 'Petros Koutroumpis' ],17'License' => MSF_LICENSE,18'Notes' => {19'Reliability' => UNKNOWN_RELIABILITY,20'Stability' => UNKNOWN_STABILITY,21'SideEffects' => UNKNOWN_SIDE_EFFECTS22}23)24)25register_options(26[27OptString.new('CHANNEL', [ true, "Channel to use", "SYSTEM.DEF.SVRCONN"]),28OptInt.new('CONCURRENCY', [true, "The number of concurrent ports to check per host", 10]),29OptInt.new('TIMEOUT', [true, "The socket connect timeout in seconds", 10]),30OptString.new('PORTS', [true, 'Ports to probe', '1414']),3132]33)34deregister_options('RPORT')35end3637def create_packet(channel_type)38chan = datastore['CHANNEL'] + "\x20" * (20 - datastore['CHANNEL'].length.to_i)39if channel_type == 040chan_type = "\x26"41elsif channel_type == 142chan_type = "\x07"43elsif channel_type == 244chan_type = "\x08"45end4647packet = "\x54\x53\x48\x20" + # StructID48"\x00\x00\x01\x0c" + # MQSegmLen49"\x02" + # ByteOrder50"\x01" + # SegmType51"\x01" + # CtlFlag152"\x00" + # CtlFlag253"\x00\x00\x00\x00\x00\x00\x00\x00" + # LUW Ident54"\x22\x02\x00\x00" + # Encoding55"\xb5\x01" + # CCSID56"\x00\x00" + # Reserved57"\x49\x44\x20\x20" + # StructId58"\x0d" + # FAP level59chan_type + # CapFlag1 - Message Type60"\x00" + # ECapFlag161"\x00" + # IniErrFlg162"\x00\x00" + # Reserved63"\x32\x00" + # MaxMsgBtch64"\xec\x7f\x00\x00" + # MaxTrSize65"\x00\x00\x40\x00" + # MaxMsgSize66"\xff\xc9\x9a\x3b" + # SeqWrapVal67chan + # Channel Name68"\x87" + # CapFlag269"\x00" + # ECapFlag270"\x5b\x01" + # ccsid71"QM1" + "\x20" * 45 + # Queue Manager Name72"\x2c\x01\x00\x00" + # HBInterval73"\x8a\x00" + # EFLLength74"\x00" + # IniErrFlg275"\x55" + # Reserved176"\x00\xff" + # HdrCprsLst77"\x00\xff\xff\xff\xff\xff\xff\xff\xff" + # MsgCprsLst178"\xff\xff\xff\xff\xff\xff\xff" + # MsgCprsLst279"\x00\x00" + # Reserved280"\x00\x00\x00\x00" + # SSLKeyRst81"\x00\x00\x00\x00" + # ConvBySkt82"\x05" + # CapFlag383"\x00" + # ECapFlag384"\x00\x00" + # Reserved385"\x10\x13\x00\x00" + # ProcessId86"\x01\x00\x00\x00" + # ThreadId87"\x01\x00\x00\x00" + # TraceId88"MQMM09000000" + # ProdId89"MQMID" + "\x20" * 43 + # MQM ID90"\x00\x00\xff\xff\xff\xff\xff\xff\xff" + # Unknown191"\xff\xff\xff\xff\xff\xff\xff\xff\xff" + # Unknown292"\xff\xff\x00\x00\x00\x00\x00\x00\x00" + # Unknown393"\x00\x00\x00\x00\x00" # Unknown494end9596def run_host(ip)97chan = datastore['CHANNEL']98if chan.length > 2099print_error("Channel name must be less than 20 characters.")100raise Msf::OptionValidateError.new(['CHANNEL'])101end102ports = Rex::Socket.portspec_crack(datastore['PORTS'])103while (ports.length > 0)104t = []105r = []106begin1071.upto(datastore['CONCURRENCY']) do108this_port = ports.shift109break if not this_port110111t << framework.threads.spawn("Module(#{self.refname})-#{ip}:#{this_port}", false, this_port) do |port|112begin113data_recv = ""1143.times do |channel_type|115data_recv = send_packet(ip, port, channel_type)116if data_recv.nil?117next118end119# check if CHANNEL_WRONG_TYPE error received and retry with different type120if data_recv[data_recv.length - 4...data_recv.length] != "\x02\x00\x00\x00"121break122end123end124if data_recv.nil?125print_status("No response received. Try increasing TIMEOUT value.")126print_line127next128end129status_code = data_recv[-4..-1]130if status_code == "\x18\x00\x00\x00"131print_status("Channel Requires SSL. Could not get more information.")132print_line133end134if not data_recv[0...3].include?('TSH')135next136end137138if status_code == "\x01\x00\x00\x00"139print_error('Channel "' + chan + '" does not exist.')140print_line141end142if status_code == "\x02\x00\x00\x00" or status_code == "\x06\x00\x00\x00"143print_error('Unsupported channel type. Try a different channel.')144print_line145end146if data_recv.length < 180147next148end149150qm_name = data_recv[76...124].delete(' ')151mq_version = data_recv[180...188].scan(/../).collect { |x| x.to_i }.join('.')152print_good("#{ip}:#{port} - Queue Manager Name: #{qm_name} - MQ Version: #{mq_version}")153print_line154end155end156end157t.each { |x| x.join }158end159end160end161162def send_packet(ip, port, channel_type)163begin164timeout = datastore['TIMEOUT'].to_i165packet = create_packet(channel_type)166s = connect(false,167{168'RPORT' => port,169'RHOST' => ip,170})171s.put(packet)172data = s.get_once(-1, timeout)173return data174rescue ::Rex::ConnectionRefused175print_error("#{ip}:#{port} - TCP Port Closed.")176print_line177rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error, Errno::ECONNRESET178print_error("#{ip}:#{port} - Connection Failed.")179print_line180rescue ::Interrupt181raise $!182ensure183if s184disconnect(s) rescue nil185end186end187end188189end190191192