CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

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