Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/windows/gather/enum_db.rb
19721 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::Post
7
include Msf::Post::File
8
include Msf::Post::Windows::Registry
9
include Msf::Auxiliary::Report
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'Windows Gather Database Instance Enumeration',
16
'Description' => %q{This module will enumerate a Windows system for installed database instances.},
17
'License' => MSF_LICENSE,
18
'Author' => [
19
'Barry Shteiman <barry[at]sectorix.com>', # Module author
20
'juan vazquez' # minor help
21
],
22
'Platform' => [ 'win' ],
23
'SessionTypes' => [ 'meterpreter' ],
24
'Notes' => {
25
'Stability' => [CRASH_SAFE],
26
'SideEffects' => [],
27
'Reliability' => []
28
},
29
'Compat' => {
30
'Meterpreter' => {
31
'Commands' => %w[
32
stdapi_fs_search
33
stdapi_sys_config_getenv
34
]
35
}
36
}
37
)
38
)
39
end
40
41
def run
42
hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']
43
print_status("Enumerating databases on #{hostname} (#{session.session_host})")
44
45
results = []
46
if check_mssql
47
results += enumerate_mssql
48
end
49
if check_oracle
50
results += enumerate_oracle
51
end
52
if check_db2
53
results += enumerate_db2
54
end
55
if check_mysql
56
results += enumerate_mysql
57
end
58
if check_sybase
59
results += enumerate_sybase
60
end
61
62
if results.empty?
63
print_status('Done, no databases were found')
64
return
65
end
66
67
print_status("Done, #{results.length} databases found.")
68
69
tbl = Rex::Text::Table.new(
70
'Header' => 'Installed Databases',
71
'Indent' => 1,
72
'Columns' =>
73
[
74
'Type',
75
'Instance',
76
'Database',
77
'Port'
78
]
79
)
80
81
results.each do |r|
82
report_service(host: session.sock.peerhost, port: r[3], name: r[0], info: "#{r[0]}, #{r[1]}")
83
tbl << r
84
end
85
86
print_line(tbl.to_s)
87
p = store_loot('host.databases', 'text/plain', session, tbl.to_s, 'databases.txt', 'Running Databases')
88
print_good("Results stored in: #{p}")
89
end
90
91
##### initial identification methods #####
92
93
# Check if MSSQL database instances are installed on host
94
def check_mssql
95
if registry_enumkeys('HKLM\\SOFTWARE\\Microsoft').include?('Microsoft SQL Server')
96
print_status("\tMicrosoft SQL Server found.")
97
return true
98
end
99
100
return false
101
rescue StandardError
102
return false
103
end
104
105
# Check if Oracle database instances are installed on host
106
def check_oracle
107
keys = registry_enumkeys('HKLM\\SOFTWARE\\Oracle')
108
109
if keys.include?('ALL_HOMES')
110
print_status("\tOracle Server found.")
111
return true
112
end
113
114
if keys.include?('SYSMAN')
115
print_status("\tOracle Server found.")
116
return true
117
end
118
119
if keys.include?('KEY_XE')
120
print_status("\tOracle Server found.")
121
return true
122
end
123
124
return false
125
rescue StandardError
126
return false
127
end
128
129
# Check if DB2 database instances are installed on host
130
def check_db2
131
if registry_enumkeys('HKLM\\SOFTWARE\\IBM\\DB2').include?('GLOBAL_PROFILE')
132
print_status("\tDB2 Server found.")
133
return true
134
end
135
136
return false
137
rescue StandardError
138
return false
139
end
140
141
# Check if MySQL database instances are installed on host
142
def check_mysql
143
if registry_enumkeys('HKLM\\SOFTWARE').include?('MySQL AB')
144
print_status("\tMySQL Server found.")
145
return true
146
end
147
return false
148
rescue StandardError
149
return false
150
end
151
152
# Check if Sybase database instances are installed on host
153
def check_sybase
154
keys = registry_enumkeys('HKLM\\SOFTWARE\\Sybase')
155
156
if keys.include?('SQLServer')
157
print_status("\tSybase Server found.")
158
return true
159
end
160
161
if keys.include?('Server')
162
print_status("\tSybase Server found.")
163
return true
164
end
165
166
return false
167
rescue StandardError
168
return false
169
end
170
171
##### deep analysis methods #####
172
173
# method to identify MSSQL instances
174
def enumerate_mssql
175
results = []
176
key = 'HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\Instance Names\\SQL'
177
instances = registry_enumvals(key)
178
179
return results if instances.blank?
180
181
instances.each do |i|
182
tcpkey = "HKLM\\SOFTWARE\\Microsoft\\Microsoft SQL Server\\#{registry_getvaldata(key, i)}\\MSSQLServer\\SuperSocketNetLib\\Tcp\\IPAll"
183
tcpport = registry_getvaldata(tcpkey, 'TcpPort')
184
print_good("\t\t+ #{registry_getvaldata(key, i)} (Port:#{tcpport})")
185
results << ['mssql', "instance:#{registry_getvaldata(key, i)} port:#{tcpport}", 'Microsoft SQL Server', tcpport]
186
end
187
188
results
189
rescue StandardError
190
print_error("\t\t! could not identify information")
191
return results || []
192
end
193
194
# method to identify oracle instances
195
def enumerate_oracle
196
results = []
197
found_key = false
198
basekey_set = ['HKLM\\SOFTWARE\\Oracle\\SYSMAN', 'HKLM\\SOFTWARE\\ORACLE\\KEY_XE']
199
basekey_set.each do |basekey|
200
next if found_key
201
202
instances = registry_enumkeys(basekey)
203
204
next if instances.blank?
205
206
found_key = true
207
208
instances.each do |i|
209
if basekey.include? 'KEY_XE'
210
oracle_sid = registry_getvaldata(basekey, 'ORACLE_SID')
211
oracle_home = registry_getvaldata(basekey, 'ORACLE_HOME')
212
else
213
key = "#{basekey}\\#{i}"
214
oracle_sid = registry_getvaldata(key, 'ORACLE_SID')
215
oracle_home = registry_getvaldata(key, 'ORACLE_HOME')
216
end
217
218
if !exist?(oracle_home + '\\NETWORK\\ADMIN\\tnsnames.ora')
219
print_error("\t\t! #{oracle_sid} (No Listener Found)")
220
next
221
end
222
223
data_tnsnames = read_file(oracle_home + '\\NETWORK\\ADMIN\\tnsnames.ora')
224
if data_tnsnames =~ /PORT\ =\ (\d+)/
225
port = ::Regexp.last_match(1)
226
print_good("\t\t+ #{oracle_sid} (Port:#{port})")
227
results << [ 'oracle', "instance:#{oracle_sid} port:#{port}", 'Oracle Database Server', port ]
228
else
229
print_error("\t\t! #{oracle_sid} (No Listener Found)")
230
end
231
end
232
end
233
234
if !found_key
235
print_error("\t\t! Oracle instances not found")
236
end
237
238
results
239
rescue StandardError
240
print_error("\t\t! could not identify information")
241
return results || []
242
end
243
244
# method to identify mysql instances
245
def enumerate_mysql
246
results = []
247
basekey = 'HKLM\\SOFTWARE\\MySQL AB'
248
instances = registry_enumkeys(basekey)
249
250
return results if instances.blank?
251
252
instances.each do |i|
253
key = "#{basekey}\\#{i}"
254
location = registry_getvaldata(key, 'Location')
255
256
data = read_mysql_conf(location)
257
if data.nil?
258
data = find_and_read_mysql_conf
259
end
260
261
if data && data =~ (/port=(\d+)/)
262
port = ::Regexp.last_match(1)
263
print_good("\t\t+ MYSQL (Port:#{port})")
264
results << ['mysql', "instance:MYSQL port:#{port}", 'MySQL Server', port]
265
else
266
print_error("\t\t! could not identify information")
267
end
268
end
269
270
results
271
rescue StandardError
272
print_error("\t\t! could not identify information")
273
return results || []
274
end
275
276
# method to identify sybase instances
277
def enumerate_sybase
278
basekey = 'HKLM\\SOFTWARE\\Sybase\\SQLServer'
279
instance = registry_getvaldata(basekey, 'DSLISTEN')
280
location = registry_getvaldata(basekey, 'RootDir')
281
results = []
282
283
if !exist?(location + '\\ini\\sql.ini')
284
print_error("\t\t! could not locate configuration file.")
285
return results
286
end
287
288
data = read_file(location + '\\ini\\sql.ini')
289
if data =~ /\[#{instance}\]([^\[]*)/
290
segment = ::Regexp.last_match(1)
291
else
292
print_error("\t\t! could not locate information.")
293
return results
294
end
295
296
if segment =~ /master=\w+,[^,]+,(\d+)/
297
port = ::Regexp.last_match(1)
298
else
299
print_error("\t\t! could not locate information.")
300
return results
301
end
302
303
print_good("\t\t+ #{instance} (Port:#{port})")
304
results << [ 'sybase', "instance:#{instance} port:#{port}", 'Sybase SQL Server', port ]
305
return results
306
rescue StandardError
307
print_error("\t\t! could not locate information.")
308
return results || []
309
end
310
311
# method to identify db2 instances
312
def enumerate_db2
313
results = []
314
cmd_i = cmd_exec('db2cmd', '-i -w /c db2ilist')
315
cmd_p = cmd_exec('db2cmd', '-i -w /c db2 get dbm cfg')
316
if cmd_p =~ %r{\ ?TCP/IP\ Service\ name\ +\(SVCENAME\)\ =\ (\w+)}
317
port = ::Regexp.last_match(1)
318
else
319
print_error("\t\t! could not identify instances information")
320
return results
321
end
322
323
windir = session.sys.config.getenv('windir')
324
getfile = session.fs.file.search(windir + '\\system32\\drivers\\etc\\', 'services.*', true, -1)
325
326
data = nil
327
getfile.each do |file|
328
if exist?("#{file['path']}\\#{file['name']}")
329
data = read_file("#{file['path']}\\#{file['name']}")
330
break if !data.nil?
331
end
332
end
333
334
if data && data =~ (/#{port}[\ \t]+(\d+)/)
335
port_t = ::Regexp.last_match(1)
336
else
337
print_error("\t\t! could not identify instances information")
338
return results
339
end
340
341
cmd_i.split("\n").compact.each do |line|
342
stripped = line.strip
343
print_good("\t\t+ #{stripped} (Port:#{port_t})")
344
results << [ 'db2', "instance:#{stripped} port:#{port_t}", 'DB2 Server', port_t ]
345
end
346
347
results
348
rescue StandardError
349
print_error("\t\t! could not identify instances information")
350
return results || []
351
end
352
353
##### helper methods #####
354
355
def read_mysql_conf(location)
356
return unless location
357
358
if exist?(location + '\\my.ini')
359
return read_file(location + '\\my.ini')
360
end
361
362
if exist?(location + '\\my.cnf')
363
return read_file(location + '\\my.cnf')
364
end
365
366
nil
367
end
368
369
def find_and_read_mysql_conf
370
sysdriv = session.sys.config.getenv('SYSTEMDRIVE')
371
getfile = session.fs.file.search(sysdriv + '\\', 'my.ini', true, -1)
372
getfile.each do |file|
373
path = "#{file['path']}\\#{file['name']}"
374
if exist?(path)
375
return read_file(path)
376
end
377
end
378
379
nil
380
end
381
end
382
383