CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/modules/auxiliary/scanner/misc/ibm_mq_login.rb
Views: 1904
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary67include Msf::Exploit::Remote::Tcp8include Msf::Auxiliary::Scanner9include Msf::Auxiliary::Report1011def initialize12super(13'Name' => 'IBM WebSphere MQ Login Check',14'Description' => 'This module can be used to bruteforce usernames that can be used to connect to a queue manager. The name of a valid server-connection channel without SSL configured is required, as well as a list of usernames to try.',15'Author' => 'Petros Koutroumpis',16'License' => MSF_LICENSE17)18register_options([19Opt::RPORT(1414),20OptInt.new('TIMEOUT', [true, "The socket connect timeout in seconds", 5]),21OptInt.new('CONCURRENCY', [true, "The number of usernames to check concurrently", 10]),22OptString.new('QUEUE_MANAGER', [true, "Queue Manager name to use" ,""]),23OptString.new('CHANNEL', [true, "Channel to use" ,"SYSTEM.ADMIN.SVRCONN"]),24OptString.new('PASSWORD', [false, "Optional password to attempt with login"]),25OptPath.new('USERNAMES_FILE',26[ true, "The file that contains a list of usernames. UserIDs are case insensitive!"]27)])28#deregister_options('THREADS')29end3031def run_host(ip)32@usernames = []33if datastore['CHANNEL'].length.to_i > 2034print_error("Channel name cannot be more that 20 characters.")35exit36end37if datastore['QUEUE_MANAGER'].length.to_i > 4838print_error("Queue Manager name cannot be more that 48 characters.")39exit40end41begin42username_list43rescue ::Rex::ConnectionError44rescue ::Exception => e45print_error("#{e} #{e.backtrace}")46end47print_line48if(@usernames.empty?)49print_status("#{ip}:#{rport} No valid users found.")50else51print_good("#{ip}:#{rport} Valid usernames found: #{@usernames}")52report_note(53:host => rhost,54:port => rport,55:type => 'mq.usernames'56)57print_line58end59end6061def first_packet(channel,qm_name)62init1 = "\x54\x53\x48\x20" + # StructId63"\x00\x00\x01\x0c" + # MQSegmLen64"\x01" + # ByteOrder65"\x01" + # SegmType66"\x31" + # CtlFlag167"\x00" + # CtlFlag268"\x00\x00\x00\x00\x00\x00\x00\x00" +# LUW Ident69"\x00\x00\x01\x11" + # Encoding70"\x04\xb8" + # CCSID71"\x00\x00" + # Reserved72"\x49\x44\x20\x20" + # StructId73"\x0d" + # FAPLevel74"\x26" + # CapFlag175"\x00" + # ECapFlag176"\x00" + # InierrFlg177"\x00\x00" + # ReserveD78"\x00\x00" + # MaxMsgBtch79"\x00\x00\x7f\xec" + # MaxTrSize80"\x06\x40\x00\x00" + # MaxMsgSize81"\x00\x00\x00\x00" + # SeqWrapVal82channel + # Channel Name83"\x51" + # CapFlag284"\x00" + # ECapFlag285"\x04\xb8" + # ccsid86qm_name + # Queue Manager Name87"\x00\x00\x00\x01" + # HBInterval88"\x00\x8a" + # EFLLength89"\x00" + # IniErrFlg290"\x00" + # Reserved191"\x00\xff" + # HdrCprsLst92"\x00\xff\xff\xff\xff\xff\xff\xff" +# MsgCprsLst193"\xff\xff\xff\xff\xff\xff\xff\xff" +# MsgCprsLst294"\x00\x00" + # Reserved295"\x00\x00\x00\x00" + # SSLKeyRst96"\x00\x00\x00\x0a" + # ConvBySkt97"\x08" + # CapFlag398"\x00" + # ECapFlag399"\x00\x00" + # Reserved3100"\x00\x00\x00\x00" + # ProcessId101"\x00\x00\x00\x00" + # ThreadId102"\x00\x00\x00\x1b" + # TraceId103"MQMM09000000" + # ProdId104"MQMID" + "\x20"*43 + # MQM ID105"\x00\x01\x00\x00\xff\xff\xff\xff" +# Unknown1106"\xff\xff\xff\xff\xff\xff\xff\xff" +# Unknown2107"\xff\xff\xff\xff\xf1\x18\xa6\x93" +# Unknown3108"\x2b\x8a\x44\x3c\x67\x53\x73\x08" # Unknown4109end110111def second_packet(channel,qm_name)112init2 = "\x54\x53\x48\x4d" + # StructId113"\x00\x00\x00\xf4" + # MQSegmLen114"\x00\x00\x00\x01" + # Convers Id115"\x00\x00\x00\x00" + # Request Id116"\x02" + # ByteOrder117"\x01" + # SegmType118"\x31" + # CtlFlag1119"\x00" + # CtlFlag2120"\x00\x00\x00\x00\x00\x00\x00\x00" +# LUW Ident121"\x11\x01\x00\x00" + # Encoding122"\xb5\x01" + # CCSID123"\x00\x00" + # Reserved124"\x49\x44\x20\x20" + # StructId125"\x0c" + # FAPLevel126"\x26" + # CapFlag1127"\x00" + # ECapFlag1128"\x00" + # IniErrFlg1129"\x00\x00" + # Reserved130"\x00\x00" + # MaxMsgBtch131"\xec\x7f\x00\x00" + # MaxTrSize132"\x00\x00\x40\x00" + # MaxMsgSize133"\x00\x00\x00\x00" + # SeqWrapVal134channel + # Channel Name135"\x51" + # CapFlag2136"\x00" + # ECapFlag2137"\xb5\x01" + # ccsid138qm_name + # Queue Manager Name139"\x2c\x01\x00\x00" + # HBInterval140"\x8a\x00" + # EFLLength141"\x00" + # IniErrFlg2142"\x00" + # Reserved1143"\x00\xff" + # HdrCprsLst144"\x00\xff\xff\xff\xff\xff\xff" + # MsgCprsLst1145"\xff\xff\xff\xff\xff\xff\xff" + # MsgCprsLst2146"\xff\xff" + # MsgCprsLst3147"\x00\x00" + # Reserved2148"\x00\x00\x00\x00" + # SSLKeyRst149"\x0a\x00\x00\x00" + # ConvBySkt150"\x00" + # CapFlag3151"\x00" + # ECapFlag3152"\x00\x00" + # Reserved3153"\x00\x00\x00\x00" + # ProcessId154"\x00\x00\x00\x00" + # ThreadId155"\x1b\x00\x00\x00" + # TraceId156"MQMM09000000" + # ProdId157"MQMID" + "\x20"*43 # MQM ID158end159160def send_userid(userid,uname)161162if datastore['PASSWORD'].nil?163password = "\x00" * 12164else165password = datastore['PASSWORD']166if (password.length > 12)167print_warning("Passwords greater than 12 characters are unsupported. Truncating...")168password = password[0..12]169end170password = password + ( "\x00" * (12-password.length) )171end172vprint_status("Using password: '#{password}' (Length: #{password.length})")173174send_userid = "\x54\x53\x48\x4d" + # StructId175"\x00\x00\x00\xa8" + # MQSegmLen176"\x00\x00\x00\x01" + # Convers ID177"\x00\x00\x00\x00" + # Request ID178"\x02" + # Byte Order179"\x08" + # SegmType180"\x30" + # CtlFlag1181"\x00" + # CtlFlag2182"\x00\x00\x00\x00\x00\x00\x00\x00" +# LUW Ident183"\x11\x01\x00\x00" + # Encoding184"\xb5\x01" + # CCSID185"\x00\x00" + # Reserved186"\x55\x49\x44\x20" + # StructId187userid + # UserId - Doesnt affect anything188password + # Password189uname + # Long UID - This matters!190"\x00" + # SID Len191"\x00" * 39 # Unknown192end193194def start_conn(qm_name)195start_conn = "\x54\x53\x48\x4d" + # StructId196"\x00\x00\x01\x38" + # MQSegmLen197"\x00\x00\x00\x01" + # Convers ID198"\x00\x00\x00\x00" + # Request ID199"\x02" + # Byte Order200"\x81" + # SegmType201"\x30" + # CtlFlag1202"\x00" + # CtlFlag2203"\x00\x00\x00\x00\x00\x00\x00\x00" +# LUW Ident204"\x11\x01\x00\x00" + # Encoding205"\xb5\x01" + # CCSID206"\x00\x00" + # Reserved207"\x00\x00\x01\x38" + # Reply Len208"\x00\x00\x00\x00" + # Compl Code209"\x00\x00\x00\x00" + # Reason Code210"\x00\x00\x00\x00" + # Object Hdl211qm_name + # Queue Manager Name212"\x4d\x51\x20\x45\x78\x70\x6c" + # Appl Name213"\x6f\x72\x65\x72\x20\x39\x2e" + # Appl Name214"\x30\x2e\x30\x20\x20\x20\x20" + # Appl Name215"\x20\x20\x20\x20\x20\x20\x20" + # Appl Name216"\x1c\x00\x00\x00" + # ApplType217"\x00" * 32 + # AccntTok218"\x03\x00\x00\x00" + # MQCONNX219"\x00\x00\x00\x00" + # Options220"\x46\x43\x4e\x4f" + # Struct ID221"\x02\x00\x00\x00" + # Version222"\x00\x00\x00\x00" + # Option223"\x4d\x51\x4a\x42\x30\x39\x30" + # msgid224"\x30\x30\x30\x30\x34" + # msgid225"MQM" + "\x20" * 45 + # MqmId226"\x00" * 68 # Unknown227end228229def username_list230username_data = get_usernames231while (username_data.length > 0)232t = []233r = []234begin2351.upto(datastore['CONCURRENCY']) do236this_username = username_data.shift237if this_username.nil?238next239end240t << framework.threads.spawn("Module(#{self.refname})-#{rhost}:#{rport}", false, this_username) do |username|241connect242vprint_status "#{rhost}:#{rport} - Sending request for #{username}..."243channel = datastore['CHANNEL']244if channel.length > 20245print_error("Channel name must be less than 20 characters.")246next247end248channel += "\x20" * (20-channel.length.to_i) # max channel name length is 20249qm_name = datastore['QUEUE_MANAGER']250if qm_name.length > 48251print_error("Queue Manager name must be less than 48 characters.")252next253end254qm_name += "\x20" * (48-qm_name.length.to_i) # max queue manager name length is 48255if username.length > 12256print_error("Username must be less than 12 characters.")257next258end259uname = username + "\x20" * (64-username.length.to_i)260userid = username + "\x20" * (12 - username.length.to_i) # this doesnt make a difference261timeout = datastore['TIMEOUT'].to_i262s = connect(false,263{264'RPORT' => rport,265'RHOST' => rhost,266}267)268s.put(first_packet(channel,qm_name))269first_response = s.get_once(-1,timeout)270if first_response[-4..-1] == "\x00\x00\x00\x02" # CHANNEL_WRONG_TYPE code271print_error("Channel needs to be MQI type!")272next273end274s.put(second_packet(channel,qm_name))275second_response = s.get_once(-1,timeout)276s.put(send_userid(userid,uname))277s.put(start_conn(qm_name))278data = s.get_once(-1,timeout)279if data[41..44] == "\x00\x00\x00\x00"280print_status("Found username: #{username}")281@usernames << username282end283disconnect284end285end286t.each {|x| x.join }287end288end289end290291def get_usernames292if(! @common)293File.open(datastore['USERNAMES_FILE'], "rb") do |fd|294data = fd.read(fd.stat.size)295@common = data.split(/\n/).compact.uniq296end297end298@common299end300301end302303304