Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/misc/ibm_mq_enum.rb
19534 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::Tcp
8
include Msf::Auxiliary::Scanner
9
include Msf::Auxiliary::Report
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Identify Queue Manager Name and MQ Version',
16
'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.',
17
'Author' => [ 'Petros Koutroumpis' ],
18
'License' => MSF_LICENSE,
19
'Notes' => {
20
'Reliability' => UNKNOWN_RELIABILITY,
21
'Stability' => UNKNOWN_STABILITY,
22
'SideEffects' => UNKNOWN_SIDE_EFFECTS
23
}
24
)
25
)
26
register_options(
27
[
28
OptString.new('CHANNEL', [ true, "Channel to use", "SYSTEM.DEF.SVRCONN"]),
29
OptInt.new('CONCURRENCY', [true, "The number of concurrent ports to check per host", 10]),
30
OptInt.new('TIMEOUT', [true, "The socket connect timeout in seconds", 10]),
31
OptString.new('PORTS', [true, 'Ports to probe', '1414']),
32
33
]
34
)
35
deregister_options('RPORT')
36
end
37
38
def create_packet(channel_type)
39
chan = datastore['CHANNEL'] + "\x20" * (20 - datastore['CHANNEL'].length.to_i)
40
if channel_type == 0
41
chan_type = "\x26"
42
elsif channel_type == 1
43
chan_type = "\x07"
44
elsif channel_type == 2
45
chan_type = "\x08"
46
end
47
48
packet = "\x54\x53\x48\x20" + # StructID
49
"\x00\x00\x01\x0c" + # MQSegmLen
50
"\x02" + # ByteOrder
51
"\x01" + # SegmType
52
"\x01" + # CtlFlag1
53
"\x00" + # CtlFlag2
54
"\x00\x00\x00\x00\x00\x00\x00\x00" + # LUW Ident
55
"\x22\x02\x00\x00" + # Encoding
56
"\xb5\x01" + # CCSID
57
"\x00\x00" + # Reserved
58
"\x49\x44\x20\x20" + # StructId
59
"\x0d" + # FAP level
60
chan_type + # CapFlag1 - Message Type
61
"\x00" + # ECapFlag1
62
"\x00" + # IniErrFlg1
63
"\x00\x00" + # Reserved
64
"\x32\x00" + # MaxMsgBtch
65
"\xec\x7f\x00\x00" + # MaxTrSize
66
"\x00\x00\x40\x00" + # MaxMsgSize
67
"\xff\xc9\x9a\x3b" + # SeqWrapVal
68
chan + # Channel Name
69
"\x87" + # CapFlag2
70
"\x00" + # ECapFlag2
71
"\x5b\x01" + # ccsid
72
"QM1" + "\x20" * 45 + # Queue Manager Name
73
"\x2c\x01\x00\x00" + # HBInterval
74
"\x8a\x00" + # EFLLength
75
"\x00" + # IniErrFlg2
76
"\x55" + # Reserved1
77
"\x00\xff" + # HdrCprsLst
78
"\x00\xff\xff\xff\xff\xff\xff\xff\xff" + # MsgCprsLst1
79
"\xff\xff\xff\xff\xff\xff\xff" + # MsgCprsLst2
80
"\x00\x00" + # Reserved2
81
"\x00\x00\x00\x00" + # SSLKeyRst
82
"\x00\x00\x00\x00" + # ConvBySkt
83
"\x05" + # CapFlag3
84
"\x00" + # ECapFlag3
85
"\x00\x00" + # Reserved3
86
"\x10\x13\x00\x00" + # ProcessId
87
"\x01\x00\x00\x00" + # ThreadId
88
"\x01\x00\x00\x00" + # TraceId
89
"MQMM09000000" + # ProdId
90
"MQMID" + "\x20" * 43 + # MQM ID
91
"\x00\x00\xff\xff\xff\xff\xff\xff\xff" + # Unknown1
92
"\xff\xff\xff\xff\xff\xff\xff\xff\xff" + # Unknown2
93
"\xff\xff\x00\x00\x00\x00\x00\x00\x00" + # Unknown3
94
"\x00\x00\x00\x00\x00" # Unknown4
95
end
96
97
def run_host(ip)
98
chan = datastore['CHANNEL']
99
if chan.length > 20
100
print_error("Channel name must be less than 20 characters.")
101
raise Msf::OptionValidateError.new(['CHANNEL'])
102
end
103
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
104
while (ports.length > 0)
105
t = []
106
r = []
107
begin
108
1.upto(datastore['CONCURRENCY']) do
109
this_port = ports.shift
110
break if not this_port
111
112
t << framework.threads.spawn("Module(#{self.refname})-#{ip}:#{this_port}", false, this_port) do |port|
113
begin
114
data_recv = ""
115
3.times do |channel_type|
116
data_recv = send_packet(ip, port, channel_type)
117
if data_recv.nil?
118
next
119
end
120
# check if CHANNEL_WRONG_TYPE error received and retry with different type
121
if data_recv[data_recv.length - 4...data_recv.length] != "\x02\x00\x00\x00"
122
break
123
end
124
end
125
if data_recv.nil?
126
print_status("No response received. Try increasing TIMEOUT value.")
127
print_line
128
next
129
end
130
status_code = data_recv[-4..-1]
131
if status_code == "\x18\x00\x00\x00"
132
print_status("Channel Requires SSL. Could not get more information.")
133
print_line
134
end
135
if not data_recv[0...3].include?('TSH')
136
next
137
end
138
139
if status_code == "\x01\x00\x00\x00"
140
print_error('Channel "' + chan + '" does not exist.')
141
print_line
142
end
143
if status_code == "\x02\x00\x00\x00" or status_code == "\x06\x00\x00\x00"
144
print_error('Unsupported channel type. Try a different channel.')
145
print_line
146
end
147
if data_recv.length < 180
148
next
149
end
150
151
qm_name = data_recv[76...124].delete(' ')
152
mq_version = data_recv[180...188].scan(/../).collect { |x| x.to_i }.join('.')
153
print_good("#{ip}:#{port} - Queue Manager Name: #{qm_name} - MQ Version: #{mq_version}")
154
print_line
155
end
156
end
157
end
158
t.each { |x| x.join }
159
end
160
end
161
end
162
163
def send_packet(ip, port, channel_type)
164
begin
165
timeout = datastore['TIMEOUT'].to_i
166
packet = create_packet(channel_type)
167
s = connect(false,
168
{
169
'RPORT' => port,
170
'RHOST' => ip,
171
})
172
s.put(packet)
173
data = s.get_once(-1, timeout)
174
return data
175
rescue ::Rex::ConnectionRefused
176
print_error("#{ip}:#{port} - TCP Port Closed.")
177
print_line
178
rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error, Errno::ECONNRESET
179
print_error("#{ip}:#{port} - Connection Failed.")
180
print_line
181
rescue ::Interrupt
182
raise $!
183
ensure
184
if s
185
disconnect(s) rescue nil
186
end
187
end
188
end
189
190
end
191
192